import React, { useState } from "react"; import { useSearchParams } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { Stack, Slider, Group, Text, Button, Checkbox, TextInput, Paper } from "@mantine/core"; import { FileWithUrl } from "../types/file"; import { fileStorage } from "../services/fileStorage"; export interface CompressProps { files?: FileWithUrl[]; setDownloadUrl?: (url: string) => void; setLoading?: (loading: boolean) => void; params?: { compressionLevel: number; grayscale: boolean; removeMetadata: boolean; expectedSize: string; aggressive: boolean; }; updateParams?: (newParams: Partial) => void; } const CompressPdfPanel: React.FC = ({ files = [], setDownloadUrl, setLoading, params = { compressionLevel: 5, grayscale: false, removeMetadata: false, expectedSize: "", aggressive: false, }, updateParams, }) => { const { t } = useTranslation(); const [selected, setSelected] = useState(files.map(() => false)); const [localLoading, setLocalLoading] = useState(false); const { compressionLevel, grayscale, removeMetadata, expectedSize, aggressive, } = params; // Update selection state if files prop changes React.useEffect(() => { setSelected(files.map(() => false)); }, [files]); const handleCheckbox = (idx: number) => { setSelected(sel => sel.map((v, i) => (i === idx ? !v : v))); }; const handleCompress = async () => { const selectedFiles = files.filter((_, i) => selected[i]); if (selectedFiles.length === 0) return; setLocalLoading(true); setLoading?.(true); try { const formData = new FormData(); // Handle IndexedDB files for (const file of selectedFiles) { if (!file.id) { continue; // Skip files without an id } const storedFile = await fileStorage.getFile(file.id); if (storedFile) { const blob = new Blob([storedFile.data], { type: storedFile.type }); const actualFile = new File([blob], storedFile.name, { type: storedFile.type, lastModified: storedFile.lastModified }); formData.append("fileInput", actualFile); } } formData.append("compressionLevel", compressionLevel.toString()); formData.append("grayscale", grayscale.toString()); formData.append("removeMetadata", removeMetadata.toString()); formData.append("aggressive", aggressive.toString()); if (expectedSize) formData.append("expectedSize", expectedSize); const res = await fetch("/api/v1/general/compress-pdf", { method: "POST", body: formData, }); const blob = await res.blob(); setDownloadUrl?.(URL.createObjectURL(blob)); } catch (error) { console.error('Compression failed:', error); } finally { setLocalLoading(false); setLoading?.(false); } }; return ( {t("multiPdfDropPrompt", "Select files to compress:")} {files.length === 0 && {t("noFileSelected")}} {files.map((file, idx) => ( handleCheckbox(idx)} /> ))} {t("compress.selectText.2", "Compression Level")} updateParams?.({ compressionLevel: value })} marks={[ { value: 1, label: "1" }, { value: 5, label: "5" }, { value: 9, label: "9" }, ]} style={{ flex: 1 }} /> updateParams?.({ grayscale: e.currentTarget.checked })} /> updateParams?.({ removeMetadata: e.currentTarget.checked })} /> updateParams?.({ aggressive: e.currentTarget.checked })} /> updateParams?.({ expectedSize: e.currentTarget.value })} /> ); }; export default CompressPdfPanel;