diff --git a/src/components/modules/downloads/DownloadsModule.tsx b/src/components/modules/downloads/DownloadsModule.tsx new file mode 100644 index 000000000..f9287a030 --- /dev/null +++ b/src/components/modules/downloads/DownloadsModule.tsx @@ -0,0 +1,120 @@ +import { Loader, Table, Text, Tooltip, Title, Group, Progress } from '@mantine/core'; +import { Download } from 'tabler-icons-react'; +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'; + +export const DownloadsModule: IModule = { + title: 'Download speeds', + 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 qBittorrentService = config.services + .filter((service) => service.type === 'qBittorrent') + .at(0); + const hideComplete: boolean = + (config?.modules?.[DownloadsModule.title]?.options?.hidecomplete?.value as boolean) ?? false; + + const [torrents, setTorrents] = useState([]); + + useEffect(() => { + if (qBittorrentService) { + axios.post('/api/modules/downloads', { ...qBittorrentService }).then((res) => { + setTorrents(res.data.torrents); + }); + setInterval(() => { + axios.post('/api/modules/downloads', { ...qBittorrentService }).then((res) => { + setTorrents(res.data.torrents); + }); + }, 3000); + } + }, []); + + if (!qBittorrentService) { + return ( + + Critical: No qBittorrent instance found in services. + + Add a qBittorrent service to view current downloads + + + + ); + } + + if (torrents.length === 0) { + return ; + } + + const ths = ( + + Name + Download + Upload + Progress + + ); + + const rows = torrents.map((torrent) => { + if (torrent.progress === 1 && hideComplete) { + return null; + } + const downloadSpeed = torrent.downloadSpeed / 1024 / 1024; + const uploadSpeed = torrent.uploadSpeed / 1024 / 1024; + return ( + + + + + {torrent.name} + + + + + {downloadSpeed > 0 ? `${downloadSpeed.toFixed(1)} Mb/s` : '-'} + + + {uploadSpeed > 0 ? `${uploadSpeed.toFixed(1)} Mb/s` : '-'} + + + {(torrent.progress * 100).toFixed(1)}% + + + + ); + }); + + return ( + + Your downloads + + {ths} + {rows} +
+
+ ); +} diff --git a/src/components/modules/downloads/index.ts b/src/components/modules/downloads/index.ts new file mode 100644 index 000000000..d3b2b4b7c --- /dev/null +++ b/src/components/modules/downloads/index.ts @@ -0,0 +1 @@ +export { DownloadsModule } from './DownloadsModule'; diff --git a/src/components/modules/index.ts b/src/components/modules/index.ts index 4b85fa930..410bf3b56 100644 --- a/src/components/modules/index.ts +++ b/src/components/modules/index.ts @@ -3,3 +3,4 @@ export * from './calendar'; export * from './search'; export * from './ping'; export * from './weather'; +export * from './downloads';