refactor(slint): extract shared album_map module

Move map_album (V2 nested-first with flat fallback), tier/tier_hires,
release-type classification, to_item and sort_album_items out of
label.rs into a shared album_map module. favorites.rs now maps albums
through it too, so favorite album cards gain the AlbumListRow extras
(release_type / quality_detail / track_count / plain_year) and the
hires-without-bit-depth tier fallback — one implementation to maintain
ahead of the Favorites album list/grid toolbar port.

cc
This commit is contained in:
vicrodh committed 2026-05-26 21:12:57 -06:00
1 parent 12048bcee0
commit d80f9c73b5
4 files changed
+221 -250

No files matched your search

+3 -60
View File
@@ -16,6 +16,7 @@ use qbz_models::{Album, Artist, Playlist, Track};
use serde::Deserialize;
use slint::{ComponentHandle, ModelRc, VecModel};
use crate::album_map::{self, map_album, to_item, AlbumCard};
use crate::artwork::{ArtworkJob, ArtworkTarget};
use crate::{
AlbumCardItem, AppWindow, FavoriteArtistItem, FavoriteLabelItem, FavoritePlaylistItem,
@@ -100,19 +101,6 @@ pub struct TrackCard {
pub artwork_url: String,
}
#[derive(Clone)]
pub struct AlbumCard {
pub id: String,
pub title: String,
pub artist: String,
pub artist_id: String,
pub genre: String,
pub year: String,
pub quality_tier: String,
pub quality_label: String,
pub artwork_url: String,
}
#[derive(Clone)]
pub struct ArtistCard {
pub id: String,
@@ -209,14 +197,6 @@ where
})
}
fn tier(bit_depth: Option<u32>) -> &'static str {
match bit_depth {
Some(b) if b > 16 => "hires",
Some(_) => "cd",
None => "",
}
}
fn mmss(secs: u32) -> String {
format!("{}:{:02}", secs / 60, secs % 60)
}
@@ -243,32 +223,12 @@ fn map_track(track: Track) -> TrackCard {
artist_id,
album_id,
duration: mmss(track.duration),
quality_tier: tier(track.maximum_bit_depth).to_string(),
quality_tier: album_map::tier(track.maximum_bit_depth).to_string(),
explicit: track.parental_warning,
artwork_url,
}
}
fn map_album(album: Album) -> AlbumCard {
let year = crate::dates::release_label(album.release_date_original.as_deref());
let genre = album.genre.map(|g| g.name).unwrap_or_default();
let quality_label = match (album.maximum_bit_depth, album.maximum_sampling_rate) {
(Some(bd), Some(sr)) => format!("{}-bit / {} kHz", bd, sr),
_ => String::new(),
};
AlbumCard {
id: album.id,
title: album.title,
artist: album.artist.name,
artist_id: album.artist.id.to_string(),
genre,
year,
quality_tier: tier(album.maximum_bit_depth).to_string(),
quality_label,
artwork_url: album.image.best().cloned().unwrap_or_default(),
}
}
fn map_artist(artist: Artist) -> ArtistCard {
let albums_line = match artist.albums_count {
Some(n) if n > 0 => format!("{} albums", n),
@@ -344,24 +304,7 @@ pub fn apply_favorites(window: &AppWindow, data: FavData) {
state.set_tracks_total(total as i32);
}
FavData::Albums { items, total } => {
let cards: Vec<AlbumCardItem> = items
.into_iter()
.map(|a| AlbumCardItem {
id: a.id.into(),
title: a.title.into(),
artist: a.artist.into(),
artist_id: a.artist_id.into(),
genre: a.genre.into(),
year: a.year.into(),
quality_tier: a.quality_tier.into(),
quality_label: a.quality_label.into(),
ribbon: "".into(),
ribbon_kind: "".into(),
artwork_url: a.artwork_url.into(),
artwork: slint::Image::default(),
..Default::default()
})
.collect();
let cards: Vec<AlbumCardItem> = items.into_iter().map(to_item).collect();
state.set_albums(ModelRc::new(VecModel::from(cards)));
state.set_albums_total(total as i32);
}