47 lines
2.5 KiB
Markdown
47 lines
2.5 KiB
Markdown
|
|
# Player State Machine Refactor
|
||
|
|
|
||
|
|
## Task
|
||
|
|
Refactored the player state management to eliminate race conditions during rapid station tapping, stop/play transitions, and the NowPlayingScreen bounce-back bug.
|
||
|
|
|
||
|
|
## Changes Made
|
||
|
|
|
||
|
|
### PlaybackState.kt
|
||
|
|
- Added `Connecting` state variant to represent the period between user tap and service processing the intent.
|
||
|
|
|
||
|
|
### RadioController.kt
|
||
|
|
- `play()` now sets state to `Connecting` synchronously before sending the intent, eliminating the async gap.
|
||
|
|
- `stop()` now sets state to `Idle` synchronously before sending the intent.
|
||
|
|
- `pause()` now sets state to `Paused` synchronously before sending the intent.
|
||
|
|
- Added redundancy guard: double-tapping a station that's already `Connecting` is a no-op.
|
||
|
|
|
||
|
|
### RadioPlaybackService.kt
|
||
|
|
- Removed the `pauseRequested` volatile flag entirely.
|
||
|
|
- The `handlePlay()` finally block now checks `controller.state.value` (the single source of truth) instead of the volatile flag to determine cleanup behavior.
|
||
|
|
- Renamed `cleanup()` to `cleanupResources()` since it no longer sets `Idle` state (that's now the controller's responsibility).
|
||
|
|
- `handlePause()` and `handleStop()` no longer set `pauseRequested`.
|
||
|
|
|
||
|
|
### MainActivity.kt
|
||
|
|
- Centralized navigation logic via a `LaunchedEffect` that observes `RadioController.state`.
|
||
|
|
- Navigates to NowPlaying on `Idle -> Active` transitions.
|
||
|
|
- Navigates back to StationList on `Active -> Idle` transitions while on NowPlaying.
|
||
|
|
- Station switching (`Playing(A) -> Connecting(B)`) stays on NowPlaying.
|
||
|
|
|
||
|
|
### NowPlayingScreen.kt
|
||
|
|
- Removed the `LaunchedEffect(playbackState)` that called `onBack()` on `Idle` (was the source of the bounce-back bug).
|
||
|
|
- Added `Connecting` to the `when` branches, showing a loading spinner overlay.
|
||
|
|
- Disabled pause/skip-ahead buttons while connecting.
|
||
|
|
|
||
|
|
### NowPlayingViewModel.kt
|
||
|
|
- Added `Connecting` handling in session timer (uses `sessionStartedAt`), connection timer (shows 0), and artwork resolver (uses station default artwork).
|
||
|
|
|
||
|
|
### StationListScreen.kt
|
||
|
|
- Removed `onNavigateToNowPlaying()` from `onPlay` callbacks (navigation is now centralized in MainActivity).
|
||
|
|
- Added `Connecting` to mini player visibility and "now playing" station highlight.
|
||
|
|
|
||
|
|
### MiniPlayer.kt
|
||
|
|
- Added `Connecting` to the destructuring `when` block.
|
||
|
|
- Shows "Connecting..." subtitle for the `Connecting` state.
|
||
|
|
|
||
|
|
## Follow-up Items
|
||
|
|
- The `stayConnected` and `retryImmediatelyOnNetwork` volatile flags in RadioPlaybackService could be further consolidated into the state machine in a future pass.
|