From d195a132b36bfe0b98a34a73d99c1b9a28b128c5 Mon Sep 17 00:00:00 2001 From: NimBold Date: Thu, 16 Jul 2026 17:23:43 +0330 Subject: [PATCH] perf(downloads): scale playlist rows efficiently --- src/components/DownloadItem.tsx | 50 +++++---------- src/components/DownloadTable.tsx | 107 ++++++++++++++++++++++--------- 2 files changed, 92 insertions(+), 65 deletions(-) diff --git a/src/components/DownloadItem.tsx b/src/components/DownloadItem.tsx index a622530..4887938 100644 --- a/src/components/DownloadItem.tsx +++ b/src/components/DownloadItem.tsx @@ -1,11 +1,8 @@ import React from 'react'; -import { useShallow } from 'zustand/react/shallow'; -import { useDownloadStore } from '../store/useDownloadStore'; import { useDownloadProgressStore } from '../store/downloadProgressStore'; import { Play, Pause, MoreVertical, Clock, ArrowUp, ArrowDown } from 'lucide-react'; import type { DownloadItem as DownloadItemType } from '../bindings/DownloadItem'; import { canPauseDownload, canStartDownload, startActionLabel } from '../utils/downloadActions'; -import { isActiveDownloadStatus } from '../utils/downloads'; import { downloadProgressColorClass, formatDownloadTotal, @@ -13,47 +10,35 @@ import { } from '../utils/downloadProgress'; interface DownloadItemProps { - downloadId: string; + download: DownloadItemType; index: number; + queueIndex: number; + queueLength: number; tableGridTemplate: string; setContextMenu: (menu: { x: number; y: number; id: string }) => void; handlePause: (id: string, skipConfirm?: boolean) => void; handleResume: (item: DownloadItemType) => void; getCategoryIcon: (category: string) => React.ReactNode; - selectedIds: Set; + isSelected: boolean; + onMoveInQueue: (id: string, direction: 'up' | 'down') => void; onClick: (e: React.MouseEvent, item: DownloadItemType) => void; } export const DownloadItem = React.memo(({ - downloadId, + download, index, + queueIndex, + queueLength, tableGridTemplate, setContextMenu, handlePause, handleResume, getCategoryIcon, - selectedIds, + isSelected, + onMoveInQueue, onClick, }) => { - const download = useDownloadStore(state => state.downloads.find(d => d.id === downloadId)); - const queueItems = useDownloadStore(useShallow(state => { - const item = state.downloads.find(candidate => candidate.id === downloadId); - if (!item) return []; - const queueId = item.queueId; - return state.downloads - .filter(candidate => - candidate.queueId === queueId && - candidate.status !== 'completed' && - !(isActiveDownloadStatus(candidate.status) && candidate.status !== 'queued') - ) - .sort((left, right) => (left.queuePosition ?? 0) - (right.queuePosition ?? 0)) - .map(candidate => candidate.id); - })); - const moveInQueue = useDownloadStore(state => state.moveInQueue); - const liveProgress = useDownloadProgressStore(state => state.progressMap[downloadId]); - const queueIndex = queueItems.indexOf(downloadId); - - if (!download) return null; + const liveProgress = useDownloadProgressStore(state => state.progressMap[download.id]); const displayFraction = download.status === 'downloading' ? liveProgress?.fraction ?? download.fraction ?? 0 @@ -83,7 +68,7 @@ export const DownloadItem = React.memo(({ return (
onClick(e, download)} onContextMenu={(e) => { @@ -138,8 +123,7 @@ export const DownloadItem = React.memo(({ style={{ width: `${displayFraction * 100}%` }} />
- (({
@@ -191,7 +174,6 @@ export const DownloadItem = React.memo(({
@@ -215,7 +197,7 @@ export const DownloadItem = React.memo(({ {(download.status === 'queued' || download.status === 'staged') && queueIndex !== -1 && ( <>