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
2 changed files with 18 additions and 1 deletions
Showing only changes of commit a85a95507c - Show all commits
@@ -87,7 +87,7 @@ fun AlbumDetailScreen(
albumLiked = albumLiked,
likedTrackIds = likedTrackIds,
onPlayAll = { viewModel.play(startTrackId = null) },
onShuffleAll = { viewModel.play(startTrackId = null) },
onShuffleAll = viewModel::shuffle,
onTrackClick = { id -> viewModel.play(startTrackId = id) },
onToggleAlbumLike = viewModel::toggleLikeAlbum,
onToggleTrackLike = viewModel::toggleLikeTrack,
@@ -90,6 +90,23 @@ class AlbumDetailViewModel @Inject constructor(
)
}
/**
* Play the album in shuffled order. Pre-shuffles the list and hands
* the result to the player — matches the PlaylistDetail shuffle
* pattern. A future refinement could use Media3's
* `setShuffleModeEnabled` for play-then-shuffle without disturbing
* the original queue ordering.
*/
fun shuffle() {
val detail = (internal.value as? AlbumDetailUiState.Success)?.detail ?: return
if (detail.tracks.isEmpty()) return
player.setQueue(
tracks = detail.tracks.shuffled(),
initialIndex = 0,
source = "album:${detail.album.id}",
)
}
fun toggleLikeAlbum() {
val desired = !albumLiked.value
viewModelScope.launch {