feat(slint): clickable artist name on AlbumCard -> artist page
Ports Tauri's behavior where clicking an album card's artist name
navigates to that artist (the card body still opens the album).
- AlbumCardItem gains artist-id; populated in every album-card
constructor (home/search/label/foryou/favorites). Artist-page
release cards leave it empty (their subtitle slot shows the year,
not the artist, so it stays non-clickable).
- AlbumCard wraps the artist name in a TouchArea that emits
media-action("artist", artist-id, "open") and brightens on hover
only when an id is known.
- main.rs handles ("artist","open") -> open the artist page;
FavoritesView (which only forwarded clicked) now forwards the
artist action.
cc
This commit is contained in:
8 files changed
+56
-6
No files matched your search
@@ -341,6 +341,7 @@ fn map_compilation_album(album: PageArtistTrackAlbum) -> CardData {
|
|||||||
id: album.id,
|
id: album.id,
|
||||||
title: album.title,
|
title: album.title,
|
||||||
artist: String::new(),
|
artist: String::new(),
|
||||||
|
artist_id: String::new(),
|
||||||
genre: album.genre.map(|g| g.name).unwrap_or_default(),
|
genre: album.genre.map(|g| g.name).unwrap_or_default(),
|
||||||
year: String::new(),
|
year: String::new(),
|
||||||
quality_tier: String::new(),
|
quality_tier: String::new(),
|
||||||
@@ -397,6 +398,7 @@ fn map_release(release: PageArtistRelease) -> CardData {
|
|||||||
id: release.id,
|
id: release.id,
|
||||||
title: release.title,
|
title: release.title,
|
||||||
artist,
|
artist,
|
||||||
|
artist_id: String::new(),
|
||||||
genre: release.genre.map(|g| g.name).unwrap_or_default(),
|
genre: release.genre.map(|g| g.name).unwrap_or_default(),
|
||||||
year,
|
year,
|
||||||
quality_tier,
|
quality_tier,
|
||||||
@@ -439,6 +441,7 @@ fn card_to_item(card: CardData) -> AlbumCardItem {
|
|||||||
id: card.id.into(),
|
id: card.id.into(),
|
||||||
title: card.title.into(),
|
title: card.title.into(),
|
||||||
artist: card.year.clone().into(),
|
artist: card.year.clone().into(),
|
||||||
|
artist_id: "".into(),
|
||||||
genre: card.genre.into(),
|
genre: card.genre.into(),
|
||||||
year: card.year.into(),
|
year: card.year.into(),
|
||||||
quality_tier: card.quality_tier.into(),
|
quality_tier: card.quality_tier.into(),
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ pub struct AlbumCard {
|
|||||||
pub id: String,
|
pub id: String,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub artist: String,
|
pub artist: String,
|
||||||
|
pub artist_id: String,
|
||||||
pub year: String,
|
pub year: String,
|
||||||
pub quality_tier: String,
|
pub quality_tier: String,
|
||||||
pub quality_label: String,
|
pub quality_label: String,
|
||||||
@@ -252,6 +253,7 @@ fn map_album(album: Album) -> AlbumCard {
|
|||||||
id: album.id,
|
id: album.id,
|
||||||
title: album.title,
|
title: album.title,
|
||||||
artist: album.artist.name,
|
artist: album.artist.name,
|
||||||
|
artist_id: album.artist.id.to_string(),
|
||||||
year,
|
year,
|
||||||
quality_tier: tier(album.maximum_bit_depth).to_string(),
|
quality_tier: tier(album.maximum_bit_depth).to_string(),
|
||||||
quality_label,
|
quality_label,
|
||||||
@@ -335,6 +337,7 @@ pub fn apply_favorites(window: &AppWindow, data: FavData) {
|
|||||||
id: a.id.into(),
|
id: a.id.into(),
|
||||||
title: a.title.into(),
|
title: a.title.into(),
|
||||||
artist: a.artist.into(),
|
artist: a.artist.into(),
|
||||||
|
artist_id: a.artist_id.into(),
|
||||||
genre: "".into(),
|
genre: "".into(),
|
||||||
year: a.year.into(),
|
year: a.year.into(),
|
||||||
quality_tier: a.quality_tier.into(),
|
quality_tier: a.quality_tier.into(),
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ pub struct AlbumCard {
|
|||||||
pub id: String,
|
pub id: String,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub artist: String,
|
pub artist: String,
|
||||||
|
pub artist_id: String,
|
||||||
pub year: String,
|
pub year: String,
|
||||||
pub quality_tier: String,
|
pub quality_tier: String,
|
||||||
pub quality_label: String,
|
pub quality_label: String,
|
||||||
@@ -106,6 +107,7 @@ fn map_album(album: Album) -> AlbumCard {
|
|||||||
id: album.id,
|
id: album.id,
|
||||||
title: album.title,
|
title: album.title,
|
||||||
artist: album.artist.name,
|
artist: album.artist.name,
|
||||||
|
artist_id: album.artist.id.to_string(),
|
||||||
year,
|
year,
|
||||||
quality_tier,
|
quality_tier,
|
||||||
quality_label,
|
quality_label,
|
||||||
@@ -146,6 +148,7 @@ where
|
|||||||
id: a.id,
|
id: a.id,
|
||||||
title: a.title,
|
title: a.title,
|
||||||
artist: a.artist,
|
artist: a.artist,
|
||||||
|
artist_id: String::new(),
|
||||||
year: String::new(),
|
year: String::new(),
|
||||||
quality_tier: a.quality_tier,
|
quality_tier: a.quality_tier,
|
||||||
quality_label: a.quality_label,
|
quality_label: a.quality_label,
|
||||||
@@ -366,6 +369,11 @@ where
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|a| a.name.display.clone())
|
.map(|a| a.name.display.clone())
|
||||||
.unwrap_or_else(|| page.name.display.clone()),
|
.unwrap_or_else(|| page.name.display.clone()),
|
||||||
|
artist_id: rel
|
||||||
|
.artist
|
||||||
|
.as_ref()
|
||||||
|
.map(|a| a.id.to_string())
|
||||||
|
.unwrap_or_default(),
|
||||||
year,
|
year,
|
||||||
quality_tier: match bd {
|
quality_tier: match bd {
|
||||||
Some(d) if d >= 24 => "hires",
|
Some(d) if d >= 24 => "hires",
|
||||||
@@ -406,6 +414,7 @@ fn album_items(cards: &[AlbumCard]) -> Vec<AlbumCardItem> {
|
|||||||
id: c.id.clone().into(),
|
id: c.id.clone().into(),
|
||||||
title: c.title.clone().into(),
|
title: c.title.clone().into(),
|
||||||
artist: c.artist.clone().into(),
|
artist: c.artist.clone().into(),
|
||||||
|
artist_id: c.artist_id.clone().into(),
|
||||||
genre: "".into(),
|
genre: "".into(),
|
||||||
year: c.year.clone().into(),
|
year: c.year.clone().into(),
|
||||||
quality_tier: c.quality_tier.clone().into(),
|
quality_tier: c.quality_tier.clone().into(),
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ pub struct CardData {
|
|||||||
pub id: String,
|
pub id: String,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub artist: String,
|
pub artist: String,
|
||||||
|
/// Artist id for the clickable artist name; empty = not clickable
|
||||||
|
/// (e.g. artist-page release cards, whose subtitle slot is the year).
|
||||||
|
pub artist_id: String,
|
||||||
pub genre: String,
|
pub genre: String,
|
||||||
pub year: String,
|
pub year: String,
|
||||||
/// "hires" | "cd" | "" — drives the icon-only quality badge.
|
/// "hires" | "cd" | "" — drives the icon-only quality badge.
|
||||||
@@ -159,6 +162,7 @@ where
|
|||||||
id: album.id,
|
id: album.id,
|
||||||
title: album.title,
|
title: album.title,
|
||||||
artist: album.artist,
|
artist: album.artist,
|
||||||
|
artist_id: String::new(),
|
||||||
genre: String::new(),
|
genre: String::new(),
|
||||||
year: String::new(),
|
year: String::new(),
|
||||||
quality_tier: album.quality_tier,
|
quality_tier: album.quality_tier,
|
||||||
@@ -220,6 +224,11 @@ fn map_album(album: DiscoverAlbum) -> CardData {
|
|||||||
.first()
|
.first()
|
||||||
.map(|a| a.name.clone())
|
.map(|a| a.name.clone())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
let artist_id = album
|
||||||
|
.artists
|
||||||
|
.first()
|
||||||
|
.map(|a| a.id.to_string())
|
||||||
|
.unwrap_or_default();
|
||||||
let genre = album.genre.map(|g| g.name).unwrap_or_default();
|
let genre = album.genre.map(|g| g.name).unwrap_or_default();
|
||||||
let year = album
|
let year = album
|
||||||
.dates
|
.dates
|
||||||
@@ -241,6 +250,7 @@ fn map_album(album: DiscoverAlbum) -> CardData {
|
|||||||
id: album.id,
|
id: album.id,
|
||||||
title: album.title,
|
title: album.title,
|
||||||
artist,
|
artist,
|
||||||
|
artist_id,
|
||||||
genre,
|
genre,
|
||||||
year,
|
year,
|
||||||
quality_tier,
|
quality_tier,
|
||||||
@@ -338,6 +348,7 @@ fn card_to_item(card: CardData) -> AlbumCardItem {
|
|||||||
id: card.id.into(),
|
id: card.id.into(),
|
||||||
title: card.title.into(),
|
title: card.title.into(),
|
||||||
artist: card.artist.into(),
|
artist: card.artist.into(),
|
||||||
|
artist_id: card.artist_id.into(),
|
||||||
genre: card.genre.into(),
|
genre: card.genre.into(),
|
||||||
year: card.year.into(),
|
year: card.year.into(),
|
||||||
quality_tier: card.quality_tier.into(),
|
quality_tier: card.quality_tier.into(),
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ pub struct AlbumCard {
|
|||||||
pub id: String,
|
pub id: String,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub artist: String,
|
pub artist: String,
|
||||||
|
pub artist_id: String,
|
||||||
pub year: String,
|
pub year: String,
|
||||||
pub quality_tier: String,
|
pub quality_tier: String,
|
||||||
pub quality_label: String,
|
pub quality_label: String,
|
||||||
@@ -112,6 +113,7 @@ fn map_album(album: Album) -> AlbumCard {
|
|||||||
id: album.id,
|
id: album.id,
|
||||||
title: album.title,
|
title: album.title,
|
||||||
artist: album.artist.name,
|
artist: album.artist.name,
|
||||||
|
artist_id: album.artist.id.to_string(),
|
||||||
year,
|
year,
|
||||||
quality_tier,
|
quality_tier,
|
||||||
quality_label,
|
quality_label,
|
||||||
@@ -150,6 +152,7 @@ fn to_item(card: AlbumCard) -> AlbumCardItem {
|
|||||||
id: card.id.into(),
|
id: card.id.into(),
|
||||||
title: card.title.into(),
|
title: card.title.into(),
|
||||||
artist: card.artist.into(),
|
artist: card.artist.into(),
|
||||||
|
artist_id: card.artist_id.into(),
|
||||||
genre: "".into(),
|
genre: "".into(),
|
||||||
year: card.year.into(),
|
year: card.year.into(),
|
||||||
quality_tier: card.quality_tier.into(),
|
quality_tier: card.quality_tier.into(),
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ pub struct AlbumRow {
|
|||||||
pub id: String,
|
pub id: String,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub artist: String,
|
pub artist: String,
|
||||||
|
pub artist_id: String,
|
||||||
pub genre: String,
|
pub genre: String,
|
||||||
pub year: String,
|
pub year: String,
|
||||||
pub quality_tier: String,
|
pub quality_tier: String,
|
||||||
@@ -181,6 +182,7 @@ pub fn map_album(album: Album) -> AlbumRow {
|
|||||||
id: album.id,
|
id: album.id,
|
||||||
title: album.title,
|
title: album.title,
|
||||||
artist: album.artist.name,
|
artist: album.artist.name,
|
||||||
|
artist_id: album.artist.id.to_string(),
|
||||||
genre: album
|
genre: album
|
||||||
.genre
|
.genre
|
||||||
.map(|g| g.name)
|
.map(|g| g.name)
|
||||||
@@ -324,6 +326,7 @@ fn album_item(row: AlbumRow) -> AlbumCardItem {
|
|||||||
id: row.id.into(),
|
id: row.id.into(),
|
||||||
title: row.title.into(),
|
title: row.title.into(),
|
||||||
artist: row.artist.into(),
|
artist: row.artist.into(),
|
||||||
|
artist_id: row.artist_id.into(),
|
||||||
genre: row.genre.into(),
|
genre: row.genre.into(),
|
||||||
year: row.year.into(),
|
year: row.year.into(),
|
||||||
quality_tier: row.quality_tier.into(),
|
quality_tier: row.quality_tier.into(),
|
||||||
|
|||||||
@@ -286,13 +286,26 @@ export component AlbumCard inherits Rectangle {
|
|||||||
vertical-alignment: center;
|
vertical-alignment: center;
|
||||||
overflow: elide;
|
overflow: elide;
|
||||||
}
|
}
|
||||||
Text {
|
// Artist name — clickable when an artist id is known,
|
||||||
text: root.album.artist;
|
// navigating to the artist page (1:1 with Tauri).
|
||||||
|
artist-area := TouchArea {
|
||||||
height: 18px;
|
height: 18px;
|
||||||
color: Theme.text-muted;
|
width: artist-text.preferred-width;
|
||||||
font-size: Typography.link;
|
mouse-cursor: root.album.artist-id != "" ? pointer : default;
|
||||||
vertical-alignment: center;
|
clicked => {
|
||||||
overflow: elide;
|
if (root.album.artist-id != "") {
|
||||||
|
root.media-action("artist", root.album.artist-id, "open");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
artist-text := Text {
|
||||||
|
text: root.album.artist;
|
||||||
|
color: root.album.artist-id != "" && artist-area.has-hover
|
||||||
|
? Theme.text-primary
|
||||||
|
: Theme.text-muted;
|
||||||
|
font-size: Typography.link;
|
||||||
|
vertical-alignment: center;
|
||||||
|
overflow: elide;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -355,6 +355,11 @@ export component FavoritesView inherits Rectangle {
|
|||||||
height: root.album-h;
|
height: root.album-h;
|
||||||
album: album;
|
album: album;
|
||||||
clicked(id) => { root.open-album(id); }
|
clicked(id) => { root.open-album(id); }
|
||||||
|
media-action(kind, id, action) => {
|
||||||
|
if (kind == "artist") {
|
||||||
|
root.open-artist(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user