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.
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.
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.
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
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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: splitstop()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'sMediaControllerbinding across pause cycles so notification + watch transport controls keep working. Previously the user had to unpair/repair the Watch when controls went dead.Playlists (#479)
Tests (#399)
ci-flutter:1.26image 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
x/crypto,pgx,migrate,pgerrcodebumps;staticcheck S1016collapses 4 struct-literal copies to type conversions.container.image:perci-runners.md(ci-go:1.26 / ci-flutter:3.44); golangci-lint v2 schema; Flutter 3.44 ListTile/ColoredBox strictness wraps.Test plan
MinstrelAudioHandler.pause()and pause the audio (no unpair/repair workaround needed)Generated with Claude Code