import { Table, Text, Tooltip, Title, Group, Progress, Skeleton, ScrollArea, Center, Image, } from '@mantine/core'; import { IconDownload as Download } from '@tabler/icons'; import { useEffect, useState } from 'react'; import axios from 'axios'; import { NormalizedTorrent } from '@ctrl/shared-torrent'; import { IModule } from '../modules'; import { useConfig } from '../../../tools/state'; import { AddItemShelfButton } from '../../AppShelf/AddAppShelfItem'; import { useSetSafeInterval } from '../../../tools/hooks/useSetSafeInterval'; import { useViewportSize } from '@mantine/hooks'; import { humanFileSize } from '../../../tools/humanFileSize'; export const DownloadsModule: IModule = { title: 'Torrent', description: 'Show the current download speed of supported services', icon: Download, component: DownloadComponent, options: { hidecomplete: { name: 'Hide completed torrents', value: false, }, }, }; export default function DownloadComponent() { const { config } = useConfig(); const { height, width } = useViewportSize(); const downloadServices = config.services.filter( (service) => service.type === 'qBittorrent' || service.type === 'Transmission' || service.type === 'Deluge' ) ?? []; const hideComplete: boolean = (config?.modules?.[DownloadsModule.title]?.options?.hidecomplete?.value as boolean) ?? false; const [torrents, setTorrents] = useState([]); const setSafeInterval = useSetSafeInterval(); const [isLoading, setIsLoading] = useState(true); useEffect(() => { setIsLoading(true); if (downloadServices.length === 0) return; setSafeInterval(() => { // Send one request with each download service inside axios.post('/api/modules/downloads', { config }).then((response) => { setTorrents(response.data); setIsLoading(false); }); }, 5000); }, [config.services]); if (downloadServices.length === 0) { return ( No supported download clients found! Add a download service to view your current downloads... ); } if (isLoading) { return ( <> ); } const ths = ( Name Size {width > 576 ? Down : ``} {width > 576 ? Up : ``} ETA Progress ); // Loop over qBittorrent torrents merging with deluge torrents const rows = torrents .filter((torrent) => !(torrent.progress === 1 && hideComplete)) .map((torrent) => { const downloadSpeed = torrent.downloadSpeed / 1024 / 1024; const uploadSpeed = torrent.uploadSpeed / 1024 / 1024; const size = torrent.totalSelected; // Convert Seconds to readable format. function calculateETA(givenSeconds: number) { if (givenSeconds > 86399) { // No return ">1d" } const time = new Date(givenSeconds * 1000).toISOString(); const hours = parseInt(time.substring(11,13)); const minutes = parseInt(time.substring(14,16)); const seconds = parseInt(time.substring(17,19)); var str = ""; // If tree go brr if (hours > 0) { str = `${hours}h `; } if (minutes > 0) { str = `${str}${minutes}m ` } if (seconds > 0) { str = `${str}${seconds}s`; } return str.trim(); } return ( {torrent.name} {humanFileSize(size)} {width > 576 ? {downloadSpeed > 0 ? `${downloadSpeed.toFixed(1)} Mb/s` : '-'} : ``} {width > 576 ? {uploadSpeed > 0 ? `${uploadSpeed.toFixed(1)} Mb/s` : '-'} : ``} {torrent.eta <= 0 ? '∞' : calculateETA(torrent.eta)} {(torrent.progress * 100).toFixed(1)}% ); }); const easteregg = (
); return ( {rows.length > 0 ? ( {ths}{rows}
) : ( easteregg )}
); }