From cf0df928b12a1446e0dda7b26679761730a0760d Mon Sep 17 00:00:00 2001 From: Oronemu Date: Sat, 10 Jan 2026 09:22:28 +0700 Subject: [PATCH] Fix app --- desktop/src/renderer/pages/DashboardPage.tsx | 48 ++++++++++++-------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/desktop/src/renderer/pages/DashboardPage.tsx b/desktop/src/renderer/pages/DashboardPage.tsx index 1b15c89..65a3963 100644 --- a/desktop/src/renderer/pages/DashboardPage.tsx +++ b/desktop/src/renderer/pages/DashboardPage.tsx @@ -75,24 +75,26 @@ export function DashboardPage() { // Check if we should track time: any tracked game is running + active assignment exists const isTrackingAssignment = !!(currentGame && currentAssignment && currentAssignment.status === 'active') - // Sync time to server + // Track base minutes at session start to avoid re-adding on each sync + const baseMinutesRef = useRef(0) + + // Sync time to server - use refs to avoid dependency issues const doSyncTime = useCallback(async () => { - if (!currentAssignment || !isTrackingAssignment) { + const assignment = useMarathonStore.getState().currentAssignment + if (!assignment || assignment.status !== 'active' || !sessionStartRef.current) { return } - // Calculate total minutes: previous tracked + current session - const sessionDuration = sessionStartRef.current - ? Math.floor((Date.now() - sessionStartRef.current) / 60000) - : 0 - const totalMinutes = currentAssignment.tracked_time_minutes + sessionDuration + // Calculate session duration only + const sessionMinutes = Math.floor((Date.now() - sessionStartRef.current) / 60000) + const totalMinutes = baseMinutesRef.current + sessionMinutes if (totalMinutes !== lastSyncedMinutesRef.current && totalMinutes > 0) { - console.log(`[Sync] Syncing ${totalMinutes} minutes for assignment ${currentAssignment.id}`) + console.log(`[Sync] Syncing ${totalMinutes} minutes for assignment ${assignment.id} (base: ${baseMinutesRef.current}, session: ${sessionMinutes})`) await syncTime(totalMinutes) lastSyncedMinutesRef.current = totalMinutes } - }, [currentAssignment, isTrackingAssignment, syncTime]) + }, [syncTime]) useEffect(() => { loadTrackedGames() @@ -134,16 +136,17 @@ export function DashboardPage() { useEffect(() => { let localTimerInterval: NodeJS.Timeout | null = null - if (isTrackingAssignment) { + if (isTrackingAssignment && currentAssignment) { // Start session if not already started if (!sessionStartRef.current) { sessionStartRef.current = Date.now() + // Store base minutes at session start + baseMinutesRef.current = currentAssignment.tracked_time_minutes || 0 + lastSyncedMinutesRef.current = baseMinutesRef.current + console.log(`[Sync] Session started, base minutes: ${baseMinutesRef.current}`) } - // Sync immediately when game starts - doSyncTime() - - // Setup periodic sync every 60 seconds + // Setup periodic sync every 60 seconds (don't sync immediately to avoid loops) syncIntervalRef.current = setInterval(() => { doSyncTime() }, 60000) @@ -157,12 +160,15 @@ export function DashboardPage() { } else { // Do final sync when game stops - if (syncIntervalRef.current) { + if (sessionStartRef.current) { doSyncTime() + } + if (syncIntervalRef.current) { clearInterval(syncIntervalRef.current) syncIntervalRef.current = null - sessionStartRef.current = null } + sessionStartRef.current = null + baseMinutesRef.current = 0 setLocalSessionSeconds(0) } @@ -175,7 +181,9 @@ export function DashboardPage() { clearInterval(localTimerInterval) } } - }, [isTrackingAssignment, doSyncTime]) + // Note: doSyncTime is intentionally excluded to avoid infinite loops + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isTrackingAssignment]) // Toggle monitoring const toggleMonitoring = async () => { @@ -222,9 +230,11 @@ export function DashboardPage() { // Playthrough assignment if (assignment.is_playthrough && assignment.playthrough_info) { - // Use localSessionSeconds for live display (updates every second) + // When actively tracking: use baseMinutesRef (set at session start) + current session + // Otherwise: use tracked_time_minutes from assignment + const baseMinutes = isTrackingAssignment ? baseMinutesRef.current : assignment.tracked_time_minutes const sessionSeconds = isTrackingAssignment ? localSessionSeconds : 0 - const totalSeconds = (assignment.tracked_time_minutes * 60) + sessionSeconds + const totalSeconds = (baseMinutes * 60) + sessionSeconds const totalMinutes = Math.floor(totalSeconds / 60) const trackedHours = totalMinutes / 60 const estimatedPoints = Math.floor(trackedHours * 30)