Skip to content

feat(notifications): F022 browser rest timer and session reminder notifications - #111

Merged
rghamilton3 merged 7 commits into
mainfrom
worktree-feat+browser-notif
Apr 15, 2026
Merged

rghamilton3 merged 7 commits into
mainfrom
worktree-feat+browser-notif

Conversation

@rghamilton3

Copy link
Copy Markdown
Contributor

Summary

  • Extends the browser notification path to cover rest timer alerts and session reminders, bringing browser parity with the Tauri native experience for in-tab usage
  • Removes the "Session reminders require the native app" gate and replaces it with contextual browser permission status and a "tab must remain open" note
  • Adds 40 new tests (7 test files) covering all 14 spec assertions; full suite 2508/2508 passing

Changes

File Change
active-workout-store.ts _onRestExpired callback: fires on expiry, silent on skip/cleanup/finish/discard
notification-service.ts sendRestTimerNotification + sendSessionReminderNotification with contextual permission requests
use-active-workout.ts confirmSet passes onExpired callback + exercise/set context to startRestTimer
use-session-reminder-browser.ts New -- 60s polling hook, Supabase queries, once-per-day guard
_authenticated.tsx Mounts useSessionReminderBrowser() in authenticated layout
notification-settings.tsx BrowserPermissionStatus (granted/default/denied states), updated session reminders copy

Known limitation

advanceMinutes is not consumed in Phase 1 (no time-of-day column on scheduled_sessions). Matches Rust behavior. Documented in Spec.md. Will be addressed when session time fields are added.

Test plan

  • bun run test -- 2508/2508 passing
  • bun run lint -- clean
  • bun run build -- TypeScript + Vite build clean
  • Manual: start a short rest timer in browser, let it expire -- confirm system notification appears
  • Manual: enable session reminders in browser mode, confirm settings UI shows permission status
  • Manual: verify "Session reminders require the native app" string is absent from settings

@vercel

vercel Bot commented Apr 15, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ardent-forge Ready Ready Preview, Comment Apr 15, 2026 8:32pm

Phase 1 (Web Notifications API, tab-open only):
- rest timer expiry notification via onExpired callback on startRestTimer
- session reminder polling hook with 60s setInterval
- settings UI permission status display and copy updates

Out of scope: service workers, Web Push, Tauri changes (Phase 2 backlog)
…ifications

Extends the browser notification path to cover rest timer alerts and session
reminders, bringing browser parity with the Tauri native experience for
in-tab usage.

- active-workout-store: add _onRestExpired callback to startRestTimer; fires
  on natural expiry, silently cleared on skip/cleanup/finish/discard
- notification-service: add sendRestTimerNotification and
  sendSessionReminderNotification with contextual permission requests (D-4)
- use-active-workout: wire onExpired callback in confirmSet, reading prefs
  async and passing exercise/set context to the notification
- use-session-reminder-browser: new 60s polling hook with Supabase queries
  for active program, today's session, and logged workouts; once-per-day guard
- _authenticated: mount useSessionReminderBrowser in authenticated layout
- notification-settings: add BrowserPermissionStatus (granted/default/denied),
  remove "requires native app" gate, add "tab must remain open" note

Tasks: S001, S002, S003, S004, S005, S006
Feature: 022-Browser-Notifications
…open questions

- Steps.md: status -> Complete, last milestone updated
- Spec.md: mark open questions resolved, document advanceMinutes Phase 1
  limitation (no session time-of-day column, matches Rust behavior), add
  revision history entry

Feature: 022-Browser-Notifications
… guard correctness

- P16-001: Capture err in bare catch in getNotificationPreferences JSON parse
- P16-002: Add .catch() to discarded sendRestTimerNotification Promise in onExpired callback
- P16-003: Wrap new Notification() constructor in try/catch in all three send functions
- P16-004: Set _lastRemindedDate before firing notification to prevent Supabase query spam on failure
- P16-005: Switch setNotificationPreferences to safeParse with prefixed error log
- P16-006: Log console.error in update() guard clause before silent return
- P16-007: Use local calendar date (not UTC) for once-per-day reminder guard
- P16-008: Extract session_templates coercion with warn log when join returns no name
- P16-010: Add unmounted flag to BrowserPermissionStatus to prevent listener leak on unmount race

Review: Context/Reviews/0016-pr111-f022-browser-notifications-review.md
…rror branch tests

Review: Context/Reviews/0016-pr111-f022-browser-notifications-review.md
…session reminder

Add five tests covering all per-query error paths (activationErr, blockErr,
weekErr, sessErr, logErr) in use-session-reminder-browser. Each test asserts
the [session-reminder-browser] console.error fires with the correct prefix
and that sendSessionReminderNotification is not called.

Tasks: S008-T
Feature: 022-Browser-Notifications
@rghamilton3
rghamilton3 force-pushed the worktree-feat+browser-notif branch from 8fda7e5 to 1ef9232 Compare April 15, 2026 20:32
@rghamilton3
rghamilton3 merged commit 926962e into main Apr 15, 2026
4 checks passed

This branch was successfully deployed

1 active deployment
Preview — 1ef92320 Deployed Apr 15, 2026 by vercel[bot]
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.

1 participant