diff --git a/api/api/views.py b/api/api/views.py index 1655b7d..6cb298c 100644 --- a/api/api/views.py +++ b/api/api/views.py @@ -1,4 +1,5 @@ import os +import shutil import uuid import zipfile from django.http import FileResponse, HttpResponse @@ -18,6 +19,7 @@ from freqsplit.input.format_checker import is_supported_format UPLOAD_DIR = "/tmp/freqsplit" # Ensure the temp directory exists +shutil.rmtree(UPLOAD_DIR) os.makedirs(UPLOAD_DIR, exist_ok=True) # Endpoint to ping server diff --git a/client/src/Pages/PreviewPage.tsx b/client/src/Pages/PreviewPage.tsx index e30d023..47b2def 100644 --- a/client/src/Pages/PreviewPage.tsx +++ b/client/src/Pages/PreviewPage.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect, useRef } from 'react'; +import { useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { Typography, @@ -18,12 +18,7 @@ import SpectrogramPlayer from "react-audio-spectrogram-player" function PreviewPage() { const navigate = useNavigate(); const { mediaFile, response } = useMediaContext(); - const [error, setError] = useState(false); - const videoRef = useRef(null); const audioClass = response.audio_class - // Supported video formats - const supportedFormats = ['video/mp4', 'video/webm', 'video/ogg']; - const isVideo = mediaFile && supportedFormats.includes(mediaFile.type); useEffect(() => { if (!mediaFile) { @@ -46,32 +41,7 @@ function PreviewPage() { - {isVideo ? ( - - - ) : mediaFile.type.startsWith('audio/') ? ( + {mediaFile.type.startsWith('audio/') ? ( new Promise(resolve => setTimeout(resolve, ms)); - const processStep = async (url: string, log: string | null, nextStep: () => void, progressValue: number, status: string, extraData = {}) => { - try { + const showErrorToast = (message: string) => { + setToastMessage(message); + setToastOpen(true); + } + const processStep = async ( + url: string, + log: string | null, + nextStep: () => void, + progressValue: number, + status: string, + extraData = {} + ) => { + try { if (log !== null) { setLogs((prevLogs) => [...prevLogs, log]); } - + const formData = new FormData(); formData.append("file_uuid", response.file_uuid); - Object.entries(extraData).forEach(([key, value]) => + Object.entries(extraData).forEach(([key, value]) => formData.append(key, String(value)) ); - - + setStatusText(status); const startTime = Date.now(); - const res = await axios.post(url, formData, { + await axios.post(url, formData, { headers: { "Content-Type": "multipart/form-data" }, }); - - if (res.status === 200 && res.data) { - const elapsedTime = Date.now() - startTime; - if (elapsedTime < 5000) await delay(5000 - elapsedTime); - setProgress(progressValue); - nextStep(); - } + + const elapsedTime = Date.now() - startTime; + if (elapsedTime < 5000) await delay(5000 - elapsedTime); + + setProgress(progressValue); + nextStep(); } catch (error) { - console.error(`Error in step: ${url}`, error); + if (axios.isAxiosError(error)) { + if (error.response?.status === 500) { + showErrorToast(`Internal Server Error`); + } else { + showErrorToast(`Internal Server Error`); + } + } else { + showErrorToast(`Internal Server Error`); + } } }; + const fetchZipDownload = async () => { try { @@ -61,7 +80,15 @@ function ProcessingPage() { console.log("Failed to download the file"); } } catch (error) { - console.error("Error fetching download:", error); + if (axios.isAxiosError(error)) { + if (error.response?.status === 500) { + showErrorToast(`Internal Server Error`); + } else { + showErrorToast(`Internal Server Error`); + } + } else { + showErrorToast(`Internal Server Error`); + } } }; @@ -118,7 +145,15 @@ function ProcessingPage() { console.log("Failed to download the file"); } } catch (error) { - console.error("Error fetching download:", error); + if (axios.isAxiosError(error)) { + if (error.response?.status === 500) { + showErrorToast(`Internal Server Error`); + } else { + showErrorToast(`Internal Server Error`); + } + } else { + showErrorToast(`Internal Server Error`); + } } }; @@ -134,7 +169,8 @@ function ProcessingPage() { const fileURLs = []; for (const [filename, fileData] of Object.entries(zip.files)) { - if (!fileData.dir) { + try { + if (!fileData.dir) { const fileBlob = await fileData.async("blob"); const fileURL = URL.createObjectURL(fileBlob); @@ -162,6 +198,17 @@ function ProcessingPage() { } fileURLs.push({ name: filename, url: fileURL, spectrogram: res.data.spectrogram, spec_sr: res.data.spec_sr }); } + } catch (error) { + if (axios.isAxiosError(error)) { + if (error.response?.status === 500) { + showErrorToast(`Internal Server Error`); + } else { + showErrorToast(`Internal Server Error`); + } + } else { + showErrorToast(`Internal Server Error`); + } + } } setExtractedFiles(fileURLs); setProgress(100); @@ -231,7 +278,8 @@ function ProcessingPage() { }} /> - + + ); } diff --git a/client/src/Pages/ResultsPage.tsx b/client/src/Pages/ResultsPage.tsx index d5e5fa1..f9858c1 100644 --- a/client/src/Pages/ResultsPage.tsx +++ b/client/src/Pages/ResultsPage.tsx @@ -1,6 +1,5 @@ import { useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; -//import axios from 'axios'; import { Typography, Container, @@ -13,7 +12,6 @@ import { LinearProgress, } from '@mui/material'; import { - Check as CheckIcon, VolumeUp as VolumeUpIcon } from '@mui/icons-material'; import StepperComponent from '../components/StepperComponent'; @@ -27,7 +25,6 @@ function ResultsPage() { const navigate = useNavigate(); const { mediaFile, response, extractedFiles, downloadedFileURL, downloadedFileSpectrogram, setLogs } = useMediaContext(); const audioClass = response.audio_class - const isVideo = mediaFile?.type.includes('video'); const handleDownloadAll = () => { if (audioClass === 'Music') { @@ -57,17 +54,6 @@ function ResultsPage() { } }, [mediaFile, navigate]); -// const togglePlay = (index) => { -// if (audioRefs[index].current) { -// if (isPlaying) { -// audioRefs[index].current.pause(); -// } else { -// audioRefs[index].current.play(); -// } -// setIsPlaying(!isPlaying); -// } -// }; - if (!mediaFile) return ; return ( @@ -75,11 +61,17 @@ function ResultsPage() { - - - - Processing Complete! - + + + Processing Complete! + @@ -87,82 +79,74 @@ function ResultsPage() { - {isVideo ? ( - diff --git a/client/src/Pages/UploadPage.tsx b/client/src/Pages/UploadPage.tsx index 9725903..4982a20 100644 --- a/client/src/Pages/UploadPage.tsx +++ b/client/src/Pages/UploadPage.tsx @@ -1,6 +1,7 @@ import React, { useState, useEffect } from "react"; import { useNavigate } from "react-router-dom"; import Logs from "../components/Logs" +import Toast from "../components/Toast"; import axios from "axios"; import { Typography, @@ -13,7 +14,6 @@ import { import { CloudUpload as CloudUploadIcon, VolumeUp as VolumeUpIcon, - Movie as MovieIcon, } from "@mui/icons-material"; import StepperComponent from "../components/StepperComponent"; import { useWebSocket } from "../contexts/WebSocketContext"; @@ -24,13 +24,17 @@ function UploadPage() { const navigate = useNavigate(); const theme = useTheme(); const { socket, isConnected } = useWebSocket(); - const { setMediaFile, setResponse, setLogs } = useMediaContext(); + const { setMediaFile, setResponse, setLogs, setToastOpen, setToastMessage } = useMediaContext(); const [file, setFile] = useState(null); const [isDragging, setIsDragging] = useState(false); - const [fileError, setFileError] = useState(""); const [upload, setUpload] = useState(false); const [inputEnabled, setInputEnabled] = useState(false); + const showErrorToast = (message: string) => { + setToastMessage(message); + setToastOpen(true); + } + useEffect(() => { const startLogs = async () => { setLogs([formatLogMessage("Initializing freqsplit")]); @@ -102,19 +106,37 @@ function UploadPage() { }; const handleFileChange = (e: React.ChangeEvent) => { + setUpload(false); + setResponse({ + audio_class: "", + file_uuid: "", + sr: 0, + spectrogram: "", + spec_sr: 0 + }); const selectedFile = e.target.files?.[0] || null; + const maxSize = 100 * 1024 * 1024; // 100MB in bytes + + if (selectedFile) { + if (selectedFile.size > maxSize) { + showErrorToast("Max file size is 100MB!"); + setFile(null); + setUpload(false); + e.target.value = ""; + return; + } + } + validateAndSetFile(selectedFile); handleUpload(selectedFile); }; const validateAndSetFile = (file: File | null) => { - setFileError(""); - if (!file) return; const fileType = file.type; if (!fileType.includes("audio") && !fileType.includes("video")) { - setFileError("Please upload only audio or video files."); + showErrorToast("Please upload only audio or video files."); return; } @@ -131,7 +153,7 @@ function UploadPage() { }); // navigate('/preview'); } else { - setFileError("Please upload a file to continue."); + showErrorToast("Please upload a file to continue"); } }; @@ -178,6 +200,16 @@ function UploadPage() { setLogs((prevLogs) => [...prevLogs, formatLogMessage(`freqsplit/input: audio_class: ${res.data.audio_class}`)]) } } catch (error) { + showErrorToast("Failed to upload file"); + setUpload(false); + setResponse({ + audio_class: "", + file_uuid: "", + sr: 0, + spectrogram: "", + spec_sr: 0 + }); + setFile(null); console.error("Upload failed:", error); } }; @@ -205,6 +237,7 @@ function UploadPage() { : "transparent", transition: "all 0.3s ease", cursor: "pointer", + overflow: "auto" }} onDragOver={handleDragOver} onDragLeave={handleDragLeave} @@ -216,32 +249,34 @@ function UploadPage() { id="fileInput" style={{ display: "none" }} onChange={handleFileChange} - accept="audio/*,video/*" + accept="audio/*" disabled={!inputEnabled} /> - + {file ? file.name : "Drop your file here or click to browse files"} + + Max file size: 100MB + {file && ( - {file.type.includes("video") ? ( - - ) : ( - - )} + {file.type.includes("audio") ? : null} {file.type} - {(file.size / (1024 * 1024)).toFixed(2)} MB )} - {fileError && ( - - {fileError} - - )} -