Release: web UX overhaul + Android native port + server polish #59
@@ -709,10 +709,18 @@ enum class OfflinePoolKind(val label: String) {
|
||||
|
||||
/**
|
||||
* Builds the Home Playlists row. When [offline], the two cache-backed
|
||||
* pool cards (Recently played, Liked) lead the row — mirrors Flutter's
|
||||
* `_buildPlaylistsRow`. Then For You + Discover + 3× Songs-like fixed
|
||||
* slots (real card when generated, placeholder otherwise), then any
|
||||
* user-owned playlists.
|
||||
* pool cards (Recently played, Liked) lead the row. Then For You +
|
||||
* Discover + 3× Songs-like fixed slots (real card when generated,
|
||||
* placeholder otherwise), then the secondary system kinds (deep cuts /
|
||||
* rediscover / new for you / on this day / first listens) when they
|
||||
* exist — no placeholders for these since they're conditional on
|
||||
* library shape, not guaranteed singletons. Finally user-owned
|
||||
* playlists.
|
||||
*
|
||||
* Diverges from Flutter (`flutter_client/lib/library/home_screen.dart`
|
||||
* `_buildPlaylistsRow`) which only shows the 5 fixed slots and never
|
||||
* surfaces the secondary kinds on Home. Operator authorized the
|
||||
* divergence on 2026-06-01; web UI catch-up tracked as task #53.
|
||||
*/
|
||||
private fun buildPlaylistsRow(
|
||||
owned: List<PlaylistRef>,
|
||||
@@ -736,6 +744,15 @@ private fun buildPlaylistsRow(
|
||||
?.let { PlaylistRowItem.Real(it) }
|
||||
?: PlaylistRowItem.Placeholder("Songs like…", variantFor("songs-like", status))
|
||||
}
|
||||
// Secondary system kinds in server-registry order. Only included
|
||||
// when actually generated — these depend on library shape (Deep
|
||||
// cuts needs deep albums, On this day needs prior history, etc.)
|
||||
// so a missing one means "not enough data" rather than "still
|
||||
// building".
|
||||
for (variant in SECONDARY_SYSTEM_VARIANTS) {
|
||||
owned.firstOrNull { it.systemVariant == variant }
|
||||
?.let { out += PlaylistRowItem.Real(it) }
|
||||
}
|
||||
owned.filter { it.systemVariant == null }.forEach { out += PlaylistRowItem.Real(it) }
|
||||
return out
|
||||
}
|
||||
@@ -749,6 +766,19 @@ private fun variantFor(slot: String, s: SystemPlaylistsStatus): String = when {
|
||||
|
||||
private const val SONGS_LIKE_SLOTS = 3
|
||||
|
||||
/**
|
||||
* The 5 system playlist kinds the server generates that aren't pinned
|
||||
* to Home's primary slots. Order matches `systemPlaylistRegistry` in
|
||||
* `internal/playlists/system.go`.
|
||||
*/
|
||||
private val SECONDARY_SYSTEM_VARIANTS = listOf(
|
||||
"deep_cuts",
|
||||
"rediscover",
|
||||
"new_for_you",
|
||||
"on_this_day",
|
||||
"first_listens",
|
||||
)
|
||||
|
||||
@Composable
|
||||
private fun ArtistsRow(
|
||||
title: String,
|
||||
|
||||
+5
-1
@@ -159,7 +159,11 @@ private fun systemLabelFor(variant: String?): String = when (variant) {
|
||||
"for_you" -> "For You"
|
||||
"discover" -> "Discover"
|
||||
"songs_like_artist" -> "Songs like…"
|
||||
"todays_mix" -> "Today's mix"
|
||||
"deep_cuts" -> "Deep cuts"
|
||||
"rediscover" -> "Rediscover"
|
||||
"new_for_you" -> "New for you"
|
||||
"on_this_day" -> "On this day"
|
||||
"first_listens" -> "First listens"
|
||||
null -> ""
|
||||
else -> variant.replace('_', ' ').replaceFirstChar { it.uppercase() }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user