import React, { useState, useRef, useEffect } from 'react'; import { Card, CardContent } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { MediaModal } from '@/components/MediaModal'; import { AnimatedAvatar } from '@/components/AnimatedAvatar'; import { Users, Circle, Upload, File, ImageIcon, Video, Music, FileText, Download, Play, Pause, Trash2 } from 'lucide-react'; interface ActiveUser { id: string; name: string; color: string; lastSeen: Date; isTyping?: boolean; currentLine?: number; } interface MediaFile { id: string; name: string; type: string; size: number; url: string; uploadedAt: Date; uploadedBy: string; } interface LeftPanelProps { isVisible: boolean; className?: string; users?: ActiveUser[]; currentUser?: ActiveUser | null; mediaFiles?: MediaFile[]; onFileUpload?: (files: FileList) => void; onFileDelete?: (fileId: string) => void; onModalStateChange?: (isOpen: boolean) => void; } export const LeftPanel: React.FC = ({ isVisible, users = [], currentUser, mediaFiles = [], onFileDelete, onModalStateChange }) => { const [activeUsers, setActiveUsers] = useState(users); const [localMediaFiles, setLocalMediaFiles] = useState(mediaFiles); const [usersScrollState, setUsersScrollState] = useState({ top: false, bottom: false }); const [mediaScrollState, setMediaScrollState] = useState({ top: false, bottom: false }); const usersScrollRef = useRef(null); const mediaScrollRef = useRef(null); // Update local state when props change useEffect(() => { setActiveUsers(users); }, [users]); // Scroll detection function const handleScroll = (element: HTMLDivElement | null, setState: (state: { top: boolean; bottom: boolean }) => void) => { if (!element) return; const { scrollTop, scrollHeight, clientHeight } = element; const isScrolledFromTop = scrollTop > 5; const isScrolledFromBottom = scrollTop < scrollHeight - clientHeight - 5; setState({ top: isScrolledFromTop, bottom: isScrolledFromBottom && scrollHeight > clientHeight }); }; // Add scroll listeners useEffect(() => { const usersElement = usersScrollRef.current; const mediaElement = mediaScrollRef.current; const handleUsersScroll = () => handleScroll(usersElement, setUsersScrollState); const handleMediaScroll = () => handleScroll(mediaElement, setMediaScrollState); if (usersElement) { usersElement.addEventListener('scroll', handleUsersScroll); // Initial check handleUsersScroll(); } if (mediaElement) { mediaElement.addEventListener('scroll', handleMediaScroll); // Initial check handleMediaScroll(); } return () => { if (usersElement) usersElement.removeEventListener('scroll', handleUsersScroll); if (mediaElement) mediaElement.removeEventListener('scroll', handleMediaScroll); }; }, [activeUsers, localMediaFiles]); useEffect(() => { setLocalMediaFiles(mediaFiles); }, [mediaFiles]); const [playingAudio, setPlayingAudio] = useState(null); const [modalFile, setModalFile] = useState(null); const [audioProgress, setAudioProgress] = useState<{ [key: string]: { currentTime: number; duration: number } }>({}); const audioRefs = useRef<{ [key: string]: HTMLAudioElement }>({}); // Helper function to get the correct file URL using HTTP server const getFileUrl = (file: MediaFile) => { const httpUrl = process.env.NEXT_PUBLIC_HTTP_URL || 'http://localhost:8081'; return file.url.startsWith('http') ? file.url : `${httpUrl}${file.url}`; }; // Helper function to handle modal state changes const handleModalChange = (file: MediaFile | null) => { setModalFile(file); if (onModalStateChange) { onModalStateChange(file !== null); } }; // Users Panel Functions const getStatusIndicator = (user: ActiveUser) => { const timeDiff = Date.now() - user.lastSeen.getTime(); if (timeDiff < 60000) { // Less than 1 minute return { status: 'online', color: 'rgb(184, 187, 38)' }; // success color } else if (timeDiff < 300000) { // Less than 5 minutes return { status: 'away', color: 'rgb(250, 189, 47)' }; // warning color } else { return { status: 'offline', color: 'rgb(146, 131, 116)' }; // muted color } }; const formatLastSeen = (date: Date) => { const timeDiff = Date.now() - date.getTime(); if (timeDiff < 60000) { return 'Just now'; } else if (timeDiff < 3600000) { const minutes = Math.floor(timeDiff / 60000); return `${minutes}m ago`; } else { const hours = Math.floor(timeDiff / 3600000); return `${hours}h ago`; } }; // Media Panel Functions const formatFileSize = (bytes: number) => { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; }; const formatTimeAgo = (date: Date) => { const timeDiff = Date.now() - date.getTime(); if (timeDiff < 60000) { return 'Just now'; } else if (timeDiff < 3600000) { const minutes = Math.floor(timeDiff / 60000); return `${minutes}m ago`; } else { const hours = Math.floor(timeDiff / 3600000); return `${hours}h ago`; } }; const getFileIcon = (type: string) => { if (type.startsWith('image/')) return ; if (type.startsWith('video/')) return