feat(slint): Discover Editor's Picks + For You tabs

Makes the three-tab Discover pill (Home / Editor's Picks / For You)
functional, plus the matching Discover header-dropdown rows. Mirrors
Tauri's DiscoveryView: all tabs draw from one fetch and swap which
curated section set is shown — no extra round-trips on tab switch.

home.rs:
  - load_home now builds three section sets from a single
    get_discover_index call (cloning the editorial containers):
      * home — the existing balanced set.
      * editorPicks — editorial only (New Releases, Qobuzissimes,
        Press Accolades, Most Streamed, Ideal Discography, Albums of
        the Week), ordered per Tauri's DEFAULT_PREFS.editorPicks.
      * forYou — Release Watch (get_release_watch "artists"). The
        deeper personalized sections (Qobuz mixes, similar albums,
        spotlight) need reco-DB backend the Slint MVP lacks, so this
        is the honest first cut.
  - apply_home caches all three sets in a thread-local; select_tab
    swaps HomeState.sections to the chosen set and returns the
    Section-targeted artwork jobs to re-fire. Reuses the existing
    Section artwork target — no new targets.
  - map_full_album maps release-watch's catalog Album to a card.

Slint:
  - HomeState gains active-tab; HomeActions.select-tab wired to the
    pill (active state derived from active-tab) and to the Discover
    dropdown rows (route "discover-<tab>") via header-menu-navigate.
  - The Home-only sections (Recently Played albums/tracks, Popular)
    are gated to active-tab == "home" so Editor's Picks / For You
    render just their own set.

cc
This commit is contained in:
vicrodh committed 2026-05-20 21:33:06 -06:00
1 parent 93edce305c
commit 1efa6fc745
6 files changed
+247 -24

No files matched your search

+30 -9
View File
@@ -8,7 +8,7 @@
import { Theme } from "../foundation/semantic-colors.slint";
import { Typography } from "../foundation/typography.slint";
import { HomeState, NavState, ContentView } from "../state.slint";
import { HomeState, HomeActions, NavState, ContentView } from "../state.slint";
import { Carousel } from "Carousel.slint";
import { GridSection } from "GridSection.slint";
import { QbzIcon } from "../primitives/QbzIcon.slint";
@@ -174,9 +174,21 @@ export component HomeView inherits Rectangle {
tab-row := HorizontalLayout {
padding: 3px;
spacing: 4px;
Tab { label: @tr("Home"); active: true; }
Tab { label: @tr("Editor's Picks"); }
Tab { label: @tr("For You"); }
Tab {
label: @tr("Home");
active: HomeState.active-tab == "home";
clicked => { HomeActions.select-tab("home"); }
}
Tab {
label: @tr("Editor's Picks");
active: HomeState.active-tab == "editorPicks";
clicked => { HomeActions.select-tab("editorPicks"); }
}
Tab {
label: @tr("For You");
active: HomeState.active-tab == "forYou";
clicked => { HomeActions.select-tab("forYou"); }
}
}
}
}
@@ -246,9 +258,14 @@ export component HomeView inherits Rectangle {
}
}
// The Recently Played + Popular sections below belong
// to the Home tab only; Editor's Picks / For You show
// just their own cached section set above.
// Recently Played Albums — always present; shows a
// placeholder until the play history has data.
if HomeState.recent-albums.length > 0: Carousel {
if HomeState.active-tab == "home"
&& HomeState.recent-albums.length > 0: Carousel {
section: {
title: @tr("Recently Played Albums"),
albums: HomeState.recent-albums,
@@ -260,25 +277,29 @@ export component HomeView inherits Rectangle {
root.media-action(kind, id, action);
}
}
if HomeState.recent-albums.length == 0: RecentPlaceholder {
if HomeState.active-tab == "home"
&& HomeState.recent-albums.length == 0: RecentPlaceholder {
title: @tr("Recently Played Albums");
hint: @tr("Albums you play will appear here.");
}
// Recently Played Tracks — always present, same pattern.
if HomeState.recent.length > 0: GridSection {
if HomeState.active-tab == "home"
&& HomeState.recent.length > 0: GridSection {
title: @tr("Recently Played Tracks");
items: HomeState.recent;
item-clicked(id) => {
root.media-action("track", id, "play");
}
}
if HomeState.recent.length == 0: RecentPlaceholder {
if HomeState.active-tab == "home"
&& HomeState.recent.length == 0: RecentPlaceholder {
title: @tr("Recently Played Tracks");
hint: @tr("Tracks you play will appear here.");
}
if HomeState.popular.length > 0: GridSection {
if HomeState.active-tab == "home"
&& HomeState.popular.length > 0: GridSection {
title: @tr("Popular albums");
items: HomeState.popular;
item-clicked(id) => {