feat: M3 weighted shuffle v1 — real /api/radio with scoring #21

Merged
bvandeusen merged 262 commits from dev into main 2026-04-27 11:00:29 -04:00
Showing only changes of commit b71f9c239e - Show all commits
@@ -227,6 +227,21 @@ private fun NowPlayingBody(
Spacer(Modifier.height(24.dp))
TrackHeader(title = track.title, artist = track.artistName, album = track.albumTitle)
Spacer(Modifier.height(24.dp))
// Action row (like, shuffle, repeat, queue, kebab) sits ABOVE the
// scrubber — Flutter's _SecondaryControls placement
// (now_playing_screen.dart:464). Android previously had it below
// the transport row.
BottomActionsRow(
navController = navController,
track = track,
shuffleEnabled = state.shuffleEnabled,
repeatMode = state.repeatMode,
isLiked = isLiked,
onToggleLike = { trackActionsViewModel.toggleLike(track.id, isLiked) },
onToggleShuffle = viewModel::toggleShuffle,
onCycleRepeat = viewModel::cycleRepeat,
)
Spacer(Modifier.height(8.dp))
ScrubberRow(
positionMs = state.positionMs,
durationMs = state.durationMs,
@@ -239,17 +254,6 @@ private fun NowPlayingBody(
onPlayPause = { if (state.isPlaying) viewModel.pause() else viewModel.play() },
onNext = viewModel::skipToNext,
)
Spacer(Modifier.height(16.dp))
BottomActionsRow(
navController = navController,
track = track,
shuffleEnabled = state.shuffleEnabled,
repeatMode = state.repeatMode,
isLiked = isLiked,
onToggleLike = { trackActionsViewModel.toggleLike(track.id, isLiked) },
onToggleShuffle = viewModel::toggleShuffle,
onCycleRepeat = viewModel::cycleRepeat,
)
}
}