mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-11 22:06:17 +00:00
feat: enhance download tracking by adding speed history management in download slice
This commit is contained in:
@@ -13,6 +13,7 @@ export interface DownloadState {
|
||||
gamesWithDeletionInProgress: string[];
|
||||
extraction: ExtractionInfo | null;
|
||||
peakSpeeds: Record<string, number>;
|
||||
speedHistory: Record<string, number[]>;
|
||||
}
|
||||
|
||||
const initialState: DownloadState = {
|
||||
@@ -21,6 +22,7 @@ const initialState: DownloadState = {
|
||||
gamesWithDeletionInProgress: [],
|
||||
extraction: null,
|
||||
peakSpeeds: {},
|
||||
speedHistory: {},
|
||||
};
|
||||
|
||||
export const downloadSlice = createSlice({
|
||||
@@ -31,13 +33,25 @@ export const downloadSlice = createSlice({
|
||||
state.lastPacket = action.payload;
|
||||
if (!state.gameId && action.payload) state.gameId = action.payload.gameId;
|
||||
|
||||
// Track peak speed atomically when packet arrives
|
||||
// Track peak speed and speed history atomically when packet arrives
|
||||
if (action.payload?.gameId && action.payload.downloadSpeed != null) {
|
||||
const { gameId, downloadSpeed } = action.payload;
|
||||
|
||||
// Update peak speed if this is higher
|
||||
const currentPeak = state.peakSpeeds[gameId] || 0;
|
||||
if (downloadSpeed > currentPeak) {
|
||||
state.peakSpeeds[gameId] = downloadSpeed;
|
||||
}
|
||||
|
||||
// Update speed history for chart
|
||||
if (!state.speedHistory[gameId]) {
|
||||
state.speedHistory[gameId] = [];
|
||||
}
|
||||
state.speedHistory[gameId].push(downloadSpeed);
|
||||
// Keep only last 120 entries
|
||||
if (state.speedHistory[gameId].length > 120) {
|
||||
state.speedHistory[gameId].shift();
|
||||
}
|
||||
}
|
||||
},
|
||||
clearDownload: (state) => {
|
||||
@@ -85,6 +99,7 @@ export const downloadSlice = createSlice({
|
||||
},
|
||||
clearPeakSpeed: (state, action: PayloadAction<string>) => {
|
||||
state.peakSpeeds[action.payload] = 0;
|
||||
state.speedHistory[action.payload] = [];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -11,12 +11,10 @@ import { addMilliseconds } from "date-fns";
|
||||
import { DOWNLOADER_NAME } from "@renderer/constants";
|
||||
import {
|
||||
useAppSelector,
|
||||
useAppDispatch,
|
||||
useDownload,
|
||||
useLibrary,
|
||||
useDate,
|
||||
} from "@renderer/hooks";
|
||||
import { clearPeakSpeed } from "@renderer/features";
|
||||
|
||||
import "./download-group.scss";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -514,9 +512,9 @@ export function DownloadGroup({
|
||||
|
||||
const { formatDistance } = useDate();
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
// Get speed history and peak speeds from Redux (centralized state)
|
||||
const speedHistory = useAppSelector((state) => state.download.speedHistory);
|
||||
const peakSpeeds = useAppSelector((state) => state.download.peakSpeeds);
|
||||
const speedHistoryRef = useRef<Record<string, number[]>>({});
|
||||
const [dominantColors, setDominantColors] = useState<Record<string, string>>(
|
||||
{}
|
||||
);
|
||||
@@ -579,62 +577,8 @@ export function DownloadGroup({
|
||||
});
|
||||
}, [library, lastPacket?.gameId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!lastPacket?.gameId || lastPacket.downloadSpeed === undefined) return;
|
||||
|
||||
const gameId = lastPacket.gameId;
|
||||
const downloadSpeed = lastPacket.downloadSpeed;
|
||||
|
||||
if (!speedHistoryRef.current[gameId]) {
|
||||
speedHistoryRef.current[gameId] = [];
|
||||
}
|
||||
|
||||
speedHistoryRef.current[gameId].push(downloadSpeed);
|
||||
|
||||
if (speedHistoryRef.current[gameId].length > 120) {
|
||||
speedHistoryRef.current[gameId].shift();
|
||||
}
|
||||
}, [lastPacket]);
|
||||
|
||||
useEffect(() => {
|
||||
for (const game of library) {
|
||||
if (
|
||||
game.download &&
|
||||
game.download.progress < 0.01 &&
|
||||
game.download.status !== "paused"
|
||||
) {
|
||||
// Fresh download - clear any old data
|
||||
if (speedHistoryRef.current[game.id]?.length > 0) {
|
||||
speedHistoryRef.current[game.id] = [];
|
||||
dispatch(clearPeakSpeed(game.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [library, dispatch]);
|
||||
|
||||
useEffect(() => {
|
||||
const timeouts: NodeJS.Timeout[] = [];
|
||||
|
||||
for (const game of library) {
|
||||
if (
|
||||
game.download?.progress === 1 &&
|
||||
speedHistoryRef.current[game.id]?.length > 0
|
||||
) {
|
||||
const gameId = game.id;
|
||||
const timeout = setTimeout(() => {
|
||||
speedHistoryRef.current[gameId] = [];
|
||||
dispatch(clearPeakSpeed(gameId));
|
||||
}, 10_000);
|
||||
timeouts.push(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
return () => {
|
||||
for (const timeout of timeouts) {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
};
|
||||
}, [library, dispatch]);
|
||||
// Speed history and peak speeds are now tracked in Redux (in setLastPacket reducer)
|
||||
// No local effect needed - data is updated atomically when packets arrive
|
||||
|
||||
useEffect(() => {
|
||||
if (library.length > 0 && title === t("download_in_progress")) {
|
||||
@@ -839,7 +783,13 @@ export function DownloadGroup({
|
||||
? (lastPacket?.downloadSpeed ?? 0)
|
||||
: 0;
|
||||
const finalDownloadSize = getFinalDownloadSize(game);
|
||||
const peakSpeed = peakSpeeds[game.id] || 0;
|
||||
// Use lastPacket.gameId for lookup since that's the key used to store the data
|
||||
// Fall back to game.id if lastPacket is not available
|
||||
const dataKey = lastPacket?.gameId ?? game.id;
|
||||
const gameSpeedHistory = speedHistory[dataKey] ?? [];
|
||||
const storedPeak = peakSpeeds[dataKey];
|
||||
// Use stored peak if available and > 0, otherwise use current speed as initial value
|
||||
const peakSpeed = storedPeak !== undefined && storedPeak > 0 ? storedPeak : downloadSpeed;
|
||||
|
||||
let currentProgress = game.download?.progress || 0;
|
||||
if (isGameExtracting) {
|
||||
@@ -861,7 +811,7 @@ export function DownloadGroup({
|
||||
currentProgress={currentProgress}
|
||||
dominantColor={dominantColor}
|
||||
lastPacket={lastPacket}
|
||||
speedHistory={speedHistoryRef.current[game.id] || []}
|
||||
speedHistory={gameSpeedHistory}
|
||||
formatSpeed={formatSpeed}
|
||||
calculateETA={calculateETA}
|
||||
pauseDownload={pauseDownload}
|
||||
|
||||
Reference in New Issue
Block a user