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 0927b9177b - Show all commits
@@ -38,6 +38,32 @@ private const val MINI_BAR_HEIGHT_DP = 64
private const val MINI_BAR_TONAL_ELEVATION_DP = 4
private const val COVER_SIZE_DP = 48
@Composable
private fun MiniCover(coverUrl: String, contentDescription: String) {
Box(
modifier = Modifier
.size(COVER_SIZE_DP.dp)
.clip(RoundedCornerShape(FabledSwordFlatTokens.radiusSm))
.background(MaterialTheme.colorScheme.surfaceVariant),
contentAlignment = Alignment.Center,
) {
if (coverUrl.isEmpty()) {
Icon(
imageVector = Lucide.Music,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
)
} else {
AsyncImage(
model = coverUrl,
contentDescription = contentDescription,
modifier = Modifier.size(COVER_SIZE_DP.dp),
contentScale = ContentScale.Crop,
)
}
}
}
/**
* Collapsed player bar shown above the bottom nav. Returns nothing
* when no track is loaded so it doesn't take screen space on a
@@ -69,28 +95,7 @@ fun MiniPlayer(
modifier = Modifier.padding(horizontal = 12.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Box(
modifier = Modifier
.size(COVER_SIZE_DP.dp)
.clip(RoundedCornerShape(FabledSwordFlatTokens.radiusSm))
.background(MaterialTheme.colorScheme.surfaceVariant),
contentAlignment = Alignment.Center,
) {
if (track.coverUrl.isEmpty()) {
Icon(
imageVector = Lucide.Music,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
)
} else {
AsyncImage(
model = track.coverUrl,
contentDescription = track.title,
modifier = Modifier.size(COVER_SIZE_DP.dp),
contentScale = ContentScale.Crop,
)
}
}
MiniCover(coverUrl = track.coverUrl, contentDescription = track.title)
Spacer(Modifier.width(12.dp))
Column(modifier = Modifier.weight(1f)) {
Text(