import React, { useState, useCallback, useEffect } from "react"; import { useTranslation } from 'react-i18next'; import { useSearchParams } from "react-router-dom"; import AddToPhotosIcon from "@mui/icons-material/AddToPhotos"; import ContentCutIcon from "@mui/icons-material/ContentCut"; import ZoomInMapIcon from "@mui/icons-material/ZoomInMap"; import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile"; import VisibilityIcon from "@mui/icons-material/Visibility"; import EditNoteIcon from "@mui/icons-material/EditNote"; import { Group, SegmentedControl, Paper, Center, Box, Button, useMantineTheme, useMantineColorScheme } from "@mantine/core"; import ToolPicker from "../components/ToolPicker"; import FileManager from "../components/FileManager"; import SplitPdfPanel from "../tools/Split"; import CompressPdfPanel from "../tools/Compress"; import MergePdfPanel from "../tools/Merge"; import PageEditor from "../components/PageEditor"; import Viewer from "../components/Viewer"; import LanguageSelector from "../components/LanguageSelector"; import DarkModeIcon from '@mui/icons-material/DarkMode'; import LightModeIcon from '@mui/icons-material/LightMode'; type ToolRegistryEntry = { icon: React.ReactNode; name: string; component: React.ComponentType; view: string; }; type ToolRegistry = { [key: string]: ToolRegistryEntry; }; // Base tool registry without translations const baseToolRegistry = { split: { icon: , component: SplitPdfPanel, view: "viewer" }, compress: { icon: , component: CompressPdfPanel, view: "viewer" }, merge: { icon: , component: MergePdfPanel, view: "fileManager" }, }; const VIEW_OPTIONS = [ { label: ( ), value: "viewer", }, { label: ( ), value: "pageEditor", }, { label: ( ), value: "fileManager", }, ]; // Utility to extract params for a tool from searchParams function getToolParams(toolKey: string, searchParams: URLSearchParams) { switch (toolKey) { case "split": return { mode: searchParams.get("splitMode") || "byPages", pages: searchParams.get("pages") || "", hDiv: searchParams.get("hDiv") || "", vDiv: searchParams.get("vDiv") || "", merge: searchParams.get("merge") === "true", splitType: searchParams.get("splitType") || "size", splitValue: searchParams.get("splitValue") || "", bookmarkLevel: searchParams.get("bookmarkLevel") || "0", includeMetadata: searchParams.get("includeMetadata") === "true", allowDuplicates: searchParams.get("allowDuplicates") === "true", }; case "compress": return { compressionLevel: parseInt(searchParams.get("compressionLevel") || "5"), grayscale: searchParams.get("grayscale") === "true", removeMetadata: searchParams.get("removeMetadata") === "true", expectedSize: searchParams.get("expectedSize") || "", aggressive: searchParams.get("aggressive") === "true", }; case "merge": return { order: searchParams.get("mergeOrder") || "default", removeDuplicates: searchParams.get("removeDuplicates") === "true", }; // Add more tools here as needed default: return {}; } } // Utility to update params for a tool function updateToolParams(toolKey: string, searchParams: URLSearchParams, setSearchParams: any, newParams: any) { const params = new URLSearchParams(searchParams); // Clear tool-specific params if (toolKey === "split") { [ "splitMode", "pages", "hDiv", "vDiv", "merge", "splitType", "splitValue", "bookmarkLevel", "includeMetadata", "allowDuplicates" ].forEach((k) => params.delete(k)); // Set new split params const merged = { ...getToolParams("split", searchParams), ...newParams }; params.set("splitMode", merged.mode); if (merged.mode === "byPages") params.set("pages", merged.pages); else if (merged.mode === "bySections") { params.set("hDiv", merged.hDiv); params.set("vDiv", merged.vDiv); params.set("merge", String(merged.merge)); } else if (merged.mode === "bySizeOrCount") { params.set("splitType", merged.splitType); params.set("splitValue", merged.splitValue); } else if (merged.mode === "byChapters") { params.set("bookmarkLevel", merged.bookmarkLevel); params.set("includeMetadata", String(merged.includeMetadata)); params.set("allowDuplicates", String(merged.allowDuplicates)); } } else if (toolKey === "compress") { ["compressionLevel", "grayscale", "removeMetadata", "expectedSize", "aggressive"].forEach((k) => params.delete(k)); const merged = { ...getToolParams("compress", searchParams), ...newParams }; params.set("compressionLevel", String(merged.compressionLevel)); params.set("grayscale", String(merged.grayscale)); params.set("removeMetadata", String(merged.removeMetadata)); if (merged.expectedSize) params.set("expectedSize", merged.expectedSize); params.set("aggressive", String(merged.aggressive)); } else if (toolKey === "merge") { ["mergeOrder", "removeDuplicates"].forEach((k) => params.delete(k)); const merged = { ...getToolParams("merge", searchParams), ...newParams }; params.set("mergeOrder", merged.order); params.set("removeDuplicates", String(merged.removeDuplicates)); } // Add more tools as needed setSearchParams(params, { replace: true }); } // List of all tool-specific params const TOOL_PARAMS = { split: [ "splitMode", "pages", "hDiv", "vDiv", "merge", "splitType", "splitValue", "bookmarkLevel", "includeMetadata", "allowDuplicates" ], compress: [ "compressionLevel", "grayscale", "removeMetadata", "expectedSize", "aggressive" ], merge: [ "mergeOrder", "removeDuplicates" ] // Add more tools as needed }; export default function HomePage() { const { t } = useTranslation(); const [searchParams, setSearchParams] = useSearchParams(); const theme = useMantineTheme(); const { colorScheme, toggleColorScheme } = useMantineColorScheme(); // Create translated tool registry const toolRegistry: ToolRegistry = { split: { ...baseToolRegistry.split, name: t("home.split.title", "Split PDF") }, compress: { ...baseToolRegistry.compress, name: t("home.compressPdfs.title", "Compress PDF") }, merge: { ...baseToolRegistry.merge, name: t("home.merge.title", "Merge PDFs") }, }; // Core app state const [selectedToolKey, setSelectedToolKey] = useState(searchParams.get("tool") || "split"); const [currentView, setCurrentView] = useState(searchParams.get("view") || "viewer"); const [pdfFile, setPdfFile] = useState(null); const [files, setFiles] = useState([]); const [downloadUrl, setDownloadUrl] = useState(null); const [sidebarsVisible, setSidebarsVisible] = useState(true); const toolParams = getToolParams(selectedToolKey, searchParams); const updateParams = (newParams: any) => updateToolParams(selectedToolKey, searchParams, setSearchParams, newParams); // Update URL when core state changes useEffect(() => { const params = new URLSearchParams(searchParams); // Remove all tool-specific params except for the current tool Object.entries(TOOL_PARAMS).forEach(([tool, keys]) => { if (tool !== selectedToolKey) { keys.forEach((k) => params.delete(k)); } }); // Collect all params except 'view' const entries = Array.from(params.entries()).filter(([key]) => key !== "view"); // Rebuild params with 'view' first const newParams = new URLSearchParams(); newParams.set("view", currentView); newParams.set("tool", selectedToolKey); entries.forEach(([key, value]) => { if (key !== "tool") newParams.set(key, value); }); setSearchParams(newParams, { replace: true }); }, [selectedToolKey, currentView, setSearchParams, searchParams]); // Handle tool selection const handleToolSelect = useCallback( (id: string) => { setSelectedToolKey(id); if (toolRegistry[id]?.view) setCurrentView(toolRegistry[id].view); }, [toolRegistry] ); const selectedTool = toolRegistry[selectedToolKey]; // Tool component rendering const renderTool = () => { if (!selectedTool || !selectedTool.component) { return
Tool not found
; } // Pass tool-specific props switch (selectedToolKey) { case "split": return React.createElement(selectedTool.component, { file: pdfFile, downloadUrl, setDownloadUrl, params: toolParams, updateParams, }); case "compress": return React.createElement(selectedTool.component, { files, setDownloadUrl, setLoading: (loading: boolean) => {}, // TODO: Add loading state params: toolParams, updateParams, }); case "merge": return React.createElement(selectedTool.component, { files, setDownloadUrl, params: toolParams, updateParams, }); default: return React.createElement(selectedTool.component, { files, setDownloadUrl, params: toolParams, updateParams, }); } }; return ( {/* Left: Tool Picker */} {sidebarsVisible && ( )} {/* Middle: Main View */} {/* Overlayed View Switcher + Theme Toggle */}
{/* Main content area */} {(currentView === "viewer" || currentView === "pageEditor") && !pdfFile ? ( ) : currentView === "viewer" ? ( ) : currentView === "pageEditor" ? ( ) : ( )}
{/* Right: Tool Interaction */} {sidebarsVisible && ( {selectedTool && selectedTool.component && renderTool()} )} {/* Sidebar toggle button */}
); }