Implement background timer notifications via service worker#28
Merged
Conversation
- Service worker now owns its own setTimeout for the rest timer so notifications fire even when the main thread is throttled/suspended by the browser while the app is backgrounded. The app sends TIMER_START (with expectedEndTime) to the SW when a rest timer begins and TIMER_CANCEL when it is skipped, completed, or abandoned. - When the main thread fires the notification (app foregrounded), it cancels the SW timer first to prevent duplicate notifications. - AudioContext.resume() is called before starting the oscillator so the beep plays correctly after the browser has suspended the audio context (common on mobile after backgrounding). https://claude.ai/code/session_01WqokDmx5PoSQULQgS7iJj5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR implements reliable background timer notifications by delegating timer scheduling to the service worker. This ensures notifications fire even when the main thread is throttled or suspended by the browser (common on mobile after backgrounding).
Key Changes
Service Worker Timer Scheduling: Modified
public/sw.jsto maintain its own background timeout that fires notifications independently of the main thread. The SW now handlesTIMER_STARTandTIMER_CANCELmessages to manage the background timer lifecycle.Main Thread Communication: Added
scheduleBackgroundTimerNotification()andcancelBackgroundTimerNotification()functions insrc/ui/notifications.tsto post timer events to the service worker.Timer Integration: Updated
src/ui/workout.tsto:scheduleBackgroundTimerNotification()when a rest timer startscancelBackgroundTimerNotification()when the timer completes, is skipped, or the workout endsAudioContext Resume: Enhanced
fireTimerNotification()insrc/ui/notifications.tsto callAudioContext.resume()before playing the beep sound. This prevents audio from being stuck in a suspended state after the browser has been backgrounded (common on mobile).Comprehensive E2E Tests: Added
e2e/background-timer.spec.tswith four test cases covering:Implementation Details
The background timer works by having the service worker calculate the delay from the current time to the expected end time, then scheduling its own
setTimeout(). This approach is more reliable than relying on the main thread's timer loop, which can be suspended by the browser. The main thread still maintains its own timer for UI updates, but the notification is guaranteed by the SW's independent scheduling.https://claude.ai/code/session_01WqokDmx5PoSQULQgS7iJj5