feat: add LabelView to browse albums by record label
- Add get_label API endpoint and Tauri command - Create LabelView component with album grid, search, and infinite scroll - Add clickable label links in AlbumDetailView, AlbumCreditsModal, and TrackInfoModal - Add label_id to AlbumInfo and AlbumDetail types - Add label to QobuzTrack album summary for track info display
This commit is contained in:
1 parent
04197b98f0
commit
6467ca038e
13 files changed
+775
-8
No files matched your search
@@ -478,6 +478,30 @@ impl QobuzClient {
|
||||
Ok(serde_json::from_value(response)?)
|
||||
}
|
||||
|
||||
/// Get label by ID with albums
|
||||
pub async fn get_label(&self, label_id: u64, limit: u32, offset: u32) -> Result<LabelDetail> {
|
||||
let url = endpoints::build_url(paths::LABEL_GET);
|
||||
let locale = self.locale().await;
|
||||
|
||||
let response: Value = self
|
||||
.http
|
||||
.get(&url)
|
||||
.header("X-App-Id", self.app_id().await?)
|
||||
.query(&[
|
||||
("label_id", label_id.to_string()),
|
||||
("extra", "albums".to_string()),
|
||||
("limit", limit.to_string()),
|
||||
("offset", offset.to_string()),
|
||||
("lang", locale),
|
||||
])
|
||||
.send()
|
||||
.await?
|
||||
.json()
|
||||
.await?;
|
||||
|
||||
Ok(serde_json::from_value(response)?)
|
||||
}
|
||||
|
||||
// === Authenticated endpoints ===
|
||||
|
||||
/// Get stream URL for a track (requires auth + signature)
|
||||
|
||||
@@ -158,6 +158,8 @@ pub struct AlbumSummary {
|
||||
pub title: String,
|
||||
#[serde(default)]
|
||||
pub image: ImageSet,
|
||||
/// Label (if returned in track response)
|
||||
pub label: Option<Label>,
|
||||
}
|
||||
|
||||
/// Artist model
|
||||
@@ -254,13 +256,24 @@ impl ImageSet {
|
||||
}
|
||||
}
|
||||
|
||||
/// Label model
|
||||
/// Label model (basic reference)
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Label {
|
||||
pub id: u64,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// Label detail with albums
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct LabelDetail {
|
||||
pub id: u64,
|
||||
pub name: String,
|
||||
pub description: Option<String>,
|
||||
pub image: Option<ImageSet>,
|
||||
pub albums: Option<SearchResultsPage<Album>>,
|
||||
pub albums_count: Option<u32>,
|
||||
}
|
||||
|
||||
/// Genre model
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Genre {
|
||||
|
||||
@@ -40,6 +40,7 @@ pub struct AlbumInfo {
|
||||
pub year: String,
|
||||
pub release_date: Option<String>,
|
||||
pub label: String,
|
||||
pub label_id: Option<u64>,
|
||||
pub genre: String,
|
||||
pub quality: String,
|
||||
pub track_count: u32,
|
||||
@@ -100,6 +101,7 @@ fn album_to_info(album: &Album) -> AlbumInfo {
|
||||
year,
|
||||
release_date: album.release_date_original.clone(),
|
||||
label: album.label.as_ref().map(|l| l.name.clone()).unwrap_or_default(),
|
||||
label_id: album.label.as_ref().map(|l| l.id),
|
||||
genre: album.genre.as_ref().map(|g| g.name.clone()).unwrap_or_default(),
|
||||
quality: format_quality(album.maximum_bit_depth, album.maximum_sampling_rate),
|
||||
track_count: album.tracks_count.unwrap_or(0),
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use tauri::State;
|
||||
|
||||
use crate::api::{Album, Artist, ArtistAlbums, SearchResultsPage, Track};
|
||||
use crate::api::{Album, Artist, ArtistAlbums, LabelDetail, SearchResultsPage, Track};
|
||||
use crate::api_cache::ApiCacheState;
|
||||
use crate::AppState;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -264,3 +264,25 @@ pub async fn get_similar_artists(
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
/// Get label detail with albums
|
||||
#[tauri::command]
|
||||
pub async fn get_label(
|
||||
label_id: u64,
|
||||
limit: Option<u32>,
|
||||
offset: Option<u32>,
|
||||
state: State<'_, AppState>,
|
||||
) -> Result<LabelDetail, String> {
|
||||
log::info!(
|
||||
"Command: get_label {} limit={:?} offset={:?}",
|
||||
label_id,
|
||||
limit,
|
||||
offset
|
||||
);
|
||||
|
||||
let client = state.client.lock().await;
|
||||
client
|
||||
.get_label(label_id, limit.unwrap_or(100), offset.unwrap_or(0))
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
@@ -436,6 +436,7 @@ pub fn run() {
|
||||
commands::get_artist_detail,
|
||||
commands::get_artist_albums,
|
||||
commands::get_similar_artists,
|
||||
commands::get_label,
|
||||
// Playback commands
|
||||
commands::play_track,
|
||||
commands::prefetch_track,
|
||||
|
||||
Reference in new issue
Block a user