import React, { useState, useRef, useCallback, useEffect } from 'react'; import { Upload, LogOut, FileText, Clock, ChevronLeft, ChevronRight, MousePointerClick, FileUp, ClipboardPaste, Loader2 } from 'lucide-react'; import { useAuth } from '../contexts/AuthContext'; import { useLanguage } from '../contexts/LanguageContext'; import { FileRecord } from '../types'; interface LeftSidebarProps { files: FileRecord[]; selectedFileId: string | null; onFileSelect: (fileId: string) => void; onUploadClick: () => void; canUploadAnonymously: boolean; onRequireAuth: () => void; isCollapsed: boolean; onToggleCollapse: () => void; onUploadFiles: (files: File[]) => void; hasMore: boolean; loadingMore: boolean; onLoadMore: () => void; historyEnabled: boolean; onToggleHistory: () => void; } export default function LeftSidebar({ files, selectedFileId, onFileSelect, onUploadClick, canUploadAnonymously, onRequireAuth, isCollapsed, onToggleCollapse, onUploadFiles, hasMore, loadingMore, onLoadMore, historyEnabled, onToggleHistory, }: LeftSidebarProps) { const { user, signOut } = useAuth(); const { t } = useLanguage(); const [isDragging, setIsDragging] = useState(false); const fileInputRef = useRef(null); const listRef = useRef(null); const displayName = user?.username?.trim() || user?.email || ''; // Handle scroll to load more const handleScroll = useCallback(() => { if (!listRef.current || loadingMore || !hasMore) return; const { scrollTop, scrollHeight, clientHeight } = listRef.current; // Trigger load more when scrolled to bottom (with 50px threshold) if (scrollHeight - scrollTop - clientHeight < 50) { onLoadMore(); } }, [loadingMore, hasMore, onLoadMore]); // Auto-load more if content doesn't fill the container useEffect(() => { if (!hasMore || loadingMore || !user || files.length === 0) return; // Use requestAnimationFrame to ensure DOM has been updated const checkAndLoadMore = () => { requestAnimationFrame(() => { if (!listRef.current) return; const { scrollHeight, clientHeight } = listRef.current; // If content doesn't fill container and there's more data, load more if (scrollHeight <= clientHeight && hasMore && !loadingMore) { onLoadMore(); } }); }; // Small delay to ensure DOM is fully rendered const timer = setTimeout(checkAndLoadMore, 100); return () => clearTimeout(timer); }, [files.length, hasMore, loadingMore, onLoadMore, user]); const handleDragOver = (e: React.DragEvent) => { e.preventDefault(); setIsDragging(true); }; const handleDragLeave = (e: React.DragEvent) => { e.preventDefault(); setIsDragging(false); }; const handleDrop = (e: React.DragEvent) => { e.preventDefault(); if (!user && !canUploadAnonymously) { onRequireAuth(); return; } setIsDragging(false); const droppedFiles = Array.from(e.dataTransfer.files); const validFiles = droppedFiles.filter(file => file.type.startsWith('image/') || file.type === 'application/pdf' ); if (validFiles.length > 0) { onUploadFiles(validFiles); } }; const handleFileChange = (e: React.ChangeEvent) => { if (!user && !canUploadAnonymously) { onRequireAuth(); return; } if (e.target.files && e.target.files.length > 0) { onUploadFiles(Array.from(e.target.files)); } // Reset input if (fileInputRef.current) { fileInputRef.current.value = ''; } }; if (isCollapsed) { return (
); } return ( <>
{/* Top Area: Title & Upload */}

{t.sidebar.title}

{t.sidebar.subtitle}

{/* Middle Area: History */} {/* Bottom Area: User info (only shown when logged in) */} {user && (

{displayName}

)}
); }