import React, { useCallback } from 'react' import { useDropzone } from 'react-dropzone' import { Box, Typography, Paper, LinearProgress, Alert } from '@mui/material' import { CloudUpload, InsertDriveFile } from '@mui/icons-material' import { useUploadStore } from '../stores/uploadStore' import { useOptionsStore } from '../stores/optionsStore' // NEW import { uploadFile, getTaskInfo, getRecommendedFormat } from '../api/client' // NEW import { useTaskStore } from '../stores/taskStore' const ALLOWED_EXTENSIONS = ['.mp3', '.flac', '.wav', '.m4a', '.ogg', '.opus', '.aac', '.wma', '.aiff', '.alac', '.ac3'] export const UploadZone: React.FC = () => { const { file, fileName, fileSize, isUploading, uploadProgress, error, setFile, setFileName, setFileSize, setIsUploading, setUploadProgress, setError, setTaskId, setHasVideo, setHasAudio, setHasSubtitle, setAudioCodec, } = useUploadStore() const { setTaskId: setTaskIdStore } = useTaskStore() const { setOptions } = useOptionsStore() // NEW const onDrop = useCallback( async (acceptedFiles: File[]) => { if (acceptedFiles.length === 0) return const selectedFile = acceptedFiles[0] const extension = '.' + selectedFile.name.split('.').pop()?.toLowerCase() if (!ALLOWED_EXTENSIONS.includes(extension)) { setError(`Unsupported file format. Allowed: ${ALLOWED_EXTENSIONS.join(', ')}`) return } setFile(selectedFile) setFileName(selectedFile.name) setFileSize(selectedFile.size) setError(null) setIsUploading(true) setUploadProgress(0) try { const response = await uploadFile(selectedFile) const taskId = response.task_id setTaskId(taskId) setTaskIdStore(taskId) setUploadProgress(100) setIsUploading(false) // Fetch stream info try { const info = await getTaskInfo(taskId) setHasVideo(info.has_video) setHasAudio(info.has_audio) setHasSubtitle(info.has_subtitle) setAudioCodec(info.audio_codec) // Fetch recommended format and update options try { // Inside UploadZone.tsx, after fetching recommended format: const rec = await getRecommendedFormat(taskId) // Update options store with container (not format) setOptions({ container: rec.format }) } catch (err) { console.warn('Failed to fetch recommended format, using default', err) } } catch (err) { console.error('Failed to fetch stream info:', err) // Don't block upload flow; user can manually change options } } catch (err: any) { setError(err.response?.data?.detail || err.message || 'Upload failed') setIsUploading(false) setUploadProgress(0) setFile(null) setFileName('') setFileSize(0) } }, [setFile, setFileName, setFileSize, setIsUploading, setUploadProgress, setError, setTaskId, setTaskIdStore, setHasVideo, setHasAudio, setHasSubtitle, setAudioCodec, setOptions] ) const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop, accept: { 'audio/*': ALLOWED_EXTENSIONS, }, multiple: false, disabled: isUploading, }) const formatFileSize = (bytes: number): string => { if (bytes < 1024) return `${bytes} B` if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB` return `${(bytes / (1024 * 1024)).toFixed(1)} MB` } return ( {file ? ( {fileName} {formatFileSize(fileSize)} {isUploading && ( {uploadProgress}% uploaded )} {!isUploading && ( ✅ Uploaded successfully )} ) : ( {isDragActive ? 'Drop your audio file here' : 'Drag & drop your audio file here'} or click to browse Supported formats: {ALLOWED_EXTENSIONS.join(', ')} )} {error && ( {error} )} ) }