feat(web): surface secondary system playlists on Home
test-web / test (push) Successful in 31s

Mirrors the Android change from commit bf61d6cf. Web's Home Playlists
row gains the 5 secondary system kinds (deep_cuts, rediscover,
new_for_you, on_this_day, first_listens) after the Songs-like slots,
in server-registry order, when they exist. No placeholders for these
— they depend on library shape (Deep cuts needs deep albums, On this
day needs prior history, etc.) so a missing one means "not enough
data," not "still building."

Test coverage: new `renders secondary system kinds` test creates a
mocked owned set with for_you + deep_cuts + new_for_you and asserts
all three card names render. Existing tests (5 placeholders, building
variant, For-You + 3 placeholders) unchanged since none seed
secondary kinds.

Most Played multi-row is NOT touched — web already chunks the 75
tracks into 3 rows of 25 via the existing HorizontalScrollRow rows=
{chunk(...,25)} pattern. My initial task description was wrong on
that point.

Naming collision (`rediscover` playlist vs Rediscover recommendations
section both read "Rediscover" on the same Home) deferred — operator
follow-up. Same on Android.

Scribe 531, local task #61.
This commit is contained in:
2026-06-01 11:25:25 -04:00
parent e5c82c56c6
commit 5393174a27
2 changed files with 67 additions and 0 deletions
+29
View File
@@ -49,6 +49,30 @@
.slice(0, 3)
);
// Secondary system kinds the server generates that don't get pinned
// to fixed Home slots: surfaced after the Songs-like slots when they
// exist, in server-registry order (internal/playlists/system.go).
// No placeholders for these — they depend on library shape (Deep
// cuts needs deep albums, On this day needs prior history, etc.) so
// a missing one means "not enough data," not "still building."
// Mirrors Android's SECONDARY_SYSTEM_VARIANTS (HomeScreen.kt). Operator
// request 2026-06-01 for web parity.
const SECONDARY_SYSTEM_VARIANTS = [
'deep_cuts',
'rediscover',
'new_for_you',
'on_this_day',
'first_listens'
] as const;
const secondarySystemPlaylists = $derived(
SECONDARY_SYSTEM_VARIANTS
.map((variant) =>
(systemPlaylistsQ.data?.owned ?? []).find((p) => p.system_variant === variant)
)
.filter((p): p is Playlist => p != null)
);
const userPlaylists = $derived(userPlaylistsQ.data?.owned ?? []);
type PlaceholderVariant = 'building' | 'failed' | 'pending' | 'seed-needed';
@@ -93,6 +117,11 @@
}
}
// Secondary system kinds in server-registry order, when generated.
for (const p of secondarySystemPlaylists) {
out.push({ kind: 'real', playlist: p });
}
// User playlists trail (server returns most-recently-updated first).
for (const p of userPlaylists) {
out.push({ kind: 'real', playlist: p });