import { Download, Minus, Plus } from "lucide-react"; import { useEffect, useRef, useState } from "react"; import { ProgressCard } from "@/components/common/progress-card"; import { useToolProcessor } from "@/hooks/use-tool-processor"; import { useFileStore } from "@/stores/file-store"; type CompressMode = "quality" | "targetSize"; type SizeUnit = "KB" | "MB"; export interface CompressControlsProps { settings?: Record; onChange?: (settings: Record) => void; } export function CompressControls({ settings: initialSettings, onChange }: CompressControlsProps) { const [mode, setMode] = useState("targetSize"); const [quality, setQuality] = useState(75); const [targetSizeValue, setTargetSizeValue] = useState(""); const [sizeUnit, setSizeUnit] = useState("KB"); const initializedRef = useRef(false); useEffect(() => { if (!initialSettings || initializedRef.current) return; initializedRef.current = true; if (initialSettings.mode != null) setMode(initialSettings.mode as CompressMode); if (initialSettings.quality != null) setQuality(Number(initialSettings.quality)); if (initialSettings.targetSizeKb != null) setTargetSizeValue(String(initialSettings.targetSizeKb)); }, [initialSettings]); const onChangeRef = useRef(onChange); useEffect(() => { onChangeRef.current = onChange; }); useEffect(() => { if (mode === "quality") { onChangeRef.current?.({ mode, quality }); } else { const valueNum = Number(targetSizeValue); const targetSizeKb = sizeUnit === "MB" ? valueNum * 1024 : valueNum; onChangeRef.current?.({ mode, targetSizeKb }); } }, [mode, quality, targetSizeValue, sizeUnit]); return (
{/* Mode toggle */}

Compression Mode

{mode === "targetSize" ? (
setTargetSizeValue(e.target.value)} min={1} placeholder={sizeUnit === "KB" ? "e.g. 200" : "e.g. 2"} className="flex-1 min-w-0 px-2 py-1.5 rounded border border-border bg-background text-sm text-foreground tabular-nums [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none" />
) : (
{quality}
setQuality(Number(e.target.value))} className="flex-1 min-w-0" />
Smallest file Best quality
)}
); } export function CompressSettings() { const { files } = useFileStore(); const { processFiles, processAllFiles, processing, error, downloadUrl, originalSize, processedSize, progress, } = useToolProcessor("compress"); const [settings, setSettings] = useState>({}); const handleProcess = () => { if (files.length > 1) { processAllFiles(files, settings); } else { processFiles(files, settings); } }; const hasFile = files.length > 0; const canProcess = settings.mode === "quality" || (settings.mode === "targetSize" && Number(settings.targetSizeKb) > 0); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (hasFile && canProcess && !processing) handleProcess(); }; return (
{/* Error */} {error &&

{error}

} {/* Size info */} {originalSize != null && processedSize != null && (

Original: {(originalSize / 1024).toFixed(1)} KB

Processed: {(processedSize / 1024).toFixed(1)} KB

Saved: {originalSize > 0 ? ((1 - processedSize / originalSize) * 100).toFixed(1) : "0"}%

)} {/* Process */} {processing ? ( ) : ( )} {/* Download */} {downloadUrl && ( Download )} ); }