feat(slint): you-may-also-like discovery section with sticky dismiss
Closes the network sidebar with the fifth section — tag-based "You may
also like" discovery, with a per-tag dismiss store so a thumbs-down
sticks across artist pages that share the same primary genre tag.
Backend (`qbz-integrations` + `qbz-core`):
- DiscoveryArtist and DiscoveryResponse DTOs added to
qbz-integrations::musicbrainz::models.
- QbzCore::musicbrainz_discover_artists ports
v2_get_discovery_artists end to end (sans the RecoState local
"play count > 2" filter, which has no equivalent in the Slint
shell yet): primary-tag search, exclude seed + similar +
dismissed, deterministic shuffle keyed on seed_mbid, validate
each candidate on Qobuz, fall back to the secondary tag if we
have fewer than 5 matches.
- normalize_artist_name re-exported at the qbz-core crate root so
the dismiss handler in qbz-slint can use the same key shape that
the discovery pipeline filters on.
- Deterministic shuffle implemented with a simple xorshift PRNG
seeded from a stable hash of seed_mbid — keeps qbz-core free of
the rand dep.
Slint controller (`crates/qbz-slint/src/`):
- discovery_dismiss.rs — small JSON store at
`<data-dir>/qbz/discovery_dismiss.json` keyed by lowercased tag
-> list of normalized artist names. dismissed_for_tag is passed
into the discovery call as the filter source; dismiss() is
invoked by the thumbs-down handler.
- artist::load_mb_discovery / apply_mb_discovery /
remove_discovery_artist plumb the pipeline result through the
standard load-off-thread / apply-on-UI split. Discovery state
includes primary_tag so the dismiss handler can persist under
the right key.
- main.rs chains discovery after relationships in the same MB
enrichment task. NetworkSidebarActions.discovery-dismissed (now
carrying mbid + name) normalizes the name, persists the
dismiss, and removes the row from the visible list.
Slint UI (`ui/state.slint`, `ui/artist/ArtistPageView.slint`):
- discovery-tag property added to NetworkSidebarState.
- YOU MAY ALSO LIKE section after Relationships — one row per
candidate (SidebarLink + a 24x24 thumbs-down button on the
right). Clicking the link navigates via the artist-clicked
callback when a Qobuz id is present.
- thumbs-down.svg icon added to ui/assets/icons (Lucide
ThumbsDown).
cc
This commit is contained in:
9 files changed
+529
-16
No files matched your search
@@ -554,6 +554,23 @@ pub struct LocationDiscoveryResponse {
|
||||
pub next_offset: usize,
|
||||
}
|
||||
|
||||
/// One candidate from the "you may also like" tag-based discovery pipeline.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct DiscoveryArtist {
|
||||
pub mbid: String,
|
||||
pub name: String,
|
||||
pub qobuz_id: Option<u64>,
|
||||
}
|
||||
|
||||
/// Result of the tag-based discovery pipeline. `primary_tag` is the tag
|
||||
/// the discovery was seeded with — frontends save dismissals keyed by
|
||||
/// it so a "thumbs down" stays sticky for that tag across artists.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct DiscoveryResponse {
|
||||
pub artists: Vec<DiscoveryArtist>,
|
||||
pub primary_tag: String,
|
||||
}
|
||||
|
||||
// ============ Musician Types ============
|
||||
|
||||
/// Musician confidence level for MusicBrainz <-> Qobuz matching
|
||||
|
||||
Reference in new issue
Block a user