"use client"; import { useState, useCallback, useEffect } from "react"; import { motion } from "framer-motion"; import { Video, Settings } from "lucide-react"; import { FileUploader } from "@/components/tools/FileUploader"; import { ProgressBar } from "@/components/tools/ProgressBar"; import { ResultPreview } from "@/components/tools/ResultPreview"; import { ConfigPanel, type ConfigOption } from "@/components/tools/ConfigPanel"; import { Button } from "@/components/ui/button"; import { useUploadStore } from "@/store/uploadStore"; import { generateId } from "@/lib/utils"; import { useTranslation, getServerTranslations } from "@/lib/i18n"; import type { UploadedFile, ProcessedFile, VideoFramesConfig } from "@/types"; const videoAccept = { "video/*": [".mp4", ".mov", ".avi", ".webm", ".mkv"], }; const defaultConfig: VideoFramesConfig = { fps: 30, format: "png", quality: 90, width: undefined, height: undefined, }; function useConfigOptions(config: VideoFramesConfig, getT: (key: string) => string): ConfigOption[] { return [ { id: "fps", type: "slider", label: getT("config.videoFrames.fps"), description: getT("config.videoFrames.fpsDescription"), value: config.fps, min: 1, max: 60, step: 1, suffix: " fps", icon: , }, { id: "format", type: "select", label: getT("config.videoFrames.format"), description: getT("config.videoFrames.formatDescription"), value: config.format, options: [ { label: "PNG", value: "png" }, { label: "JPEG", value: "jpeg" }, { label: "WebP", value: "webp" }, ], }, { id: "quality", type: "slider", label: getT("config.videoFrames.quality"), description: getT("config.videoFrames.qualityDescription"), value: config.quality, min: 1, max: 100, step: 1, suffix: "%", }, ]; } export default function VideoFramesPage() { const [mounted, setMounted] = useState(false); useEffect(() => setMounted(true), []); const { t } = useTranslation(); const getT = (key: string, params?: Record) => { if (!mounted) return getServerTranslations("en").t(key, params); return t(key, params); }; const { files, addFile, removeFile, clearFiles, processingStatus, setProcessingStatus } = useUploadStore(); const [config, setConfig] = useState(defaultConfig); const [processedFiles, setProcessedFiles] = useState([]); const handleFilesDrop = useCallback( (acceptedFiles: File[]) => { const newFiles: UploadedFile[] = acceptedFiles.map((file) => ({ id: generateId(), file, name: file.name, size: file.size, type: file.type, uploadedAt: new Date(), })); newFiles.forEach((file) => addFile(file)); }, [addFile] ); const handleConfigChange = (id: string, value: string | number | boolean | undefined) => { setConfig((prev) => ({ ...prev, [id]: value })); }; const handleResetConfig = () => { setConfig(defaultConfig); }; const handleProcess = async () => { if (files.length === 0) return; setProcessingStatus({ status: "uploading", progress: 0, message: getT("processing.uploadingVideo"), }); try { // Simulate upload for (let i = 0; i <= 100; i += 10) { await new Promise((resolve) => setTimeout(resolve, 100)); setProcessingStatus({ status: "uploading", progress: i, message: getT("processing.uploadProgress", { progress: i }), }); } setProcessingStatus({ status: "processing", progress: 0, message: getT("processing.extractingFrames"), }); // Simulate processing for (let i = 0; i <= 100; i += 5) { await new Promise((resolve) => setTimeout(resolve, 150)); setProcessingStatus({ status: "processing", progress: i, message: getT("processing.processProgress", { progress: i }), }); } // Simulate completion const results: ProcessedFile[] = files.map((file) => ({ id: generateId(), originalFile: file, processedUrl: "#", metadata: { format: config.format, quality: config.quality, fps: config.fps, frames: Math.floor(10 * config.fps), // Simulated }, createdAt: new Date(), })); setProcessedFiles(results); clearFiles(); setProcessingStatus({ status: "completed", progress: 100, message: getT("processing.processingComplete"), }); } catch (error) { setProcessingStatus({ status: "failed", progress: 0, message: getT("processing.processingFailed"), error: error instanceof Error ? error.message : getT("processing.unknownError"), }); } }; const handleDownload = (fileId: string) => { console.log("Downloading file:", fileId); }; const canProcess = files.length > 0 && processingStatus.status !== "processing"; const configOptions = useConfigOptions(config, getT); return ( {/* Header */} {getT("tools.videoFrames.title")} {getT("tools.videoFrames.description")} {/* Left Column - Upload and Config */} ({ ...opt, value: config[opt.id as keyof VideoFramesConfig], }))} onChange={handleConfigChange} onReset={handleResetConfig} /> {canProcess && ( {getT("tools.videoFrames.processVideo")} )} {/* Right Column - Progress and Results */} {processingStatus.status !== "idle" && ( )} {processedFiles.length > 0 && ( )} {/* Info Card */} {getT("tools.videoFrames.howItWorks")} {(getT("tools.videoFrames.steps") as unknown as string[]).map((step, index) => ( {index + 1}. {step} ))} ); }
{getT("tools.videoFrames.description")}