feat(award): resolve award id by name via /award/explore when /album/get omits it

/album/get's AwardDto has id: String? — Qobuz sometimes returns an
award entry with only a name and no id. Rather than disabling the
click or toasting, we look up the id in the Qobuz award catalog.

- Adds v2_get_award_explore (paginated /award/explore) all the way
  through qbz-qobuz → core → bridge → command → invoke_handler.
- New frontend awardCatalogStore caches the full (id, name) list
  lazily, one fetch per session, resolved on first click that needs
  it. Further clicks are instant.
- handleAwardClick goes straight to navigation when id is present,
  falls back to resolveAwardIdByName otherwise. Toast only fires if
  the name isn't in the catalog either (genuinely unknown award).

cc
This commit is contained in:
vicrodh committed 2026-04-14 15:06:15 -06:00
1 parent 9460838223
commit 854eaaa0a4
8 files changed
+176 -7

No files matched your search

+25
View File
@@ -442,6 +442,31 @@ pub async fn v2_get_label_page(
.map_err(RuntimeError::Internal)
}
/// Enumerate award catalog — paginated list of awards with their ids
/// and names. Used by the frontend to resolve award ids by name when
/// /album/get omits them.
#[tauri::command]
pub async fn v2_get_award_explore(
limit: Option<u32>,
offset: Option<u32>,
bridge: State<'_, CoreBridgeState>,
runtime: State<'_, RuntimeManagerState>,
) -> Result<serde_json::Value, RuntimeError> {
runtime
.manager()
.check_requirements(CommandRequirement::RequiresCoreBridgeAuth)
.await?;
let limit = limit.unwrap_or(100);
let offset = offset.unwrap_or(0);
log::info!("[V2] get_award_explore: limit={} offset={}", limit, offset);
let bridge = bridge.get().await;
bridge
.get_award_explore(limit, offset)
.await
.map_err(RuntimeError::Internal)
}
/// Get award page (hero info + award-winning releases).
#[tauri::command]
#[allow(non_snake_case)]
+12
View File
@@ -570,6 +570,18 @@ impl CoreBridge {
.map_err(|e| e.to_string())
}
/// Enumerate award catalog (/award/explore).
pub async fn get_award_explore(
&self,
limit: u32,
offset: u32,
) -> Result<serde_json::Value, String> {
self.core
.get_award_explore(limit, offset)
.await
.map_err(|e| e.to_string())
}
/// Get award page — hero info + award-winning releases.
pub async fn get_award_page(&self, award_id: &str) -> Result<qbz_models::AwardPageData, String> {
self.core
+1
View File
@@ -1603,6 +1603,7 @@ pub fn run() {
commands_v2::v2_get_label_explore,
commands_v2::v2_get_award_page,
commands_v2::v2_get_award_albums,
commands_v2::v2_get_award_explore,
commands_v2::v2_pause_playback,
commands_v2::v2_resume_playback,
commands_v2::v2_stop_playback,