From 77b6f1b2ad6f6d98153d2c10fe8693c770180b54 Mon Sep 17 00:00:00 2001 From: Moyasee Date: Sat, 13 Dec 2025 16:10:57 +0200 Subject: [PATCH] feat: add peak speed tracking and management in download slice --- src/renderer/src/features/download-slice.ts | 17 +++++++ .../src/pages/downloads/download-group.tsx | 47 +++++++++---------- 2 files changed, 40 insertions(+), 24 deletions(-) diff --git a/src/renderer/src/features/download-slice.ts b/src/renderer/src/features/download-slice.ts index 0330cca3..ae0c9c9d 100644 --- a/src/renderer/src/features/download-slice.ts +++ b/src/renderer/src/features/download-slice.ts @@ -12,6 +12,7 @@ export interface DownloadState { gameId: string | null; gamesWithDeletionInProgress: string[]; extraction: ExtractionInfo | null; + peakSpeeds: Record; } const initialState: DownloadState = { @@ -19,6 +20,7 @@ const initialState: DownloadState = { gameId: null, gamesWithDeletionInProgress: [], extraction: null, + peakSpeeds: {}, }; export const downloadSlice = createSlice({ @@ -62,6 +64,19 @@ export const downloadSlice = createSlice({ clearExtraction: (state) => { state.extraction = null; }, + updatePeakSpeed: ( + state, + action: PayloadAction<{ gameId: string; speed: number }> + ) => { + const { gameId, speed } = action.payload; + const currentPeak = state.peakSpeeds[gameId] || 0; + if (speed > currentPeak) { + state.peakSpeeds[gameId] = speed; + } + }, + clearPeakSpeed: (state, action: PayloadAction) => { + state.peakSpeeds[action.payload] = 0; + }, }, }); @@ -72,4 +87,6 @@ export const { removeGameFromDeleting, setExtractionProgress, clearExtraction, + updatePeakSpeed, + clearPeakSpeed, } = downloadSlice.actions; diff --git a/src/renderer/src/pages/downloads/download-group.tsx b/src/renderer/src/pages/downloads/download-group.tsx index 52fbcdfd..56ab398b 100644 --- a/src/renderer/src/pages/downloads/download-group.tsx +++ b/src/renderer/src/pages/downloads/download-group.tsx @@ -11,10 +11,12 @@ import { addMilliseconds } from "date-fns"; import { DOWNLOADER_NAME } from "@renderer/constants"; import { useAppSelector, + useAppDispatch, useDownload, useLibrary, useDate, } from "@renderer/hooks"; +import { updatePeakSpeed, clearPeakSpeed } from "@renderer/features"; import "./download-group.scss"; import { useTranslation } from "react-i18next"; @@ -512,7 +514,8 @@ export function DownloadGroup({ const { formatDistance } = useDate(); - const [peakSpeeds, setPeakSpeeds] = useState>({}); + const dispatch = useAppDispatch(); + const peakSpeeds = useAppSelector((state) => state.download.peakSpeeds); const speedHistoryRef = useRef>({}); const [dominantColors, setDominantColors] = useState>( {} @@ -577,28 +580,23 @@ export function DownloadGroup({ }, [library, lastPacket?.gameId]); useEffect(() => { - if (lastPacket?.gameId && lastPacket.downloadSpeed !== undefined) { - const gameId = lastPacket.gameId; + if (!lastPacket?.gameId || lastPacket.downloadSpeed === undefined) return; - const currentPeak = peakSpeeds[gameId] || 0; - if (lastPacket.downloadSpeed > currentPeak) { - setPeakSpeeds((prev) => ({ - ...prev, - [gameId]: lastPacket.downloadSpeed, - })); - } + const gameId = lastPacket.gameId; + const downloadSpeed = lastPacket.downloadSpeed; - if (!speedHistoryRef.current[gameId]) { - speedHistoryRef.current[gameId] = []; - } + dispatch(updatePeakSpeed({ gameId, speed: downloadSpeed })); - speedHistoryRef.current[gameId].push(lastPacket.downloadSpeed); - - if (speedHistoryRef.current[gameId].length > 120) { - speedHistoryRef.current[gameId].shift(); - } + if (!speedHistoryRef.current[gameId]) { + speedHistoryRef.current[gameId] = []; } - }, [lastPacket?.gameId, lastPacket?.downloadSpeed, peakSpeeds]); + + speedHistoryRef.current[gameId].push(downloadSpeed); + + if (speedHistoryRef.current[gameId].length > 120) { + speedHistoryRef.current[gameId].shift(); + } + }, [lastPacket, dispatch]); useEffect(() => { for (const game of library) { @@ -610,11 +608,11 @@ export function DownloadGroup({ // Fresh download - clear any old data if (speedHistoryRef.current[game.id]?.length > 0) { speedHistoryRef.current[game.id] = []; - setPeakSpeeds((prev) => ({ ...prev, [game.id]: 0 })); + dispatch(clearPeakSpeed(game.id)); } } } - }, [library]); + }, [library, dispatch]); useEffect(() => { const timeouts: NodeJS.Timeout[] = []; @@ -624,9 +622,10 @@ export function DownloadGroup({ game.download?.progress === 1 && speedHistoryRef.current[game.id]?.length > 0 ) { + const gameId = game.id; const timeout = setTimeout(() => { - speedHistoryRef.current[game.id] = []; - setPeakSpeeds((prev) => ({ ...prev, [game.id]: 0 })); + speedHistoryRef.current[gameId] = []; + dispatch(clearPeakSpeed(gameId)); }, 10_000); timeouts.push(timeout); } @@ -637,7 +636,7 @@ export function DownloadGroup({ clearTimeout(timeout); } }; - }, [library]); + }, [library, dispatch]); useEffect(() => { if (library.length > 0 && title === t("download_in_progress")) {