Add a processing + progress bar

This commit is contained in:
Arkaprabha Chakraborty
2024-08-08 23:38:55 +05:30
parent 2881d8ffca
commit c3a2cca6b8
3 changed files with 87 additions and 8 deletions

Binary file not shown.

View File

@@ -8,6 +8,7 @@
"@testing-library/user-event": "^13.5.0",
"axios": "^1.7.3",
"react": "^18.3.1",
"react-confetti": "^6.1.0",
"react-dom": "^18.3.1",
"react-router-dom": "^6.26.0",
"react-scripts": "5.0.1",

View File

@@ -1,29 +1,41 @@
import React, { useState } from "react";
import React, { useState, useRef, useEffect } from "react";
import axios from "axios";
import { v4 as uuidv4 } from "uuid";
import Confetti from "react-confetti";
const DownloadForm = () => {
const [url, setUrl] = useState("");
const [quality, setQuality] = useState("720p");
const [message, setMessage] = useState("");
const [progress, setProgress] = useState(0);
const [isProcessing, setIsProcessing] = useState(false);
const [showConfetti, setShowConfetti] = useState(false);
const confettiRef = useRef(null);
const handleDownload = async (e) => {
e.preventDefault();
setMessage("Downloading...");
setMessage("Processing...");
setProgress(0);
setIsProcessing(true);
try {
const response = await axios.post(
`${process.env.REACT_APP_BACKEND_URL}/downlink/download`,
{ url, quality },
{
responseType: "blob", // Ensure the response is treated as a file
responseType: "blob",
onDownloadProgress: (progressEvent) => {
const total = progressEvent.total;
const current = progressEvent.loaded;
setProgress(Math.round((current / total) * 100));
},
},
);
// Extract the filename from the Content-Disposition header if present
const disposition = response.headers["content-disposition"];
const filename = disposition
? disposition.split("filename=")[1].replace(/"/g, "")
: "video.mp4"; // Default filename
: `${uuidv4()}.mp4`;
const link = document.createElement("a");
link.href = window.URL.createObjectURL(new Blob([response.data]));
@@ -31,14 +43,47 @@ const DownloadForm = () => {
link.click();
setMessage("Download complete");
setIsProcessing(false);
setShowConfetti(true);
} catch (error) {
setMessage("Download failed");
console.error(error);
setIsProcessing(false);
}
};
const getBarClass = () => {
if (message === "Download complete") return "bg-green-500";
if (message === "Download failed") return "bg-red-500";
return "bg-blue-500"; // Default color when not processing
};
const getBarStyle = () => {
if (message === "Download complete" || message === "Download failed") {
return { transition: "width 0.5s ease-in-out" };
}
return { transition: "width 0.5s ease-in-out" };
};
const getAnimationStyle = () => {
if (message === "Download complete" || message === "Download failed") {
return { animation: "none" };
}
return { animation: "loading 1.5s infinite" };
};
useEffect(() => {
if (showConfetti) {
const timer = setTimeout(() => {
setShowConfetti(false);
}, 5000);
return () => clearTimeout(timer);
}
}, [showConfetti]);
return (
<div className="p-4">
<div className="p-4 relative">
<form onSubmit={handleDownload} className="space-y-4">
<div>
<label
@@ -77,13 +122,46 @@ const DownloadForm = () => {
<div>
<button
type="submit"
className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-black hover:bg-gray-700 hover:fg-black focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-black hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
>
Download
</button>
</div>
</form>
{message && <p className="mt-4 text-sm text-gray-700">{message}</p>}
<div className="w-full bg-white rounded-full mt-4 h-3 relative overflow-hidden">
<div
className={`h-3 ${getBarClass()} rounded-full`}
style={{
width: `${progress}%`,
...getBarStyle(),
}}
></div>
{isProcessing && (
<div
className={`absolute top-0 left-0 w-full h-full bg-blue-300 rounded-full`}
style={getAnimationStyle()}
></div>
)}
</div>
{showConfetti && (
<div className="fixed top-0 left-0 w-full h-full z-50">
<Confetti
ref={confettiRef}
width={window.innerWidth}
height={window.innerHeight}
/>
</div>
)}
<style jsx>{`
@keyframes loading {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
}
`}</style>
</div>
);
};