import React, { useState, useEffect } from 'react'; import { Stack, Card, Box, Center, Text, Badge, Button, Image, Group, Divider, ActionIcon, ScrollArea } from '@mantine/core'; import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf'; import ChevronLeftIcon from '@mui/icons-material/ChevronLeft'; import ChevronRightIcon from '@mui/icons-material/ChevronRight'; import { useTranslation } from 'react-i18next'; import { detectFileExtension, getFileSize } from '../../../utils/fileUtils'; import { useIndexedDBThumbnail } from '../../../hooks/useIndexedDBThumbnail'; import { FileWithUrl } from '../../../types/file'; import { FileDetailsProps } from './types'; const FileDetails: React.FC = ({ selectedFiles, onOpenFiles, compact = false, modalHeight = '80vh' }) => { const { t } = useTranslation(); const [currentFileIndex, setCurrentFileIndex] = useState(0); const [thumbnailCache, setThumbnailCache] = useState>({}); const [loadingFile, setLoadingFile] = useState(null); const [isAnimating, setIsAnimating] = useState(false); // Get the currently displayed file const currentFile = selectedFiles.length > 0 ? selectedFiles[currentFileIndex] : null; const hasSelection = selectedFiles.length > 0; const hasMultipleFiles = selectedFiles.length > 1; // Only load thumbnail for files not in cache const shouldLoadThumbnail = loadingFile && !thumbnailCache[loadingFile.id || loadingFile.name]; const { thumbnail } = useIndexedDBThumbnail(shouldLoadThumbnail ? loadingFile : ({} as FileWithUrl)); // Load thumbnails for all selected files useEffect(() => { // Start loading thumbnails for uncached files const uncachedFiles = selectedFiles.filter(file => !thumbnailCache[file.id || file.name]); if (uncachedFiles.length > 0 && !loadingFile) { setLoadingFile(uncachedFiles[0]); } }, [selectedFiles, thumbnailCache, loadingFile]); // Cache thumbnail when it loads and move to next uncached file useEffect(() => { if (loadingFile && thumbnail) { const fileId = loadingFile.id || loadingFile.name; setThumbnailCache(prev => ({ ...prev, [fileId]: thumbnail })); // Find next uncached file to load const uncachedFiles = selectedFiles.filter(file => !thumbnailCache[file.id || file.name] && (file.id || file.name) !== fileId ); if (uncachedFiles.length > 0) { setLoadingFile(uncachedFiles[0]); } else { setLoadingFile(null); } } }, [loadingFile, thumbnail, selectedFiles, thumbnailCache]); // Clear cache when selection changes completely useEffect(() => { const selectedFileIds = selectedFiles.map(f => f.id || f.name); setThumbnailCache(prev => { const newCache: Record = {}; selectedFileIds.forEach(id => { if (prev[id]) { newCache[id] = prev[id]; } }); return newCache; }); setLoadingFile(null); }, [selectedFiles]); // Get thumbnail from cache only const getCurrentThumbnail = () => { if (!currentFile) return null; const fileId = currentFile.id || currentFile.name; return thumbnailCache[fileId]; }; const handlePrevious = () => { if (isAnimating) return; setIsAnimating(true); setTimeout(() => { setCurrentFileIndex(prev => prev > 0 ? prev - 1 : selectedFiles.length - 1); setIsAnimating(false); }, 150); }; const handleNext = () => { if (isAnimating) return; setIsAnimating(true); setTimeout(() => { setCurrentFileIndex(prev => prev < selectedFiles.length - 1 ? prev + 1 : 0); setIsAnimating(false); }, 150); }; // Reset index when selection changes React.useEffect(() => { if (currentFileIndex >= selectedFiles.length) { setCurrentFileIndex(0); } }, [selectedFiles.length, currentFileIndex]); if (compact) { return ( {/* Compact mobile layout */} {/* Small preview */} {currentFile && getCurrentThumbnail() ? ( {currentFile.name} ) : currentFile ? (
) : null}
{/* File info */} {currentFile ? currentFile.name : 'No file selected'} {currentFile ? getFileSize(currentFile) : ''} {selectedFiles.length > 1 && ` • ${selectedFiles.length} files`} {hasMultipleFiles && ( {currentFileIndex + 1} of {selectedFiles.length} )} {/* Navigation arrows for multiple files */} {hasMultipleFiles && ( )}
{/* Action Button */}
); } return ( {/* Section 1: Thumbnail Preview */} {/* Left Navigation Arrow */} {hasMultipleFiles && ( )} {/* Document Stack Container */} {/* Background documents (stack effect) */} {hasMultipleFiles && selectedFiles.length > 1 && ( <> {/* Third document (furthest back) */} {selectedFiles.length > 2 && ( )} {/* Second document */} )} {/* Main document */} {currentFile && getCurrentThumbnail() ? ( {currentFile.name} ) : currentFile ? (
) : null}
{/* Right Navigation Arrow */} {hasMultipleFiles && ( )}
{/* Section 2: File Details */} {t('fileManager.details', 'File Details')} {t('fileManager.fileName', 'Name')} {currentFile ? currentFile.name : ''} {t('fileManager.fileFormat', 'Format')} {currentFile ? ( {detectFileExtension(currentFile.name).toUpperCase()} ) : ( )} {t('fileManager.fileSize', 'Size')} {currentFile ? getFileSize(currentFile) : ''} {t('fileManager.fileVersion', 'Version')} {currentFile ? '1.0' : ''} {selectedFiles.length > 1 && ( <> {t('fileManager.totalSelected', 'Selected')} {selectedFiles.length} files )} {/* Section 3: Action Button */}
); }; export default FileDetails;