feat(qt): carry the featured artists on Qobuz track rows

cc
This commit is contained in:
vicrodh committed 2026-09-13 03:48:02 -06:00
1 parent a29eb624ce
commit 30c2208a03
7 files changed
+28

No files matched your search

+13
View File
@@ -41,6 +41,9 @@ const RELEASE_PAGE_SIZE: u32 = 20;
#[derive(Clone, Default, Serialize)]
pub struct TrackRow {
/// Featured performers already joined ("X, Y"); "" when none.
#[serde(rename = "featured")]
pub featured: String,
pub id: String,
pub number: String,
pub title: String,
@@ -509,6 +512,15 @@ fn build_credits(album: &Album) -> Vec<(String, String, String)> {
}
/// album.rs `map_track` (with work headers for classical albums).
/// "X, Y" for the row's `feat.` suffix (empty = nothing to add). Qobuz rows
/// only — local / media-server rows never carry `performers`.
pub(crate) fn featured_join(performers: Option<&str>, artist: &str, title: &str) -> String {
let Some(performers) = performers else {
return String::new();
};
qbz_qobuz::performers::featured_artists(performers, artist, title).join(", ")
}
fn map_track(track: &Track) -> TrackRow {
let work = track
.work
@@ -536,6 +548,7 @@ fn map_track(track: &Track) -> TrackRow {
.map(|p| (p.name.clone(), p.id.to_string()))
.unwrap_or_default();
TrackRow {
featured: featured_join(track.performers.as_deref(), &artist, &track.title),
is_favorite: crate::fav_cache_qt::contains_track(track.id),
id: track.id.to_string(),
number: track.track_number.to_string(),
+1
View File
@@ -594,6 +594,7 @@ fn map_track(index: usize, track: PageArtistTrack) -> TrackRow {
.and_then(|r| r.streamable)
.unwrap_or(true);
TrackRow {
featured: String::new(),
is_favorite: crate::fav_cache_qt::contains_track(track.id),
id: track.id.to_string(),
cache_status: if crate::offline_qt::is_cached(&track.id.to_string()) {
+1
View File
@@ -1048,6 +1048,7 @@ fn to_row(track: &Track) -> TrackRow {
let bit_depth = track.maximum_bit_depth;
let sample_rate = track.maximum_sampling_rate;
TrackRow {
featured: String::new(),
id: track.id.to_string(),
title,
artist: track
+1
View File
@@ -1358,6 +1358,7 @@ fn parse_top_track(index: usize, raw: &Value) -> TrackRow {
raw.get("release_date_stream").and_then(|v| v.as_str()),
);
TrackRow {
featured: String::new(),
is_favorite: id
.parse::<u64>()
.map(crate::fav_cache_qt::contains_track)
+4
View File
@@ -806,6 +806,7 @@ pub(crate) fn row_to_display(item: &RowItem) -> (PlaylistTrackRow, Option<QueueT
} => {
let art = artwork_path.clone().unwrap_or_default();
let row = PlaylistTrackRow {
featured: String::new(),
id: track_id.to_string(),
playlist_track_id: *track_id,
title: title.clone(),
@@ -880,6 +881,7 @@ pub(crate) fn row_to_display(item: &RowItem) -> (PlaylistTrackRow, Option<QueueT
)
.unwrap_or_default();
let row = PlaylistTrackRow {
featured: String::new(),
id: queue.id.to_string(),
playlist_track_id: queue.id,
title: t.title.clone(),
@@ -930,6 +932,7 @@ pub(crate) fn row_to_display(item: &RowItem) -> (PlaylistTrackRow, Option<QueueT
.unwrap_or_else(|| path.clone());
(
PlaylistTrackRow {
featured: String::new(),
id: path.clone(),
title: name,
source: "local".to_string(),
@@ -942,6 +945,7 @@ pub(crate) fn row_to_display(item: &RowItem) -> (PlaylistTrackRow, Option<QueueT
}
RowItem::Unresolved { kind, reference } => (
PlaylistTrackRow {
featured: String::new(),
id: format!("{kind}:{reference}"),
title: qbz_i18n::t("Unavailable track"),
source: (*kind).to_string(),
+4
View File
@@ -59,6 +59,9 @@ use serde::Serialize;
#[derive(Clone, Default, Serialize)]
pub struct PlaylistTrackRow {
/// Featured performers already joined ("X, Y"); "" when none.
#[serde(rename = "featured")]
pub featured: String,
pub id: String,
/// The playlist membership row id (== catalog track id for Qobuz
/// playlists — what remove_tracks_from_playlist takes).
@@ -862,6 +865,7 @@ pub(crate) fn map_track(track: &Track) -> PlaylistTrackRow {
.map(|p| (p.name, p.id.to_string()))
.unwrap_or_default();
PlaylistTrackRow {
featured: crate::album_qt::featured_join(track.performers.as_deref(), &artist, &track.title),
// Heart state at build time, from the favourite-id cache — the same
// O(1) read `album_qt` / `artist_qt` / `label_qt` rows use. It was
// never stamped here, so `TrackRow.qml` saw `undefined` on every
+4
View File
@@ -194,6 +194,9 @@ pub struct CardRow {
#[derive(Clone, Default, Serialize)]
pub struct TrackRow {
/// Featured performers already joined ("X, Y"); "" when none.
#[serde(rename = "featured")]
pub featured: String,
pub id: String,
pub title: String,
pub artist: String,
@@ -404,6 +407,7 @@ fn map_track(track: &Track) -> TrackRow {
.map(|p| (p.name, p.id.to_string()))
.unwrap_or_default();
TrackRow {
featured: crate::album_qt::featured_join(track.performers.as_deref(), &artist, &track.title),
// Same story as `map_album`: the field was declared (line 186) and
// never stamped, so every search track row drew the empty heart and
// the first click sent `favorite/delete` on a track the user had