import { TOOLS } from "@snapotter/shared"; import { FileImage, Workflow } from "lucide-react"; import { useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; import { apiGetFileDetails, formatHeaders, getFileDownloadUrl, getFileThumbnailUrl, type UserFileDetail, } from "@/lib/api"; import { cn } from "@/lib/utils"; import { useFileStore } from "@/stores/file-store"; import { useFilesPageStore } from "@/stores/files-page-store"; function toolName(toolId: string): string { return TOOLS.find((t) => t.id === toolId)?.name ?? toolId; } function formatSize(bytes: number): string { if (bytes < 1024) return `${bytes} B`; if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; } interface FileDetailsProps { mobile?: boolean; } export function FileDetails({ mobile = false }: FileDetailsProps) { const { selectedFileId } = useFilesPageStore(); const setFiles = useFileStore((s) => s.setFiles); const navigate = useNavigate(); const [details, setDetails] = useState(null); const [loadingDetails, setLoadingDetails] = useState(false); useEffect(() => { if (!selectedFileId) { setDetails(null); return; } setLoadingDetails(true); apiGetFileDetails(selectedFileId) .then(setDetails) .catch(() => setDetails(null)) .finally(() => setLoadingDetails(false)); }, [selectedFileId]); async function handleOpenFile() { if (!details) return; const { checkedIds, files: allFiles } = useFilesPageStore.getState(); // If multiple files are checked, open all of them; otherwise just the selected one const filesToOpen = checkedIds.size > 1 ? allFiles.filter((f) => checkedIds.has(f.id)) : [{ id: details.id, originalName: details.originalName, mimeType: details.mimeType }]; const downloaded = await Promise.all( filesToOpen.map(async (f) => { const res = await fetch(getFileDownloadUrl(f.id), { headers: formatHeaders(), }); if (!res.ok) return null; const blob = await res.blob(); return { file: new File([blob], f.originalName, { type: f.mimeType }), serverId: f.id }; }), ); const valid = downloaded.filter((d): d is NonNullable => d !== null); if (valid.length === 0) return; setFiles(valid.map((d) => d.file)); navigate("/"); // Set serverFileId on each entry so tool processing creates new versions setTimeout(() => { const store = useFileStore.getState(); for (let i = 0; i < valid.length; i++) { if (store.entries[i]) { store.updateEntry(i, { serverFileId: valid[i].serverId }); } } }, 0); } if (!selectedFileId) { return ( ); } if (loadingDetails) { return (