v2026.05.21.0 — Wear OS dispatch fix, playlist-load feedback, drift CI #58

Merged
bvandeusen merged 262 commits from dev into main 2026-05-21 15:42:06 -04:00
bvandeusen commented 2026-05-21 15:42:00 -04:00 (Migrated from git.fabledsword.com)

Summary

Last meaningful-feature release on Flutter. The codebase shifts to bugfix-only after this; v1 Android native rewrite has been planned and will begin on a parallel android/ sibling directory.

Player / Wear OS (#472)

  • audio_handler.dart: split stop() into _softTeardown() + stop(). The idle timeout now calls _softTeardown — the player stops + display state clears, but the FGS and MediaSessionCompat stay alive across idle. Preserves the Wear OS companion's MediaController binding across pause cycles so notification + watch transport controls keep working. Previously the user had to unpair/repair the Watch when controls went dead.
  • Research-backed: ryanheise/audio_service 0.18.18 is stale ~13 months, no Media3 migration upstream, no Dart-accessible hook for external-controller detection. The softTeardown is the surgical client-side fix.

Playlists (#479)

  • Tap a system-playlist PlayCircleButton before the mix has loaded: previously stalled silently. Now adds 8s timeout, SnackBar on timeout / empty response / API error. PlayCircleButton's existing spinner UI was already correct; just needed the failure-path feedback.

Tests (#399)

  • Drift test cohort un-skipped after ci-flutter:1.26 image ships libsqlite3-dev. 11/11 originally-scoped tests pass plus 3/4 quarantine + widgets_smoke + storage_section. Last quarantine test skipped pending Fable #476 (Riverpod StreamProvider lifecycle in async catch path).

Deps + CI

  • Go server: x/crypto, pgx, migrate, pgerrcode bumps; staticcheck S1016 collapses 4 struct-literal copies to type conversions.
  • Flutter: audio_session 0.2.3, flutter_lucide, permission_handler now direct deps; flutter_secure_storage patch bump.
  • CI: migrated workflows to container.image: per ci-runners.md (ci-go:1.26 / ci-flutter:3.44); golangci-lint v2 schema; Flutter 3.44 ListTile/ColoredBox strictness wraps.

Test plan

  • Tap a notification button after 5+ minutes paused — should fire MinstrelAudioHandler.pause() and pause the audio (no unpair/repair workaround needed)
  • Same on Pixel Watch transport tile
  • Tap a system-playlist tile before content loads — should show SnackBar feedback rather than silent stall
  • Force-close from recents while idle — full teardown still cleans up notification + watch tile
  • CI green on tag push (release.yml + flutter.yml)

Generated with Claude Code

## Summary Last meaningful-feature release on Flutter. The codebase shifts to bugfix-only after this; v1 Android native rewrite has been planned and will begin on a parallel `android/` sibling directory. ### Player / Wear OS (#472) - `audio_handler.dart`: split `stop()` into `_softTeardown()` + `stop()`. The idle timeout now calls `_softTeardown` — the player stops + display state clears, but the FGS and MediaSessionCompat stay alive across idle. Preserves the Wear OS companion's `MediaController` binding across pause cycles so notification + watch transport controls keep working. Previously the user had to unpair/repair the Watch when controls went dead. - Research-backed: ryanheise/audio_service 0.18.18 is stale ~13 months, no Media3 migration upstream, no Dart-accessible hook for external-controller detection. The softTeardown is the surgical client-side fix. ### Playlists (#479) - Tap a system-playlist PlayCircleButton before the mix has loaded: previously stalled silently. Now adds 8s timeout, SnackBar on timeout / empty response / API error. PlayCircleButton's existing spinner UI was already correct; just needed the failure-path feedback. ### Tests (#399) - Drift test cohort un-skipped after `ci-flutter:1.26` image ships libsqlite3-dev. 11/11 originally-scoped tests pass plus 3/4 quarantine + widgets_smoke + storage_section. Last quarantine test skipped pending Fable #476 (Riverpod StreamProvider lifecycle in async catch path). ### Deps + CI - Go server: `x/crypto`, `pgx`, `migrate`, `pgerrcode` bumps; `staticcheck S1016` collapses 4 struct-literal copies to type conversions. - Flutter: audio_session 0.2.3, flutter_lucide, permission_handler now direct deps; flutter_secure_storage patch bump. - CI: migrated workflows to `container.image:` per `ci-runners.md` (ci-go:1.26 / ci-flutter:3.44); golangci-lint v2 schema; Flutter 3.44 ListTile/ColoredBox strictness wraps. ## Test plan - [ ] Tap a notification button after 5+ minutes paused — should fire `MinstrelAudioHandler.pause()` and pause the audio (no unpair/repair workaround needed) - [ ] Same on Pixel Watch transport tile - [ ] Tap a system-playlist tile before content loads — should show SnackBar feedback rather than silent stall - [ ] Force-close from recents while idle — full teardown still cleans up notification + watch tile - [ ] CI green on tag push (release.yml + flutter.yml) Generated with Claude Code
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: bvandeusen/minstrel#58