import React, { useState, useEffect, useMemo } from 'react'; import { useToast } from '@/components/feedback/ToastProvider'; import { FileDetailsView } from '@/components/views/FileDetailsView'; import { AutoMetadataDetectionModal } from '@/components/library/AutoMetadataDetectionModal'; import { WatermarkSettingsModal } from '@/components/library/WatermarkSettingsModal'; import { storageService } from '@/services/storageService'; import { logger } from '@/utils/logger'; import { FileToolbar } from './FileToolbar'; import { FileTable } from './FileTable'; import { FileGrid } from './FileGrid'; import { CloudFileBrowserSkeleton } from './CloudFileBrowserSkeleton'; import type { CloudFileNode, SortField, SortOrder, ViewMode } from './types'; import { FILE_BROWSER_DEFAULT_TAGS } from './types'; export const CloudFileBrowser: React.FC = () => { const { addToast } = useToast(); const [viewMode, setViewMode] = useState('list'); const [searchQuery, setSearchQuery] = useState(''); const [selectedFiles, setSelectedFiles] = useState([]); const [, setCurrentFolder] = useState('Root'); const [files, setFiles] = useState([]); const [loading, setLoading] = useState(true); const [selectedFileId, setSelectedFileId] = useState(null); const [sortField, setSortField] = useState('modified'); const [sortOrder, setSortOrder] = useState('desc'); const [activeTags, setActiveTags] = useState([]); const [showMetadataModal, setShowMetadataModal] = useState(false); const [showWatermarkModal, setShowWatermarkModal] = useState(false); useEffect(() => { const loadFiles = async () => { setLoading(true); try { const data = await storageService.listFiles(); setFiles(data); } catch (e) { logger.error('Error loading files', { error: e instanceof Error ? e.message : String(e), stack: e instanceof Error ? e.stack : undefined, }); } finally { setLoading(false); } }; loadFiles(); }, []); const filteredFiles = useMemo(() => { return files .filter((f) => f.name.toLowerCase().includes(searchQuery.toLowerCase())) .filter( (f) => activeTags.length === 0 || f.tags?.some((t) => activeTags.includes(t)) ) .sort((a, b) => { let valA: string | number = a[sortField] ?? ''; let valB: string | number = b[sortField] ?? ''; if (sortField === 'size') { valA = parseInt(String(a.size || '0'), 10) || 0; valB = parseInt(String(b.size || '0'), 10) || 0; } if (valA < valB) return sortOrder === 'asc' ? -1 : 1; if (valA > valB) return sortOrder === 'asc' ? 1 : -1; return 0; }); }, [files, searchQuery, activeTags, sortField, sortOrder]); const handleSort = (field: SortField) => { setSortField((prev) => { if (prev === field) { setSortOrder((o) => (o === 'asc' ? 'desc' : 'asc')); return prev; } setSortOrder('asc'); return field; }); }; const toggleTag = (tag: string) => { setActiveTags((prev) => prev.includes(tag) ? prev.filter((t) => t !== tag) : [...prev, tag] ); }; const toggleSelection = (id: string) => { setSelectedFiles((prev) => prev.includes(id) ? prev.filter((f) => f !== id) : [...prev, id] ); }; const selectAll = () => { if (selectedFiles.length === filteredFiles.length) setSelectedFiles([]); else setSelectedFiles(filteredFiles.map((f) => f.id)); }; const handleFileClick = (file: CloudFileNode) => { if (file.type === 'folder') { setCurrentFolder(file.name); addToast(`Navigated to ${file.name}`, 'info'); } else { setSelectedFileId(file.id); } }; const handleBulkAction = (action: string) => { if (selectedFiles.length === 0) return; addToast(`${action} ${selectedFiles.length} items`, 'success'); setSelectedFiles([]); }; if (selectedFileId) { return ( setSelectedFileId(null)} /> ); } if (loading) { return ; } return (
setSortOrder((o) => (o === 'asc' ? 'desc' : 'asc')) } viewMode={viewMode} onViewModeChange={setViewMode} selectedCount={selectedFiles.length} onBulkDownload={() => handleBulkAction('Downloaded')} onBulkTag={() => handleBulkAction('Tagged')} onBulkDelete={() => handleBulkAction('Deleted')} onMetadataClick={() => setShowMetadataModal(true)} onWatermarkClick={() => setShowWatermarkModal(true)} availableTags={FILE_BROWSER_DEFAULT_TAGS} />
{viewMode === 'list' ? ( { if (action === 'ai') addToast('Sent to AI Tools'); }} /> ) : ( )}
{showMetadataModal && ( f.id === selectedFileId)?.name ?? 'Selected File' : 'Scan Library' } onClose={() => setShowMetadataModal(false)} onApply={(data) => { addToast(`Applied: ${data.genre} - ${data.bpm}BPM`, 'success'); setShowMetadataModal(false); }} /> )} {showWatermarkModal && ( setShowWatermarkModal(false)} onSave={() => addToast('Watermark settings updated', 'success')} /> )}
); };