import { useEffect, useState } from "react"; import { X, Download, CheckCircle2, XCircle, Clock, FileCheck, Trash2, HardDrive, Zap, Timer } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Badge } from "@/components/ui/badge"; import { GetDownloadQueue, ClearCompletedDownloads, ClearAllDownloads } from "../../wailsjs/go/main/App"; import { toastWithSound as toast } from "@/lib/toast-with-sound"; import { backend } from "../../wailsjs/go/models"; interface DownloadQueueProps { isOpen: boolean; onClose: () => void; } export function DownloadQueue({ isOpen, onClose }: DownloadQueueProps) { const [queueInfo, setQueueInfo] = useState(new backend.DownloadQueueInfo({ is_downloading: false, queue: [], current_speed: 0, total_downloaded: 0, session_start_time: 0, queued_count: 0, completed_count: 0, failed_count: 0, skipped_count: 0, })); useEffect(() => { if (!isOpen) return; const fetchQueue = async () => { try { const info = await GetDownloadQueue(); setQueueInfo(info); } catch (error) { console.error("Failed to get download queue:", error); } }; fetchQueue(); const interval = setInterval(fetchQueue, 500); return () => clearInterval(interval); }, [isOpen]); const handleClearHistory = async () => { try { await ClearCompletedDownloads(); const info = await GetDownloadQueue(); setQueueInfo(info); } catch (error) { console.error("Failed to clear history:", error); } }; const handleReset = async () => { try { await ClearAllDownloads(); const info = await GetDownloadQueue(); setQueueInfo(info); toast.success("Download queue reset"); } catch (error) { console.error("Failed to reset queue:", error); } }; const getStatusIcon = (status: string) => { switch (status) { case "downloading": return ; case "completed": return ; case "failed": return ; case "skipped": return ; case "queued": return ; default: return null; } }; const getStatusBadge = (status: string) => { const variants: Record = { downloading: "default", completed: "outline", failed: "destructive", skipped: "secondary", queued: "outline", }; return ( {status} ); }; const formatDuration = (startTimestamp: number) => { if (startTimestamp === 0) return "—"; const now = Math.floor(Date.now() / 1000); const durationSeconds = now - startTimestamp; const hours = Math.floor(durationSeconds / 3600); const minutes = Math.floor((durationSeconds % 3600) / 60); const seconds = durationSeconds % 60; if (hours > 0) { return `${hours}h ${minutes}m ${seconds}s`; } else if (minutes > 0) { return `${minutes}m ${seconds}s`; } else { return `${seconds}s`; } }; return (
Download Queue
{(queueInfo.completed_count > 0 || queueInfo.failed_count > 0 || queueInfo.skipped_count > 0) && ()}
Queued: {queueInfo.queued_count}
Completed: {queueInfo.completed_count}
Skipped: {queueInfo.skipped_count}
Failed: {queueInfo.failed_count}
Downloaded: {queueInfo.total_downloaded > 0 ? `${queueInfo.total_downloaded.toFixed(2)} MB` : "0.00 MB"}
Speed: {queueInfo.current_speed > 0 && queueInfo.is_downloading ? `${queueInfo.current_speed.toFixed(2)} MB/s` : "—"}
Duration: {queueInfo.session_start_time > 0 ? formatDuration(queueInfo.session_start_time) : "—"}
{queueInfo.queue.length === 0 ? (

No downloads in queue

) : (queueInfo.queue.map((item) => (
{getStatusIcon(item.status)}

{item.track_name}

{item.artist_name} {item.album_name && ` • ${item.album_name}`}

{getStatusBadge(item.status)}
{item.status === "downloading" && (
{item.progress > 0 ? `${item.progress.toFixed(2)} MB` : queueInfo.is_downloading && queueInfo.current_speed > 0 ? "Downloading..." : "Starting..."} {item.speed > 0 ? `${item.speed.toFixed(2)} MB/s` : queueInfo.current_speed > 0 ? `${queueInfo.current_speed.toFixed(2)} MB/s` : "—"}
)} {item.status === "completed" && (
{item.progress.toFixed(2)} MB
)} {item.status === "skipped" && (
File already exists
)} {item.status === "failed" && item.error_message && (
{item.error_message}
)} {(item.status === "completed" || item.status === "skipped") && item.file_path && (
{item.file_path}
)}
)))}
); }