import { Download } from "lucide-react"; import { useEffect, useRef, useState } from "react"; import { ProgressCard } from "@/components/common/progress-card"; import { useTranslation } from "@/contexts/i18n-context"; import { useToolProcessor } from "@/hooks/use-tool-processor"; import { format } from "@/lib/format"; import { useFileStore } from "@/stores/file-store"; const LOSSY_FORMATS = new Set(["jpeg", "webp", "avif", "jxl"]); export interface RedEyeRemovalControlsProps { settings?: Record; onChange?: (settings: Record) => void; } export function RedEyeRemovalControls({ settings: initialSettings, onChange, }: RedEyeRemovalControlsProps) { const [sensitivity, setSensitivity] = useState(50); const [strength, setStrength] = useState(70); const [outputFormat, setOutputFormat] = useState< "original" | "png" | "jpeg" | "webp" | "avif" | "jxl" >("original"); const [quality, setQuality] = useState(90); // One-time init from pipeline settings const initializedRef = useRef(false); useEffect(() => { if (!initialSettings || initializedRef.current) return; initializedRef.current = true; if (initialSettings.sensitivity != null) setSensitivity(Number(initialSettings.sensitivity)); if (initialSettings.strength != null) setStrength(Number(initialSettings.strength)); if (initialSettings.format != null) setOutputFormat( initialSettings.format as "original" | "png" | "jpeg" | "webp" | "avif" | "jxl", ); if (initialSettings.quality != null) setQuality(Number(initialSettings.quality)); }, [initialSettings]); // Emit settings on change const onChangeRef = useRef(onChange); useEffect(() => { onChangeRef.current = onChange; }); useEffect(() => { onChangeRef.current?.({ sensitivity, strength, format: outputFormat, quality, }); }, [sensitivity, strength, outputFormat, quality]); const tabClass = (active: boolean) => `flex-1 text-xs py-1.5 rounded ${active ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground hover:bg-muted/80"}`; return (
{/* Sensitivity slider */}

Sensitivity

{sensitivity}
setSensitivity(Number(e.target.value))} className="w-full h-1.5 rounded-full appearance-none bg-muted accent-primary" />
Strict Aggressive
{/* Correction Strength slider */}

Correction Strength

{strength}
setStrength(Number(e.target.value))} className="w-full h-1.5 rounded-full appearance-none bg-muted accent-primary" />
Subtle Dark
{/* Output format */}

Output Format

{(["original", "png", "jpeg", "webp", "avif", "jxl"] as const).map((f) => ( ))}
{/* Quality slider (lossy formats only) */} {LOSSY_FORMATS.has(outputFormat) && (

Quality

{quality}
setQuality(Number(e.target.value))} className="w-full h-1.5 rounded-full appearance-none bg-muted accent-primary" />
)}
); } export function RedEyeRemovalSettings() { const { t } = useTranslation(); const { files } = useFileStore(); const { processFiles, processAllFiles, processing, error, downloadUrl, originalSize, processedSize, progress, } = useToolProcessor("red-eye-removal"); const [settings, setSettings] = useState>({}); const handleProcess = () => { if (files.length > 1) { processAllFiles(files, settings); } else { processFiles(files, settings); } }; const hasFile = files.length > 0; const hasMultiple = files.length > 1; return (
{/* Error */} {error &&

{error}

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

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

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

)} {/* Process button / progress */} {processing ? ( ) : ( )} {/* Download (single file - batch uses Download All ZIP in tool-page) */} {!hasMultiple && downloadUrl && ( Download )}
); }