feat(slint): ArtistView overhaul — server-driven buckets, dedicated discography, sort/load-more, Magazine, image fixes
Bucketing now trusts the server release_type: drop the foreign-artist filter that hid band/guest releases (e.g. Vicky Psarakis' Albums were credited to Sicksense), render every non-empty bucket, hide 'Purchase Only' (download), and move 'Other' to the end, collapsed by default. Drop the misleading per-section item counts. New 'Latest release' highlight (last_release) and 'Appears On' track section (tracks_appears_on, previously mislabeled as Compilations). Per-section persisted 5-mode sort (artist_prefs) + per-section load-more capped at 4 pages, reusing get_releases_grid. New dedicated discography page (ArtistReleasesView + artist_releases controller) with sort + infinite scroll, reached via each section's 'See discography' link. Magazine/Stories sidebar tab (artist/story) with 1:1 thumbnails and a Network|Magazine tab switcher; hide the empty similar-artists block to remove the 'no similar' over populated-discovery incoherence. Header Share action. Per-release award ribbons. Fix custom artist AND album images: decode + apply immediately on upload and resolve the local override on navigation, so a custom image now shows for artists/albums with no Qobuz artwork. Data layer: type last_release as PageArtistRelease, add /artist/story endpoint + core/client methods + ArtistStory* models, export ArtistReleases* globals. cc
This commit is contained in:
18 files changed
+1894
-225
No files matched your search
@@ -2606,6 +2606,36 @@ impl QobuzClient {
|
||||
Ok(serde_json::from_value(response)?)
|
||||
}
|
||||
|
||||
/// Get artist Magazine stories (editorial articles about the artist).
|
||||
/// REST header-auth only (no per-op signing). Web client calls offset=0 limit=2.
|
||||
pub async fn get_artist_story(
|
||||
&self,
|
||||
artist_id: u64,
|
||||
offset: u32,
|
||||
limit: u32,
|
||||
) -> Result<ArtistStoryResponse> {
|
||||
let url = endpoints::build_url(paths::ARTIST_STORY);
|
||||
let query = vec![
|
||||
("artist_id", artist_id.to_string()),
|
||||
("offset", offset.to_string()),
|
||||
("limit", limit.to_string()),
|
||||
];
|
||||
|
||||
log::debug!(
|
||||
"[API] get_artist_story({}) offset={} limit={}",
|
||||
artist_id,
|
||||
offset,
|
||||
limit
|
||||
);
|
||||
let response: serde_json::Value = self
|
||||
.signed_get(&url, "artiststory", &query.iter().map(|(k, v)| (*k, v.clone())).collect::<Vec<_>>())
|
||||
.await?
|
||||
.json()
|
||||
.await?;
|
||||
|
||||
Ok(serde_json::from_value(response)?)
|
||||
}
|
||||
|
||||
// === CMAF streaming endpoints ===
|
||||
|
||||
/// Ensure we have a valid CMAF session, renewing if expired.
|
||||
|
||||
@@ -39,6 +39,7 @@ pub mod paths {
|
||||
pub const ARTIST_PAGE: &str = "/artist/page";
|
||||
pub const ARTIST_RELEASES_GRID: &str = "/artist/getReleasesGrid";
|
||||
pub const ARTIST_RELEASES_LIST: &str = "/artist/getReleasesList";
|
||||
pub const ARTIST_STORY: &str = "/artist/story";
|
||||
|
||||
// Playlist
|
||||
pub const PLAYLIST_GET: &str = "/playlist/get";
|
||||
|
||||
Reference in new issue
Block a user