2 Commits

Author SHA1 Message Date
bvandeusen 94871437dd feat(player): resume on media-button when session torn down (#448)
Fast-follow of #54. After the #52 idle/dismiss teardown, pressing play
on a headset / watch / lock screen did nothing (handler.play() was just
_player.play() with nothing loaded; the handler is Riverpod-agnostic).

- audio_handler: _resumeHook + setResumeHook(); play() is now async —
  when mediaItem == null and a hook is set it awaits the hook (which
  restores + plays) and returns, else _player.play()
- resume_controller: extract shared _loadAndRestore() (bool); _restore()
  keeps the paused launch path; new resumeFromMediaButton() restores
  then starts playback; start() registers it via setResumeHook

Recursion-safe (post-restore mediaItem != null so the re-play hits
_player.play()); no-op when nothing to resume / auth missing / a
session is already active.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 21:31:40 -04:00
bvandeusen 41dd2892e3 feat(player): resume last session on launch (#54)
The #52 teardown clears the session when idle/dismissed, so the
headset / lock-screen play button had nothing to resume and the user
lost their place.

- track.dart: toJson() (round-trips fromJson)
- db.dart: CachedResumeState single-row snapshot, schema 9->10 + migration
- audio_handler.dart: queuedTracks getter
- player_provider.dart: restoreQueue() — configure + setQueueFromTracks
  + seek, no play (restores PAUSED)
- resume_controller.dart: restores last snapshot paused on launch;
  persists {source,index,position_ms,tracks} debounced on track
  change / pause and immediately on app teardown; never clobbers the
  saved snapshot when the queue is empty so a teardown stays
  recoverable; restore gated on auth + no active session
- app.dart: wired into postFrame

db.g.dart regenerated by CI per project convention. Deferred fast-follow:
media-button-when-fully-stopped re-init (needs a configure()-injected
callback; tracked on #54).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 15:57:58 -04:00