Commit Graph

8 Commits

Author SHA1 Message Date
bvandeusen d43719516e feat(web): drop hero row + compact Rediscover tiles
test-web / test (push) Successful in 33s
Operator UI review on the merged build:

- Hero row felt 'odd' — operator chose remove-entirely on the
  AskUserQuestion options. The Playlists row already leads with
  For-You and Recently Added leads with the newest album, so the
  hero duplicated both anchors. Pulled HomeHeroCard.svelte + all
  page-level wiring (systemShuffle/getPlaylist imports + playForYou/
  playLatestAlbum handlers) and reverted the within() test scoping
  added in 682d7a5e.

- Rediscover tiles step down to w-32 (albums) / w-28 (artists),
  matching the Most Played CompactTrackCard visual weight on web.
  Reinforces the page hierarchy: fresh content gets real estate,
  throwbacks recede.
2026-06-01 20:34:21 -04:00
bvandeusen 682d7a5ec4 test(web): scope home For-You assertions to Playlists section
test-web / test (push) Successful in 33s
The new hero card on Home renders the For-You playlist twice — once
at the top in the featured row and once in the Playlists carousel.
The two existing assertions that did screen.getByText('For You')
now match both and fail. Wrap each in within(playlistsSection) so
the test targets the carousel render specifically.
2026-06-01 20:12:59 -04:00
bvandeusen 5393174a27 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.
2026-06-01 11:25:25 -04:00
bvandeusen d67c0de596 refactor(playlists): #411 R2 — generic registry-driven system endpoints
Replaces the per-kind refresh/shuffle handlers with one generic
pair driven off the kind registry, in lockstep across both clients.

Server:
- systemPlaylistKind gains Singleton; RefreshableSystemKind(key)
  exported. for_you/discover singleton; songs_like_artist not.
- New generic POST /api/playlists/system/{kind}/refresh and
  GET /api/playlists/system/{kind}/shuffle ({kind} = raw
  system_variant). Non-singleton/unknown kind → 404. Deleted
  playlists_{foryou,discover}_refresh.go and the per-kind shuffle
  wrappers; serveSystemPlaylistShuffle core kept.
- playlistRowView.refreshable: server-derived flag so clients show
  the refresh affordance generically without hardcoding kinds.

Web (not drift-cached → uses the server flag):
- refreshSystem(variant) replaces refreshForYou/refreshDiscover;
  systemShuffle drops the for_you→for-you mapping (raw variant).
- PlaylistCard + detail page gate the kebab/Refresh button on
  playlist.refreshable; label is "Refresh {name}". Tests reworked;
  obsolete refresh-foryou/discover api tests deleted.

Flutter (list tiles are drift-cache-sourced → derive, no migration):
- Playlist.refreshable getter = isSystem && variant !=
  songs_like_artist (holds for all current + planned kinds).
- refreshSystem/systemShuffle use the raw variant; PlaylistCard +
  detail screen gate kebab/Regenerate/source-tagging on refreshable
  so songs_like_artist plays via get() (no by-kind endpoint).

Pure-plumbing refactor; CI verifies parity. Next (R3): the five
discovery mixes — each a candidate query + one registry entry.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 13:21:09 -04:00
bvandeusen 356f8f5d6c test(web): update home placeholder counts for new Discover slot
5-slot system row (For-You, Discover, 3× Songs-like) means:
- empty state: 5 placeholders (was 4)
- For-You only: 4 placeholders (was 3) — Discover + 3 songs-like
2026-05-11 23:46:07 -04:00
bvandeusen 7e8d19606a refactor(web): sweep test files to use empty likes/quarantine mocks (#375)
Replaces duplicated inline vi.mock('$lib/api/likes', ...) blocks with
the emptyLikesMock() helper, and (where previously left in working
tree by a parallel quarantine sweep) rolls in the matching
emptyQuarantineMock() switchovers in the same files.

Together with commit dd67f28 — which already swept the four search/*
test files for likes — this completes the 18 likes-mock conversions
called out in #375.

LikeButton.test.ts kept inline — it uses a state-driven mock to
assert the toggle behavior.

SKIPPED:
- liked.test.ts: re-exports createLikedTracksInfiniteQuery and the
  album/artist variants that emptyLikesMock() doesn't provide.
- playlist.test.ts: hand-rolled { subscribe, data } stub instead of
  readable(...) — different store contract.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 15:41:15 -04:00
bvandeusen 3e34f1f7b3 refactor(web/test): default svelte-query mock in vitest.setup; remove from 34 files (B3) 2026-05-08 11:08:41 -04:00
bvandeusen 5698cfe8e4 feat(web/m7-352): home Playlists row — For-You + Songs-like + user playlists
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 18:34:03 -04:00