feat(reco): Recommendations in all Discover flyouts + opt-out setting

Surface the new Recommendations tab everywhere Discover sub-sections are listed,
and make it opt-out.

- Flyouts: the sidebar section-nav flyout and both header nav flyouts (full text
  + compact icon) now list "Recommendations" alongside Home / Editor's Picks /
  For You. The Rust route handler already maps "discover-recommendations"
  (strip_prefix + select_tab + ensure_loaded), so no routing change was needed.
- Opt-out: a show_recommendations flag (default on) persisted in the per-user
  discover-prefs store (qbz_app), seeded into SettingsState on session start.
  Settings > Integrations gains a "Show Recommendations in Discover" toggle whose
  description nudges connecting Last.fm + ListenBrainz (MusicBrainz is used
  automatically to match releases). Off => the tab pill and every flyout entry
  disappear.
- Gating uses two mounted instances per flyout (one with the entry, one without)
  because Slint can't type-infer [NavMenuEntry] from a ternary of array literals;
  the HomeView pill uses a plain if.

cargo check -p qbz green.

cc
This commit is contained in:
vicrodh committed 2026-06-27 11:57:46 -06:00
1 parent 05df99b713
commit 332fa430e5
9 files changed
+117 -9

No files matched your search

+2 -2
View File
@@ -8,7 +8,7 @@
import { Theme } from "../foundation/semantic-colors.slint";
import { Typography } from "../foundation/typography.slint";
import { HomeState, HomeActions, DiscoverState, DiscoverActions, GenreFilterState, GenreFilterActions, NavState, ContentView, ShellState } from "../state.slint";
import { HomeState, HomeActions, DiscoverState, DiscoverActions, GenreFilterState, GenreFilterActions, NavState, ContentView, ShellState, SettingsState } from "../state.slint";
import { Carousel } from "Carousel.slint";
import { SlimCarousel } from "SlimCarousel.slint";
import { PlaylistCarousel } from "PlaylistCarousel.slint";
@@ -211,7 +211,7 @@ export component HomeView inherits Rectangle {
active: HomeState.active-tab == "forYou";
clicked => { HomeActions.select-tab("forYou"); }
}
Tab {
if SettingsState.show-recommendations: Tab {
label: @tr("Recommendations");
active: HomeState.active-tab == "recommendations";
clicked => { HomeActions.select-tab("recommendations"); }