feat(slint): Discover genre filter (simple view)

Ports Tauri's Filter-by-genre popup (simple grid view). The selection
is shared across the three Discover tabs — matching Tauri's single
"home" genre context — and re-fetches the discover index with the
chosen genre ids.

UI:
  - New GenreFilterPopup: header (icon + title + close), Remember
    selection + Advanced view toggles (QbzToggle), a 3-column grid of
    parent-genre chips with an accent fill + check circle when
    selected, and a Clear filter footer. Anchored top-right under the
    button, with a click-away backdrop.
  - GenreButton turns accent-filled and shows "N genres" / "1 genre"
    when a filter is active (else "Filter by genre"), 1:1 with Tauri.
  - Advanced view (search + 3-level tree + counts) is the next
    increment; its toggle is present and shows a "coming soon" stub.

State / backend:
  - GenreFilterState + GenreFilterActions globals; GenreChip struct.
  - crate::genre_filter loads the parent genres (QbzCore::get_genres)
    and owns the shared selection, persisted to
    <data-dir>/qbz/genre_filter.json when Remember is on (dropped
    when off). Stale ids are pruned against the loaded genres.
  - load_home now takes genre_ids and threads them into
    get_discover_index. The home-load path is extracted into a shared
    `reload_home(active_tab)` used by the initial shell load and by
    genre toggle/clear; it rebuilds all three section sets, restores
    the active tab via select_tab, and re-fires artwork.

cc
This commit is contained in:
vicrodh committed 2026-05-20 22:43:16 -06:00
1 parent 235c61bf80
commit 880493b73d
7 files changed
+630 -68

No files matched your search

+27
View File
@@ -56,6 +56,33 @@ export global HomeActions {
callback select-tab(string);
}
// One genre in the Filter-by-genre popup's simple grid.
export struct GenreChip {
id: string,
name: string,
selected: bool,
}
// Filter-by-genre state. The selection is shared across the three
// Discover tabs (matching Tauri's single "home" genre context) — it
// re-fetches the discover index with the chosen genre ids. Populated
// by crate::genre_filter.
export global GenreFilterState {
in property <[GenreChip]> genres: [];
in property <int> selected-count: 0;
in-out property <bool> open: false;
in-out property <bool> remember: true;
in-out property <bool> advanced: false;
in property <bool> loading: false;
}
export global GenreFilterActions {
callback toggle(string /* genre id */);
callback clear();
callback set-remember(bool);
callback set-advanced(bool);
}
export struct AlbumTrackItem {
id: string,
number: string,