Introduce a Connecting state so the UI reflects user intent immediately, centralize navigation in MainActivity via state transitions, and replace the pauseRequested volatile flag with controller state as single source of truth. Made-with: Cursor
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.
|