feat(qt): carry the featured artists on Qobuz track rows
cc
This commit is contained in:
7 files changed
+28
No files matched your search
@@ -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(),
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user