import { CATEGORIES, MODALITIES, PYTHON_SIDECAR_TOOLS, TOOL_BUNDLE_MAP, TOOLS, } from "@snapotter/shared"; import { Clock, Download, FileArchive, LayoutGrid, Loader2 } from "lucide-react"; import { useCallback, useEffect, useMemo, useState } from "react"; import { useLocation, useNavigate } from "react-router-dom"; import { ImageViewer } from "@/components/common/image-viewer"; import { MultiImageViewer } from "@/components/common/multi-image-viewer"; import { AppLayout } from "@/components/layout/app-layout"; import { DocumentView } from "@/components/tools/document-view"; import { MediaPlayerView } from "@/components/tools/media-player-view"; import { useTranslation } from "@/contexts/i18n-context"; import { useMobile } from "@/hooks/use-mobile"; import { ICON_MAP } from "@/lib/icon-map"; import { getCategoryName, getModalityName, getToolName } from "@/lib/tool-i18n"; import { cn } from "@/lib/utils"; import { useFeaturesStore } from "@/stores/features-store"; import { useFileStore } from "@/stores/file-store"; import { useSettingsStore } from "@/stores/settings-store"; // Tools shown prominently as "quick actions" at the top let hasAppliedDefaultRedirect = false; export function HomePage() { const { t } = useTranslation(); const { setFiles, files, reset, originalBlobUrl, selectedFileName, selectedFileSize, currentEntry, } = useFileStore(); const navigate = useNavigate(); const location = useLocation(); const { fetch: fetchSettings, defaultToolView, loaded: settingsLoaded } = useSettingsStore(); const { fetch: fetchFeatures, bundles, installing, queued } = useFeaturesStore(); const isMobile = useMobile(); useEffect(() => { if (location.state?.fromLibrary) { navigate(".", { replace: true, state: {} }); } else { reset(); } }, [reset, location.state, navigate]); useEffect(() => { fetchSettings(); fetchFeatures(); }, [fetchSettings, fetchFeatures]); useEffect(() => { if ( !hasAppliedDefaultRedirect && settingsLoaded && defaultToolView === "fullscreen" && files.length === 0 ) { hasAppliedDefaultRedirect = true; navigate("/fullscreen", { replace: true }); } }, [settingsLoaded, defaultToolView, files.length, navigate]); const getToolStatus = useMemo(() => { return (toolId: string) => { const isAi = (PYTHON_SIDECAR_TOOLS as readonly string[]).includes(toolId); if (!isAi) return "installed"; const bundleId = TOOL_BUNDLE_MAP[toolId]; if (!bundleId) return "installed"; if (queued.includes(bundleId)) return "queued"; if (installing[bundleId]) return "installing"; const bundle = bundles.find((b) => b.id === bundleId); return bundle?.status === "installed" ? "installed" : "not_installed"; }; }, [bundles, installing, queued]); const handleFiles = useCallback( (newFiles: File[]) => { reset(); setFiles(newFiles); }, [setFiles, reset], ); const handleUrlImport = useCallback( (file: File) => { setFiles([file]); }, [setFiles], ); const [modalityFilter, setModalityFilter] = useState("all"); const TAB_MODALITIES = useMemo(() => MODALITIES.filter((m) => m.id !== "file"), []); const hasFile = files.length > 0; // If no file uploaded, show default layout (tool panel + dropzone) if (!hasFile) { return ; } // File uploaded — mobile: stacked layout if (isMobile && hasFile) { return (

{t.nav.tools}

{/* File info bar */}
{selectedFileName ?? files[0].name} {selectedFileSize ? `${(selectedFileSize / 1024).toFixed(1)} KB` : ""}
{/* Full-width file preview */}
{files.length > 1 ? ( ) : currentEntry?.previewLoading ? (

{t.homePage.generatingPreview}

{selectedFileName}

) : currentEntry?.previewKind === "video" || currentEntry?.previewKind === "audio" ? ( ) : currentEntry?.previewKind === "document" ? ( ) : currentEntry?.previewKind === "none" ? (

{selectedFileName ?? files[0].name}

{selectedFileSize ? `${(selectedFileSize / 1024).toFixed(1)} KB` : ""}

) : originalBlobUrl ? ( ) : (

{t.homePage.loadingPreview}

)}
); } // File uploaded — desktop: tool selector on left, image preview on right return (

{t.nav.tools}

{/* Left panel: Tool selector */}
{/* File info */}
{selectedFileName ?? files[0].name}

{selectedFileSize ? `${(selectedFileSize / 1024).toFixed(1)} KB` : ""} {files.length > 1 && ` — ${files.length} files`}

{/* Modality filter tabs */}
{TAB_MODALITIES.map((m) => { const Icon = ICON_MAP[m.icon] as React.ComponentType<{ className?: string }>; const isActive = modalityFilter === m.id; const label = m.id === "document" ? "Docs" : m.name; return ( ); })}
{/* Tools by modality and category */}
{MODALITIES.filter((m) => { if (m.id === "file") return false; if (modalityFilter !== "all") { if (modalityFilter === "document") return m.id === "document"; return m.id === modalityFilter; } const key = m.id; return TOOLS.some( (tool) => tool.modality === key || (key === "document" && tool.modality === "file"), ); }).map((modality) => { const ModalityIcon = ICON_MAP[modality.icon] as React.ComponentType<{ className?: string; }>; const modalityTools = TOOLS.filter( (tool) => tool.modality === modality.id || (modality.id === "document" && tool.modality === "file"), ); const categoryMap = new Map(); for (const tool of modalityTools) { const list = categoryMap.get(tool.category) ?? []; list.push(tool); categoryMap.set(tool.category, list); } return (
{ModalityIcon && ( )}

{getModalityName( t, modality.id, modality.id === "document" ? "Documents & Files" : modality.name, )}

{CATEGORIES.filter((cat) => categoryMap.has(cat.id)).map((category) => (

{getCategoryName(t, category.id, category.name)}

{categoryMap.get(category.id)?.map((tool) => { const Icon = (ICON_MAP[tool.icon] as React.ComponentType<{ className?: string; }>) ?? ICON_MAP.FileImage; const status = getToolStatus(tool.id); return ( ); })}
))}
); })}
{/* Right panel: File preview (modality-aware) */}
{files.length > 1 ? ( ) : currentEntry?.previewLoading ? (

{t.homePage.generatingPreview}

{selectedFileName}

) : currentEntry?.previewKind === "video" || currentEntry?.previewKind === "audio" ? ( ) : currentEntry?.previewKind === "document" ? ( ) : currentEntry?.previewKind === "none" ? (

{selectedFileName ?? files[0].name}

{selectedFileSize ? `${(selectedFileSize / 1024).toFixed(1)} KB` : ""}

) : originalBlobUrl ? ( ) : (

{t.homePage.loadingPreview}

)}
); }