From c4669ca5162bc380e44d7632e7749e8503f6e304 Mon Sep 17 00:00:00 2001 From: Manuel <30572287+manuel-rw@users.noreply.github.com> Date: Thu, 11 Jan 2024 18:10:30 +0100 Subject: [PATCH] feature: #1765 reduce transferred torrent data (#1798) --- src/server/api/routers/download.ts | 34 ++++++-- .../queue/NormalizedDownloadQueueResponse.ts | 20 ++++- src/widgets/torrent/TorrentQueueItem.tsx | 11 +-- src/widgets/torrent/TorrentTile.tsx | 82 +++++++++---------- 4 files changed, 84 insertions(+), 63 deletions(-) diff --git a/src/server/api/routers/download.ts b/src/server/api/routers/download.ts index 3ca83f6d2..15d4b1ff7 100644 --- a/src/server/api/routers/download.ts +++ b/src/server/api/routers/download.ts @@ -24,7 +24,7 @@ export const downloadRouter = createTRPCRouter({ .input( z.object({ configName: z.string(), - }) + }), ) .query(async ({ input }) => { const config = getConfig(input.configName); @@ -44,7 +44,7 @@ export const downloadRouter = createTRPCRouter({ return response; } catch (err: any) { Consola.error( - `Error communicating with your download client '${app.name}' (${app.id}): ${err}` + `Error communicating with your download client '${app.name}' (${app.id}): ${err}`, ); failedClients.push(app.id); return { @@ -67,7 +67,7 @@ export const downloadRouter = createTRPCRouter({ if (failedClients.length > 0) { Consola.warn( - `${failedClients.length} download clients failed. Please check your configuration and the above log` + `${failedClients.length} download clients failed. Please check your configuration and the above log`, ); } @@ -76,13 +76,31 @@ export const downloadRouter = createTRPCRouter({ }); const GetDataFromClient = async ( - app: ConfigAppType + app: ConfigAppType, ): Promise => { const reduceTorrent = (data: AllClientData): NormalizedDownloadAppStat => ({ type: 'torrent', appId: app.id, success: true, - torrents: data.torrents, + torrents: data.torrents.map((torrent) => ({ + name: torrent.name, + eta: torrent.eta, + state: torrent.state, + progress: torrent.progress, + totalSeeds: torrent.totalSeeds, + totalSelected: torrent.totalSelected, + totalPeers: torrent.totalPeers, + ratio: torrent.ratio, + uploadSpeed: torrent.uploadSpeed, + downloadSpeed: torrent.downloadSpeed, + isCompleted: torrent.isCompleted, + totalDownloaded: torrent.totalDownloaded, + totalUploaded: torrent.totalUploaded, + label: torrent.label, + queuePosition: torrent.queuePosition, + stateMessage: torrent.stateMessage, + dateAdded: torrent.dateAdded + })), totalDownload: data.torrents .map((torrent) => torrent.downloadSpeed) .reduce((acc, torrent) => acc + torrent, 0), @@ -100,7 +118,7 @@ const GetDataFromClient = async ( await new Deluge({ baseUrl: app.url, password: findField(app, 'password'), - }).getAllData() + }).getAllData(), ); } case 'transmission': { @@ -109,7 +127,7 @@ const GetDataFromClient = async ( baseUrl: app.url, username: findField(app, 'username'), password: findField(app, 'password'), - }).getAllData() + }).getAllData(), ); } case 'qBittorrent': { @@ -118,7 +136,7 @@ const GetDataFromClient = async ( baseUrl: app.url, username: findField(app, 'username'), password: findField(app, 'password'), - }).getAllData() + }).getAllData(), ); } case 'sabnzbd': { diff --git a/src/types/api/downloads/queue/NormalizedDownloadQueueResponse.ts b/src/types/api/downloads/queue/NormalizedDownloadQueueResponse.ts index a0f5f44ca..7415991f2 100644 --- a/src/types/api/downloads/queue/NormalizedDownloadQueueResponse.ts +++ b/src/types/api/downloads/queue/NormalizedDownloadQueueResponse.ts @@ -13,7 +13,25 @@ export type NormalizedDownloadAppStat = { export type TorrentTotalDownload = { type: 'torrent'; - torrents: NormalizedTorrent[]; + torrents: { + name: string; + state: NormalizedTorrent['state']; + totalSelected: number; + totalPeers: number; + totalSeeds: number; + eta: number; + progress: number; + ratio: number; + uploadSpeed: number; + downloadSpeed: number; + isCompleted: boolean; + totalDownloaded: number; + totalUploaded: number; + label?: string; + queuePosition: number; + stateMessage: string; + dateAdded: string; + }[]; totalDownload: number; totalUpload: number; }; diff --git a/src/widgets/torrent/TorrentQueueItem.tsx b/src/widgets/torrent/TorrentQueueItem.tsx index bf20ba86a..ac4416fea 100644 --- a/src/widgets/torrent/TorrentQueueItem.tsx +++ b/src/widgets/torrent/TorrentQueueItem.tsx @@ -1,5 +1,4 @@ /* eslint-disable @next/next/no-img-element */ -import { NormalizedTorrent } from '@ctrl/shared-torrent'; import { Badge, Flex, @@ -9,7 +8,6 @@ import { Progress, Stack, Text, - createStyles, useMantineTheme } from '@mantine/core'; import { @@ -25,9 +23,10 @@ import { import { useTranslation } from 'next-i18next'; import { humanFileSize } from '~/tools/humanFileSize'; import { AppType } from '~/types/app'; +import { TorrentTotalDownload } from '~/types/api/downloads/queue/NormalizedDownloadQueueResponse'; interface TorrentQueueItemProps { - torrent: NormalizedTorrent; + torrent: TorrentTotalDownload['torrents'][0]; app?: AppType; width: number; } @@ -147,9 +146,3 @@ export const TorrentQueuePopover = ({ torrent, app }: Omit ); }; - -const useStyles = createStyles(() => ({ - noTextBreak: { - whiteSpace: 'nowrap', - }, -})); diff --git a/src/widgets/torrent/TorrentTile.tsx b/src/widgets/torrent/TorrentTile.tsx index 7f10eff2a..b030efc82 100644 --- a/src/widgets/torrent/TorrentTile.tsx +++ b/src/widgets/torrent/TorrentTile.tsx @@ -1,10 +1,4 @@ -import { - MRT_Table, - useMantineReactTable, - type MRT_ColumnDef, -} from 'mantine-react-table'; - -import { NormalizedTorrent } from '@ctrl/shared-torrent'; +import { type MRT_ColumnDef, MRT_Table, useMantineReactTable } from 'mantine-react-table'; import { Badge, Center, @@ -26,12 +20,13 @@ import duration from 'dayjs/plugin/duration'; import relativeTime from 'dayjs/plugin/relativeTime'; import { useTranslation } from 'next-i18next'; import { useMemo } from 'react'; -import { useCardStyles } from '~/components/layout/Common/useCardStyles'; import { MIN_WIDTH_MOBILE } from '~/constants/constants'; import { calculateETA } from '~/tools/client/calculateEta'; import { humanFileSize } from '~/tools/humanFileSize'; -import { NormalizedDownloadQueueResponse } from '~/types/api/downloads/queue/NormalizedDownloadQueueResponse'; -import { AppIntegrationType } from '~/types/app'; +import { + NormalizedDownloadQueueResponse, + TorrentTotalDownload, +} from '~/types/api/downloads/queue/NormalizedDownloadQueueResponse'; import { useGetDownloadClientsQueue } from '../download-speed/useGetNetworkSpeed'; import { defineWidget } from '../helper'; @@ -41,8 +36,6 @@ import { TorrentQueuePopover } from './TorrentQueueItem'; dayjs.extend(duration); dayjs.extend(relativeTime); -const downloadAppTypes: AppIntegrationType['type'][] = ['deluge', 'qBittorrent', 'transmission']; - const definition = defineWidget({ id: 'torrents-status', icon: IconFileDownload, @@ -96,7 +89,6 @@ interface TorrentTileProps { function TorrentTile({ widget }: TorrentTileProps) { const { t } = useTranslation('modules/torrents-status'); const { width, ref } = useElementSize(); - const { classes } = useCardStyles(true); const { data, @@ -110,9 +102,9 @@ function TorrentTile({ widget }: TorrentTileProps) { dataUpdatedAt: number; } = useGetDownloadClientsQueue(); - let torrents: NormalizedTorrent[] = []; - if(!(isError || !data || data.apps.length === 0 || Object.values(data.apps).length < 1)) { - torrents = data.apps.flatMap((app) => (app.type === 'torrent' ? app.torrents : [])) + let torrents: TorrentTotalDownload['torrents'] = []; + if (!(isError || !data || data.apps.length === 0 || Object.values(data.apps).length < 1)) { + torrents = data.apps.flatMap((app) => (app.type === 'torrent' ? app.torrents : [])); } const filteredTorrents = filterTorrents(widget, torrents); @@ -125,29 +117,29 @@ function TorrentTile({ widget }: TorrentTileProps) { const ratioGlobal = getTorrentsRatio(widget, torrents, false); const ratioWithFilter = getTorrentsRatio(widget, torrents, true); - const columns = useMemo[]>(() => [ + const columns = useMemo[]>(() => [ { - id: "dateAdded", + id: 'dateAdded', accessorFn: (row) => new Date(row.dateAdded), - header: "dateAdded", - maxSize: 1 + header: 'dateAdded', + maxSize: 1, }, { accessorKey: 'name', header: t('card.table.header.name'), Cell: ({ cell, row }) => ( + withArrow + withinPortal + radius="lg" + shadow="sm" + transitionProps={{ + transition: 'pop', + }} + > @@ -160,35 +152,35 @@ function TorrentTile({ widget }: TorrentTileProps) { ), maxSize: 1, - size: 1 + size: 1, }, { accessorKey: 'totalSelected', header: t('card.table.header.size'), Cell: ({ cell }) => formatSize(Number(cell.getValue())), sortDescFirst: true, - maxSize: 1 + maxSize: 1, }, { accessorKey: 'uploadSpeed', header: t('card.table.header.upload'), Cell: ({ cell }) => formatSpeed(Number(cell.getValue())), sortDescFirst: true, - maxSize: 1 + maxSize: 1, }, { accessorKey: 'downloadSpeed', header: t('card.table.header.download'), Cell: ({ cell }) => formatSpeed(Number(cell.getValue())), sortDescFirst: true, - maxSize: 1 + maxSize: 1, }, { accessorKey: 'eta', header: t('card.table.header.estimatedTimeOfArrival'), Cell: ({ cell }) => formatETA(Number(cell.getValue())), sortDescFirst: true, - maxSize: 1 + maxSize: 1, }, { accessorKey: 'progress', @@ -321,14 +313,14 @@ function TorrentTile({ widget }: TorrentTileProps) { ); } -export const filterTorrents = (widget: ITorrent, torrents: NormalizedTorrent[]) => { +export const filterTorrents = (widget: ITorrent, torrents: TorrentTotalDownload['torrents']) => { let result = torrents; if (!widget.properties.displayCompletedTorrents) { result = result.filter( (torrent) => !torrent.isCompleted || (widget.properties.displayActiveTorrents && - torrent.uploadSpeed > widget.properties.speedLimitOfActiveTorrents * 1024) + torrent.uploadSpeed > widget.properties.speedLimitOfActiveTorrents * 1024), ); } @@ -336,7 +328,7 @@ export const filterTorrents = (widget: ITorrent, torrents: NormalizedTorrent[]) result = filterTorrentsByLabels( result, widget.properties.labelFilter, - widget.properties.labelFilterIsWhitelist + widget.properties.labelFilterIsWhitelist, ); } @@ -345,7 +337,7 @@ export const filterTorrents = (widget: ITorrent, torrents: NormalizedTorrent[]) return result; }; -const filterStaleTorrent = (widget: ITorrent, torrents: NormalizedTorrent[]) => { +const filterStaleTorrent = (widget: ITorrent, torrents: TorrentTotalDownload['torrents']) => { if (widget.properties.displayStaleTorrents) { return torrents; } @@ -354,9 +346,9 @@ const filterStaleTorrent = (widget: ITorrent, torrents: NormalizedTorrent[]) => }; const filterTorrentsByLabels = ( - torrents: NormalizedTorrent[], + torrents: TorrentTotalDownload['torrents'], labels: string[], - isWhitelist: boolean + isWhitelist: boolean, ) => { if (isWhitelist) { return torrents.filter((torrent) => torrent.label && labels.includes(torrent.label)); @@ -367,8 +359,8 @@ const filterTorrentsByLabels = ( export const getTorrentsRatio = ( widget: ITorrent, - torrents: NormalizedTorrent[], - applyAllFilter: boolean + torrents: TorrentTotalDownload['torrents'], + applyAllFilter: boolean, ) => { if (applyAllFilter) { torrents = filterTorrents(widget, torrents); @@ -376,18 +368,18 @@ export const getTorrentsRatio = ( torrents = filterTorrentsByLabels( torrents, widget.properties.labelFilter, - widget.properties.labelFilterIsWhitelist + widget.properties.labelFilterIsWhitelist, ); } let totalDownloadedSum = torrents.reduce( (sum, torrent) => sum + torrent.totalDownloaded, - 0 + 0, ); return totalDownloadedSum > 0 ? torrents.reduce((sum, torrent) => sum + torrent.totalUploaded, 0) / - totalDownloadedSum + totalDownloadedSum : -1; };