Files
minstrel/android
bvandeusen 57d01d70ad feat(android): PlaybackErrorReporter — surface ExoPlayer skip-on-error (audit v3 §4.1)
The audit called this the worst kind of bug — when a track fails
to load (404, decoder failure, premature EOS, network drop)
ExoPlayer just silently skips to the next, hiding exactly the
signal that distinguishes "this file is broken" from "the app is
flaky".

* PlayerController.onPlayerError now emits the failing track's
  title onto a CONFLATED Channel exposed as playbackErrorEvents:
  Flow<String>. Conflated rather than buffered so a stuck loop
  can't pile up; the reporter's debounce coalesces anyway.

* PlaybackErrorReporter @Singleton collects the per-error stream,
  buffers in a 2-second debounce window, and emits coalesced
  user-facing strings:
    1 error  → "Couldn't play \"X\" — skipping"
    N errors → "Skipped N unplayable tracks"
  Matches the Flutter reporter shape so users see one toast on a
  network blip that kills N tracks instead of a stack of N toasts.

* PlaybackErrorViewModel bridges the reporter's Flow into Hilt's
  ViewModel layer so ShellScaffold can collectAsState via
  hiltViewModel().

* ShellScaffold adds a second LaunchedEffect that pipes the
  reporter messages into the existing shared snackbar — no new
  UI surface needed.

* MinstrelApplication uses the construct-the-singleton trick to
  start the reporter at app launch so it's collecting from the
  first Media3 connect.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 22:03:32 -04:00
..