From 4bafe6bfe762ccca7a9f33402a0b5b26f39e2be5 Mon Sep 17 00:00:00 2001 From: diederbert <162878798+diederbert@users.noreply.github.com> Date: Wed, 13 Mar 2024 17:43:24 +0100 Subject: [PATCH] perf: Improve TorrentTile rendering performance (#1951) --- src/widgets/torrent/TorrentTile.tsx | 207 ++++++++++++++-------------- 1 file changed, 104 insertions(+), 103 deletions(-) diff --git a/src/widgets/torrent/TorrentTile.tsx b/src/widgets/torrent/TorrentTile.tsx index b030efc82..5ba2e2167 100644 --- a/src/widgets/torrent/TorrentTile.tsx +++ b/src/widgets/torrent/TorrentTile.tsx @@ -1,23 +1,22 @@ -import { type MRT_ColumnDef, MRT_Table, useMantineReactTable } from 'mantine-react-table'; import { Badge, Center, - createStyles, Flex, Group, Loader, Popover, Progress, - ScrollArea, Stack, Text, Title, + createStyles, } from '@mantine/core'; import { useElementSize } from '@mantine/hooks'; import { IconFileDownload } from '@tabler/icons-react'; import dayjs from 'dayjs'; import duration from 'dayjs/plugin/duration'; import relativeTime from 'dayjs/plugin/relativeTime'; +import { type MRT_ColumnDef, MRT_TableContainer, useMantineReactTable } from 'mantine-react-table'; import { useTranslation } from 'next-i18next'; import { useMemo } from 'react'; import { MIN_WIDTH_MOBILE } from '~/constants/constants'; @@ -109,7 +108,6 @@ function TorrentTile({ widget }: TorrentTileProps) { const filteredTorrents = filterTorrents(widget, torrents); - const difference = new Date().getTime() - dataUpdatedAt; const duration = dayjs.duration(difference, 'ms'); const humanizedDuration = duration.humanize(); @@ -117,90 +115,97 @@ function TorrentTile({ widget }: TorrentTileProps) { const ratioGlobal = getTorrentsRatio(widget, torrents, false); const ratioWithFilter = getTorrentsRatio(widget, torrents, true); - const columns = useMemo[]>(() => [ - { - id: 'dateAdded', - accessorFn: (row) => new Date(row.dateAdded), - header: 'dateAdded', - maxSize: 1, - }, - { - accessorKey: 'name', - header: t('card.table.header.name'), - Cell: ({ cell, row }) => ( - - - - {String(cell.getValue())} - - - - - - - ), - maxSize: 1, - size: 1, - }, - { - accessorKey: 'totalSelected', - header: t('card.table.header.size'), - Cell: ({ cell }) => formatSize(Number(cell.getValue())), - sortDescFirst: true, - maxSize: 1, - }, - { - accessorKey: 'uploadSpeed', - header: t('card.table.header.upload'), - Cell: ({ cell }) => formatSpeed(Number(cell.getValue())), - sortDescFirst: true, - maxSize: 1, - }, - { - accessorKey: 'downloadSpeed', - header: t('card.table.header.download'), - Cell: ({ cell }) => formatSpeed(Number(cell.getValue())), - sortDescFirst: true, - maxSize: 1, - }, - { - accessorKey: 'eta', - header: t('card.table.header.estimatedTimeOfArrival'), - Cell: ({ cell }) => formatETA(Number(cell.getValue())), - sortDescFirst: true, - maxSize: 1, - }, - { - accessorKey: 'progress', - header: t('card.table.header.progress'), - maxSize: 1, - Cell: ({ cell, row }) => ( - - {(Number(cell.getValue()) * 100).toFixed(1)}% - []>( + () => [ + { + id: 'dateAdded', + accessorFn: (row) => new Date(row.dateAdded), + header: 'dateAdded', + maxSize: 1, + }, + { + accessorKey: 'name', + header: t('card.table.header.name'), + Cell: ({ cell, row }) => ( + , - ), - sortDescFirst: true, - }, - ], []); + shadow="sm" + transitionProps={{ + transition: 'pop', + }} + > + + + {String(cell.getValue())} + + + + + + + ), + maxSize: 1, + size: 1, + }, + { + accessorKey: 'totalSelected', + header: t('card.table.header.size'), + Cell: ({ cell }) => formatSize(Number(cell.getValue())), + sortDescFirst: true, + maxSize: 1, + }, + { + accessorKey: 'uploadSpeed', + header: t('card.table.header.upload'), + Cell: ({ cell }) => formatSpeed(Number(cell.getValue())), + sortDescFirst: true, + maxSize: 1, + }, + { + accessorKey: 'downloadSpeed', + header: t('card.table.header.download'), + Cell: ({ cell }) => formatSpeed(Number(cell.getValue())), + sortDescFirst: true, + maxSize: 1, + }, + { + accessorKey: 'eta', + header: t('card.table.header.estimatedTimeOfArrival'), + Cell: ({ cell }) => formatETA(Number(cell.getValue())), + sortDescFirst: true, + maxSize: 1, + }, + { + accessorKey: 'progress', + header: t('card.table.header.progress'), + maxSize: 1, + Cell: ({ cell, row }) => ( + + + {(Number(cell.getValue()) * 100).toFixed(1)}% + + + , + + ), + sortDescFirst: true, + }, + ], + [] + ); const torrentsTable = useMantineReactTable({ columns, @@ -210,6 +215,9 @@ function TorrentTile({ widget }: TorrentTileProps) { enableMultiSort: true, enableColumnActions: false, enableColumnFilters: false, + enableRowVirtualization: true, + rowVirtualizerProps: { overscan: 20 }, + mantineTableContainerProps: { sx: { scrollbarWidth: 'none' } }, enableSorting: true, initialState: { showColumnFilters: false, @@ -238,7 +246,6 @@ function TorrentTile({ widget }: TorrentTileProps) { }, }); - if (isError) { return ( @@ -288,10 +295,8 @@ function TorrentTile({ widget }: TorrentTileProps) { } return ( - - - - + + {data.apps.some((x) => !x.success) && ( @@ -320,7 +325,7 @@ export const filterTorrents = (widget: ITorrent, torrents: TorrentTotalDownload[ (torrent) => !torrent.isCompleted || (widget.properties.displayActiveTorrents && - torrent.uploadSpeed > widget.properties.speedLimitOfActiveTorrents * 1024), + torrent.uploadSpeed > widget.properties.speedLimitOfActiveTorrents * 1024) ); } @@ -328,7 +333,7 @@ export const filterTorrents = (widget: ITorrent, torrents: TorrentTotalDownload[ result = filterTorrentsByLabels( result, widget.properties.labelFilter, - widget.properties.labelFilterIsWhitelist, + widget.properties.labelFilterIsWhitelist ); } @@ -348,7 +353,7 @@ const filterStaleTorrent = (widget: ITorrent, torrents: TorrentTotalDownload['to const filterTorrentsByLabels = ( torrents: TorrentTotalDownload['torrents'], labels: string[], - isWhitelist: boolean, + isWhitelist: boolean ) => { if (isWhitelist) { return torrents.filter((torrent) => torrent.label && labels.includes(torrent.label)); @@ -360,7 +365,7 @@ const filterTorrentsByLabels = ( export const getTorrentsRatio = ( widget: ITorrent, torrents: TorrentTotalDownload['torrents'], - applyAllFilter: boolean, + applyAllFilter: boolean ) => { if (applyAllFilter) { torrents = filterTorrents(widget, torrents); @@ -368,18 +373,14 @@ 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, - ); + let totalDownloadedSum = torrents.reduce((sum, torrent) => sum + torrent.totalDownloaded, 0); return totalDownloadedSum > 0 - ? torrents.reduce((sum, torrent) => sum + torrent.totalUploaded, 0) / - totalDownloadedSum + ? torrents.reduce((sum, torrent) => sum + torrent.totalUploaded, 0) / totalDownloadedSum : -1; };