diff --git a/frontend/src/components/FileExplorer.tsx b/frontend/src/components/FileExplorer.tsx index 5b276e7..7ae5e84 100644 --- a/frontend/src/components/FileExplorer.tsx +++ b/frontend/src/components/FileExplorer.tsx @@ -247,6 +247,28 @@ export default function FileExplorer({ onLogout }: FileExplorerProps) { const [sortAsc, setSortAsc] = useState(true); const [draggedFile, setDraggedFile] = useState(null); const [uploads, setUploads] = useState([]); + const uploadsRef = useRef([]); + useEffect(() => { + uploadsRef.current = uploads; + }, [uploads]); + + const [uploadSpeed, setUploadSpeed] = useState(0); + const prevUploadBytesRef = useRef(0); + + useEffect(() => { + const timer = setInterval(() => { + const currentBytes = uploadsRef.current.reduce((acc, u) => acc + u.uploadedBytes, 0); + const diff = currentBytes - prevUploadBytesRef.current; + setUploadSpeed(diff > 0 ? diff : 0); + prevUploadBytesRef.current = currentBytes; + }, 1000); + return () => clearInterval(timer); + }, []); + + const formatSpeed = (bytesPerSec: number) => { + const mbps = (bytesPerSec * 8) / 1000000; + return ` (${mbps.toFixed(1)} Mbps)`; + }; const [toasts, setToasts] = useState([]); const [deleteConfirm, setDeleteConfirm] = useState<{ type: 'single' | 'multiple'; file?: FileItem; count?: number } | null>(null); const [conflictState, setConflictState] = useState<{ @@ -2066,7 +2088,7 @@ export default function FileExplorer({ onLogout }: FileExplorerProps) { {uploads.filter(u => u.status === 'uploading').length > 0 - ? `Uploading ${uploads.filter(u => u.status === 'uploading').length} file${uploads.filter(u => u.status === 'uploading').length > 1 ? 's' : ''}` + ? `Uploading ${uploads.filter(u => u.status === 'uploading').length} file${uploads.filter(u => u.status === 'uploading').length > 1 ? 's' : ''}${formatSpeed(uploadSpeed)}` : 'Uploads complete'}