screen-locker/stronglift_replacement/workout_app/lib/services
Krzysztof kuhy Rudnicki b6e89b93dc
Some checks failed
dependency freshness / dependencies on newest stable (push) Has been cancelled
md-naming / markdown naming convention (push) Has been cancelled
pre-commit / pre-commit (push) Has been cancelled
Tests / test (push) Has been cancelled
Tests / lock-popup-safety (push) Has been cancelled
release-apk / release (APK) (push) Has been cancelled
workout_app: run the break countdown in a foreground service with notifications
The between-set break never finished once the phone's screen was off. Three
independent causes (worked through on-device on 2026-09-12; left
uncommitted awaiting the go-ahead, committed here as-is plus one pin bump):

1. The countdown was not wall-clock: `_breakRemaining--` on a
   Timer.periodic, which Android throttles and Doze suspends in a
   backgrounded isolate, so the counter stalled and _onBreakFinished()
   never fired. Now a BreakClock deadline on the wall clock.
2. An expired break was silently dropped on restore (`if (remaining > 0)`
   only) — now cued and logged.
3. No notification infrastructure at all: no package, no
   POST_NOTIFICATIONS / FOREGROUND_SERVICE / WAKE_LOCK.

Now: flutter_foreground_task runs the countdown in a service isolate that
survives BACK and the screen lock; flutter_local_notifications shows an
ongoing "Workout A · break m:ss / Next: …" notification with −1 rep / Done
actions and a "Break over" alert on its own channel (raw break_end sound,
vibration). Button presses go through a persisted BreakIntent queue the
screen drains on resume, so a press with the app killed is not lost.
Finish and Reset stop the service; a startup reaper handles the crash case.

Verified on the phone with the screen off and locked: service alive and
ticking while Dozing, both notifications on the lock screen, channel
importance 5 with the break_end sound. Not verifiable from adb (receiver is
RECEIVER_NOT_EXPORTED): an actual action-button tap, and a true recents
swipe — see stronglift_replacement/TODO-workout-app-v2.md.

Also fixed en route: the break-end sound had never played in any widget
test (AssetSource needs path_provider, which nothing faked, and the failure
was swallowed by catchError); the queue's prune wrote back a stale list.

This commit additionally:
- takes the freshness gate's bump flutter_local_notifications 22.3.1;
- restores web/package.json to HEAD (the tree held a stale pre-bump copy);
- gives scripts/check_flutter_coverage.sh a FLUTTER_TEST_CONCURRENCY knob:
  the default one-isolate-per-core run peaks over 4 GiB and is OOM-killed
  under the resource cap. Default behaviour unchanged.

Gate: flutter analyze clean, 511 tests, 3187/3187 lines (100%), pre-commit
green. Not re-installed on the phone for the 22.3.1 pin: no device attached
at commit time.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C7vgacLhb4WJjxuVj2QLEP
2026-09-13 20:28:36 +02:00
..
backup_service_session.dart Split backup_service.dart; partly split workout_sync_service.dart 2026-08-15 21:38:42 +02:00
backup_service.dart Split backup_service.dart; partly split workout_sync_service.dart 2026-08-15 21:38:42 +02:00
break_clock.dart workout_app: run the break countdown in a foreground service with notifications 2026-09-13 20:28:36 +02:00
break_intent_queue.dart workout_app: run the break countdown in a foreground service with notifications 2026-09-13 20:28:36 +02:00
break_intent_store.dart workout_app: run the break countdown in a foreground service with notifications 2026-09-13 20:28:36 +02:00
break_notification_text.dart workout_app: run the break countdown in a foreground service with notifications 2026-09-13 20:28:36 +02:00
break_service_controller.dart workout_app: run the break countdown in a foreground service with notifications 2026-09-13 20:28:36 +02:00
break_service_port_flutter.dart workout_app: run the break countdown in a foreground service with notifications 2026-09-13 20:28:36 +02:00
break_service_port.dart workout_app: run the break countdown in a foreground service with notifications 2026-09-13 20:28:36 +02:00
break_task_handler.dart workout_app: run the break countdown in a foreground service with notifications 2026-09-13 20:28:36 +02:00
firebase_backend_desktop.dart Run the workout app on Linux, and let it hold the screen lock 2026-08-22 11:18:48 +02:00
firebase_backend_google.dart Run the workout app on Linux, and let it hold the screen lock 2026-08-22 11:18:48 +02:00
firebase_backend.dart Bring the workout app and status web UI up to latest stable 2026-09-07 15:46:07 +02:00
foreground_break_client_flutter.dart workout_app: run the break countdown in a foreground service with notifications 2026-09-13 20:28:36 +02:00
foreground_break_client.dart workout_app: run the break countdown in a foreground service with notifications 2026-09-13 20:28:36 +02:00
github_device_auth.dart Carry progression through Firebase, and stop demanding storage permission 2026-08-10 16:54:21 +02:00
google_platform_io.dart workout_app: add Google sign-in support for the Firebase sync account 2026-08-14 10:56:16 +02:00
google_platform_web.dart workout_app: add Google sign-in support for the Firebase sync account 2026-08-14 10:56:16 +02:00
google_platform.dart workout_app: add Google sign-in support for the Firebase sync account 2026-08-14 10:56:16 +02:00
google_sign_in_backend.dart Bring the workout app and status web UI up to latest stable 2026-09-07 15:46:07 +02:00
http_server_service.dart Carry progression through Firebase, and stop demanding storage permission 2026-08-10 16:54:21 +02:00
lock_mode.dart Run the workout app on Linux, and let it hold the screen lock 2026-08-22 11:18:48 +02:00
progression_sync_service_pull.dart Split progression_sync_service.dart (433) into four 2026-08-15 21:44:43 +02:00
progression_sync_service_push.dart Split progression_sync_service.dart (433) into four 2026-08-15 21:44:43 +02:00
progression_sync_service_session.dart Split progression_sync_service.dart (433) into four 2026-08-15 21:44:43 +02:00
progression_sync_service.dart Split progression_sync_service.dart (433) into four 2026-08-15 21:44:43 +02:00
storage_service_backup.dart Split storage_service.dart (781) into part extensions 2026-08-15 21:12:08 +02:00
storage_service_exercises.dart Split storage_service.dart (781) into part extensions 2026-08-15 21:12:08 +02:00
storage_service_schema.dart Bring the workout app and status web UI up to latest stable 2026-09-07 15:46:07 +02:00
storage_service_sessions.dart Split storage_service.dart (781) into part extensions 2026-08-15 21:12:08 +02:00
storage_service.dart Bring the workout app and status web UI up to latest stable 2026-09-07 15:46:07 +02:00
sync_device_id.dart Push under a persisted per-install uuid, not a fixed role id 2026-08-09 17:31:15 +02:00
sync_service.dart Carry progression through Firebase, and stop demanding storage permission 2026-08-10 16:54:21 +02:00
sync_settings.dart Carry progression through Firebase, and stop demanding storage permission 2026-08-10 16:54:21 +02:00
sync_state_factory.dart Sync workouts through Firebase, mirroring to GitHub during the cutover 2026-08-05 08:12:40 +02:00
sync_status.dart Add sync-status card and duration-threshold fixture 2026-08-15 18:41:31 +02:00
workout_sync_service_read.dart Stop the phone counting deleted and empty manual workouts 2026-08-27 20:13:12 +02:00
workout_sync_service.dart Bring the workout app and status web UI up to latest stable 2026-09-07 15:46:07 +02:00
workout_sync_session.dart Extract WorkoutSyncSession from workout_sync_service.dart (322 -> 218) 2026-08-15 22:28:02 +02:00