Skip to main content

Overview

The DownloadManager component provides a comprehensive interface for managing download tasks. It displays active, completed, and failed downloads with real-time progress updates, speed monitoring, and detailed download information.

Props

downloads
DownloadTask[]
required
Array of download tasks to display. See DownloadTask type for details.
onCancel
(id: string) => void
required
Callback function called when a user cancels an active download.
onRemove
(id: string) => void
required
Callback function called when a user removes a download from the list.
onRetry
(id: string) => void
required
Callback function called when a user retries a failed download.
onDownloadFile
(id: string) => void
required
Callback function called when a user downloads a completed file.
apiUrl
string
required
Base URL of the backend API for resolving thumbnail URLs.

Features

Download Filtering

Filter downloads by status using the built-in filter pills:
  • All: Show all downloads
  • Active: Only pending, downloading, and processing tasks
  • Completed: Only successfully completed downloads
  • Error: Only failed downloads

Real-time Progress Tracking

  • Circular Progress: Mini circular progress indicator on download cards
  • Linear Progress Bar: Detailed progress bar showing download and buffer status
  • Speed Monitor: Live download speed (e.g., “2.5 MB/s”)
  • ETA: Estimated time remaining
  • Byte Counter: Downloaded bytes vs. total file size

Download States

The component handles all download states:
StatusDescriptionActions Available
pendingQueued, waiting to startCancel, Remove
downloadingActively downloadingCancel, Remove
processingPost-download processing (e.g., merging audio+video)Cancel, Remove
completedSuccessfully finishedDownload, Remove
errorFailed with errorRetry, Remove
cancelledUser cancelledRemove

Detail Panel

Click any download to open a detail panel showing:
  • Large circular progress indicator
  • Video thumbnail and title
  • Quality/format information
  • Detailed statistics (status, progress, speed, ETA, file size)
  • Start and completion timestamps
  • Error messages (if failed)
  • Quick action buttons

Theme Support

Fully supports dark and light themes using the useTheme hook with dynamic class names.

Usage Example

import { DownloadManager } from '@/components/downloader/DownloadManager';
import type { DownloadTask } from '@/types/downloader';
import { useState } from 'react';

function DownloadsPage() {
  const [downloads, setDownloads] = useState<DownloadTask[]>([
    {
      id: '1',
      url: 'https://youtube.com/watch?v=abc123',
      title: 'Amazing Tutorial Video',
      status: 'downloading',
      progress: 45.5,
      speed: '3.2 MB/s',
      eta: '2m 15s',
      thumbnail: '/thumbnails/abc123.jpg',
      format_note: '1080p (mp4)',
      filesize: 157286400, // 150 MB
      downloaded_bytes: 71557939, // ~68 MB
      is_playlist: false,
      playlist_index: 0,
      playlist_total: 0,
      quality: '1080p',
      download_type: 'video',
      created_at: '2024-01-15T10:30:00Z',
    },
  ]);

  const handleCancel = (id: string) => {
    // Cancel download via API
    fetch(`/api/downloads/${id}/cancel`, { method: 'POST' });
    setDownloads(prev => 
      prev.map(d => d.id === id ? { ...d, status: 'cancelled' } : d)
    );
  };

  const handleRemove = (id: string) => {
    setDownloads(prev => prev.filter(d => d.id !== id));
  };

  const handleRetry = (id: string) => {
    // Retry download via API
    fetch(`/api/downloads/${id}/retry`, { method: 'POST' });
  };

  const handleDownloadFile = (id: string) => {
    const download = downloads.find(d => d.id === id);
    if (download?.filename) {
      window.open(`/api/downloads/${id}/file`, '_blank');
    }
  };

  return (
    <div className="h-screen">
      <DownloadManager
        downloads={downloads}
        onCancel={handleCancel}
        onRemove={handleRemove}
        onRetry={handleRetry}
        onDownloadFile={handleDownloadFile}
        apiUrl="http://localhost:8000"
      />
    </div>
  );
}

WebSocket Integration

For real-time updates, integrate with WebSocket to receive progress updates:
import { useEffect } from 'react';

function DownloadsPageWithWebSocket() {
  const [downloads, setDownloads] = useState<DownloadTask[]>([]);

  useEffect(() => {
    const ws = new WebSocket('ws://localhost:8000/ws/downloads');

    ws.onmessage = (event) => {
      const update = JSON.parse(event.data);
      
      setDownloads(prev => {
        const existing = prev.find(d => d.id === update.id);
        if (existing) {
          // Update existing download
          return prev.map(d => d.id === update.id ? { ...d, ...update } : d);
        } else {
          // Add new download
          return [...prev, update];
        }
      });
    };

    return () => ws.close();
  }, []);

  // ... rest of component
}

Responsive Design

The component is fully responsive:
  • Mobile: Stacked layout with vertical scrolling
  • Tablet: Two-column layout when detail panel is open
  • Desktop: Side-by-side list and detail panels

Helper Functions

The component includes useful utilities:

formatBytes

Converts bytes to human-readable format:
formatBytes(157286400) // "150.00 MB"
formatBytes(1024) // "1.00 KB"

formatDate

Formats ISO date strings to localized format:
formatDate('2024-01-15T10:30:00Z') // "15 ene, 10:30"

Integration with YouTubeExplorer

Combine with YouTubeExplorer for a complete download workflow:
import { YouTubeExplorer } from '@/components/downloader/YouTubeExplorer';
import { DownloadManager } from '@/components/downloader/DownloadManager';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';

function DownloaderApp() {
  const [downloads, setDownloads] = useState<DownloadTask[]>([]);

  const handleDownload = async (url: string, options: DownloadOptions) => {
    const response = await fetch('/api/download', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ url, ...options }),
    });
    const newTask = await response.json();
    setDownloads(prev => [...prev, newTask]);
  };

  return (
    <Tabs defaultValue="explorer">
      <TabsList>
        <TabsTrigger value="explorer">Explorer</TabsTrigger>
        <TabsTrigger value="downloads">Downloads</TabsTrigger>
      </TabsList>
      <TabsContent value="explorer">
        <YouTubeExplorer onDownload={handleDownload} apiUrl="http://localhost:8000" />
      </TabsContent>
      <TabsContent value="downloads">
        <DownloadManager
          downloads={downloads}
          onCancel={handleCancel}
          onRemove={handleRemove}
          onRetry={handleRetry}
          onDownloadFile={handleDownloadFile}
          apiUrl="http://localhost:8000"
        />
      </TabsContent>
    </Tabs>
  );
}

Source Code Reference

The DownloadManager component is located at:
  • /workspace/source/src/components/downloader/DownloadManager.tsx:21-427
Related components:
  • CircularProgress component at /workspace/source/src/components/downloader/CircularProgress.tsx