Skip to content

Enhance workout recovery and auto-save logic to prevent saving comple…#76

Merged
wulfland merged 5 commits into
mainfrom
fix-complete-workout
Feb 10, 2026
Merged

Enhance workout recovery and auto-save logic to prevent saving comple…#76
wulfland merged 5 commits into
mainfrom
fix-complete-workout

Conversation

@wulfland
Copy link
Copy Markdown
Owner

…ted workouts

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR tightens workout session recovery and auto-save behavior to avoid persisting/recovering completed workouts, aiming to prevent “resuming” a finished session.

Changes:

  • Prevent auto-save from running when a workout is marked completed.
  • Clear activeWorkout in localStorage earlier during workout completion flow.
  • Update recoverActiveWorkout() to ignore (and delete) completed workouts found in localStorage.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
src/hooks/useWorkoutSession.ts Adds guards around auto-save for completed workouts and changes when auto-saved state is cleared during endWorkout.
src/db/service.ts Ensures recovery ignores completed workouts and clears localStorage when they are encountered.

Comment thread src/hooks/useWorkoutSession.ts Outdated
Comment on lines 187 to 190
// Clear auto-saved data FIRST to prevent any race conditions
clearAutoSavedWorkout();

const duration = Math.round(
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In endWorkout, clearAutoSavedWorkout() is called before the DB write. If createWorkout/updateWorkout throws, the user loses the only recovery copy in localStorage (data loss). Also, clearing localStorage here doesn’t stop the existing auto-save interval, which can immediately re-write activeWorkout while the async DB write is in progress. Consider stopping the interval first (clear autoSaveTimerRef), performing the DB save in a try/catch, and only clearing activeWorkout after a successful save (or leaving it intact on failure).

Copilot uses AI. Check for mistakes.
Comment on lines 72 to +76
const save = () => {
autoSaveWorkout(workout);
// Double-check before saving
if (workout && isActive && !workout.completed) {
autoSaveWorkout(workout);
}
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The “double-check” inside save() doesn’t actually validate current state because workout/isActive are captured by the effect closure; if isActive is set to false, there’s a window before the effect cleanup runs where the interval can still fire and this check will still see the old isActive === true. If the goal is to prevent saves after ending/canceling, clear the interval synchronously in endWorkout/cancelWorkout and/or read workout/isActive from refs updated on render.

Copilot uses AI. Check for mistakes.
Comment thread src/db/service.ts Outdated
Comment on lines 630 to 636
// Don't recover completed workouts - they should be cleared
if (workout.completed) {
localStorage.removeItem('activeWorkout');
return null;
}

return workout;
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

recoverActiveWorkout() assumes the parsed JSON is a non-null object. If localStorage contains 'null' (or another non-object JSON value), workout.completed will throw. Add a guard after JSON.parse to validate the shape (e.g., if (!workout || typeof workout !== 'object') { ... }) before reading properties, and consider clearing the bad activeWorkout entry.

Suggested change
// Don't recover completed workouts - they should be cleared
if (workout.completed) {
localStorage.removeItem('activeWorkout');
return null;
}
return workout;
// If the parsed value is not a non-null object, treat as corrupted data
if (!workout || typeof workout !== 'object') {
localStorage.removeItem('activeWorkout');
return null;
}
// Don't recover completed workouts - they should be cleared
if ((workout as import('../types/models').Workout).completed) {
localStorage.removeItem('activeWorkout');
return null;
}
return workout as import('../types/models').Workout;

Copilot uses AI. Check for mistakes.
Comment thread src/db/service.ts Outdated
Comment on lines +610 to +634
@@ -626,6 +627,12 @@ export function recoverActiveWorkout():
return value;
});

// Don't recover completed workouts - they should be cleared
if (workout.completed) {
localStorage.removeItem('activeWorkout');
return null;
}
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new recovery behavior (auto-clearing activeWorkout when completed is true) isn’t covered by tests. Since src/db/service.test.ts exists, add unit tests for recoverActiveWorkout() covering: missing key, malformed JSON/non-object JSON, completed workout (clears + returns null), and incomplete workout (returns revived Dates).

Copilot uses AI. Check for mistakes.
@wulfland
Copy link
Copy Markdown
Owner Author

@copilot open a new pull request to apply changes based on the comments in this thread

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 10, 2026

@wulfland I've opened a new pull request, #77, to work on those changes. Once the pull request is ready, I'll request review from you.

Copilot AI and others added 3 commits February 10, 2026 09:05
Co-authored-by: wulfland <5276337+wulfland@users.noreply.github.com>
Co-authored-by: wulfland <5276337+wulfland@users.noreply.github.com>
Fix workout recovery race conditions and add validation for corrupted state
@wulfland wulfland enabled auto-merge February 10, 2026 09:10
@wulfland wulfland merged commit 8216e93 into main Feb 10, 2026
4 checks passed
@wulfland wulfland deleted the fix-complete-workout branch February 10, 2026 09:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants