perf: Improve TorrentTile rendering performance (#1951)

This commit is contained in:
diederbert
2024-03-13 17:43:24 +01:00
committed by GitHub
parent 184aa5eca6
commit 4bafe6bfe7

View File

@@ -1,23 +1,22 @@
import { type MRT_ColumnDef, MRT_Table, useMantineReactTable } from 'mantine-react-table';
import { import {
Badge, Badge,
Center, Center,
createStyles,
Flex, Flex,
Group, Group,
Loader, Loader,
Popover, Popover,
Progress, Progress,
ScrollArea,
Stack, Stack,
Text, Text,
Title, Title,
createStyles,
} from '@mantine/core'; } from '@mantine/core';
import { useElementSize } from '@mantine/hooks'; import { useElementSize } from '@mantine/hooks';
import { IconFileDownload } from '@tabler/icons-react'; import { IconFileDownload } from '@tabler/icons-react';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import duration from 'dayjs/plugin/duration'; import duration from 'dayjs/plugin/duration';
import relativeTime from 'dayjs/plugin/relativeTime'; import relativeTime from 'dayjs/plugin/relativeTime';
import { type MRT_ColumnDef, MRT_TableContainer, useMantineReactTable } from 'mantine-react-table';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { MIN_WIDTH_MOBILE } from '~/constants/constants'; import { MIN_WIDTH_MOBILE } from '~/constants/constants';
@@ -109,7 +108,6 @@ function TorrentTile({ widget }: TorrentTileProps) {
const filteredTorrents = filterTorrents(widget, torrents); const filteredTorrents = filterTorrents(widget, torrents);
const difference = new Date().getTime() - dataUpdatedAt; const difference = new Date().getTime() - dataUpdatedAt;
const duration = dayjs.duration(difference, 'ms'); const duration = dayjs.duration(difference, 'ms');
const humanizedDuration = duration.humanize(); const humanizedDuration = duration.humanize();
@@ -117,7 +115,8 @@ function TorrentTile({ widget }: TorrentTileProps) {
const ratioGlobal = getTorrentsRatio(widget, torrents, false); const ratioGlobal = getTorrentsRatio(widget, torrents, false);
const ratioWithFilter = getTorrentsRatio(widget, torrents, true); const ratioWithFilter = getTorrentsRatio(widget, torrents, true);
const columns = useMemo<MRT_ColumnDef<TorrentTotalDownload['torrents'][0]>[]>(() => [ const columns = useMemo<MRT_ColumnDef<TorrentTotalDownload['torrents'][0]>[]>(
() => [
{ {
id: 'dateAdded', id: 'dateAdded',
accessorFn: (row) => new Date(row.dateAdded), accessorFn: (row) => new Date(row.dateAdded),
@@ -138,11 +137,7 @@ function TorrentTile({ widget }: TorrentTileProps) {
}} }}
> >
<Popover.Target> <Popover.Target>
<Text <Text maw={'30vw'} size="xs" lineClamp={1}>
maw={'30vw'}
size="xs"
lineClamp={1}
>
{String(cell.getValue())} {String(cell.getValue())}
</Text> </Text>
</Popover.Target> </Popover.Target>
@@ -188,19 +183,29 @@ function TorrentTile({ widget }: TorrentTileProps) {
maxSize: 1, maxSize: 1,
Cell: ({ cell, row }) => ( Cell: ({ cell, row }) => (
<Flex> <Flex>
<Text className={useStyles().classes.noTextBreak}>{(Number(cell.getValue()) * 100).toFixed(1)}%</Text> <Text className={useStyles().classes.noTextBreak}>
{(Number(cell.getValue()) * 100).toFixed(1)}%
</Text>
<Progress <Progress
radius="lg" radius="lg"
color={ color={
Number(cell.getValue()) === 1 ? 'green' : row.original.state === 'paused' ? 'yellow' : 'blue' Number(cell.getValue()) === 1
? 'green'
: row.original.state === 'paused'
? 'yellow'
: 'blue'
} }
value={Number(cell.getValue()) * 100} value={Number(cell.getValue()) * 100}
size="lg" size="lg"
/>, />
</Flex>), ,
</Flex>
),
sortDescFirst: true, sortDescFirst: true,
}, },
], []); ],
[]
);
const torrentsTable = useMantineReactTable({ const torrentsTable = useMantineReactTable({
columns, columns,
@@ -210,6 +215,9 @@ function TorrentTile({ widget }: TorrentTileProps) {
enableMultiSort: true, enableMultiSort: true,
enableColumnActions: false, enableColumnActions: false,
enableColumnFilters: false, enableColumnFilters: false,
enableRowVirtualization: true,
rowVirtualizerProps: { overscan: 20 },
mantineTableContainerProps: { sx: { scrollbarWidth: 'none' } },
enableSorting: true, enableSorting: true,
initialState: { initialState: {
showColumnFilters: false, showColumnFilters: false,
@@ -238,7 +246,6 @@ function TorrentTile({ widget }: TorrentTileProps) {
}, },
}); });
if (isError) { if (isError) {
return ( return (
<Stack> <Stack>
@@ -288,10 +295,8 @@ function TorrentTile({ widget }: TorrentTileProps) {
} }
return ( return (
<Flex direction="column" sx={{ height: '100%' }} ref={ref}> <Flex direction="column" sx={{ height: '100%', isolation: 'isolate' }} ref={ref}>
<ScrollArea style={{ flexGrow: 1 }}> <MRT_TableContainer table={torrentsTable} />
<MRT_Table table={torrentsTable} />
</ScrollArea>
<Group spacing="sm"> <Group spacing="sm">
{data.apps.some((x) => !x.success) && ( {data.apps.some((x) => !x.success) && (
<Badge variant="dot" color="red"> <Badge variant="dot" color="red">
@@ -320,7 +325,7 @@ export const filterTorrents = (widget: ITorrent, torrents: TorrentTotalDownload[
(torrent) => (torrent) =>
!torrent.isCompleted || !torrent.isCompleted ||
(widget.properties.displayActiveTorrents && (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 = filterTorrentsByLabels(
result, result,
widget.properties.labelFilter, widget.properties.labelFilter,
widget.properties.labelFilterIsWhitelist, widget.properties.labelFilterIsWhitelist
); );
} }
@@ -348,7 +353,7 @@ const filterStaleTorrent = (widget: ITorrent, torrents: TorrentTotalDownload['to
const filterTorrentsByLabels = ( const filterTorrentsByLabels = (
torrents: TorrentTotalDownload['torrents'], torrents: TorrentTotalDownload['torrents'],
labels: string[], labels: string[],
isWhitelist: boolean, isWhitelist: boolean
) => { ) => {
if (isWhitelist) { if (isWhitelist) {
return torrents.filter((torrent) => torrent.label && labels.includes(torrent.label)); return torrents.filter((torrent) => torrent.label && labels.includes(torrent.label));
@@ -360,7 +365,7 @@ const filterTorrentsByLabels = (
export const getTorrentsRatio = ( export const getTorrentsRatio = (
widget: ITorrent, widget: ITorrent,
torrents: TorrentTotalDownload['torrents'], torrents: TorrentTotalDownload['torrents'],
applyAllFilter: boolean, applyAllFilter: boolean
) => { ) => {
if (applyAllFilter) { if (applyAllFilter) {
torrents = filterTorrents(widget, torrents); torrents = filterTorrents(widget, torrents);
@@ -368,18 +373,14 @@ export const getTorrentsRatio = (
torrents = filterTorrentsByLabels( torrents = filterTorrentsByLabels(
torrents, torrents,
widget.properties.labelFilter, widget.properties.labelFilter,
widget.properties.labelFilterIsWhitelist, widget.properties.labelFilterIsWhitelist
); );
} }
let totalDownloadedSum = torrents.reduce( let totalDownloadedSum = torrents.reduce((sum, torrent) => sum + torrent.totalDownloaded, 0);
(sum, torrent) => sum + torrent.totalDownloaded,
0,
);
return totalDownloadedSum > 0 return totalDownloadedSum > 0
? torrents.reduce((sum, torrent) => sum + torrent.totalUploaded, 0) / ? torrents.reduce((sum, torrent) => sum + torrent.totalUploaded, 0) / totalDownloadedSum
totalDownloadedSum
: -1; : -1;
}; };