diff --git a/resources/album_carousel_album.blp b/resources/album_carousel_album.blp index a2f511b..a0835f9 100644 --- a/resources/album_carousel_album.blp +++ b/resources/album_carousel_album.blp @@ -12,7 +12,7 @@ template $AudreyUiAlbumCarouselAlbum: Adw.Bin { spacing: 6; Image { - icon-name: "media-optical-cd"; + paintable: bind template.cover_art; pixel-size: 160; halign: center; hexpand: false; diff --git a/resources/style.css b/resources/style.css index 9f80e8d..5cbbeba 100644 --- a/resources/style.css +++ b/resources/style.css @@ -93,7 +93,6 @@ gridview.albums child image { .album-carousel listview row image { border-radius: 3px; - background-color: oklch(0 0 0); } .album-carousel .labels { diff --git a/src/ui/album_carousel.rs b/src/ui/album_carousel.rs index 360cea5..9a7e9ed 100644 --- a/src/ui/album_carousel.rs +++ b/src/ui/album_carousel.rs @@ -157,7 +157,7 @@ mod imp { pub fn on_bind(&self, item: >k::ListItem, _factory: >k::SignalListItemFactory) { let child: super::Album = item.child().and_downcast().unwrap(); let album: model::Album = item.item().and_downcast().unwrap(); - child.bind(&album); + child.bind(self.client.borrow().as_ref().unwrap(), &album); } #[template_callback] diff --git a/src/ui/album_carousel/album.rs b/src/ui/album_carousel/album.rs index 463ba93..df67327 100644 --- a/src/ui/album_carousel/album.rs +++ b/src/ui/album_carousel/album.rs @@ -1,7 +1,10 @@ use crate::model; +use adw::gdk; use adw::{prelude::*, subclass::prelude::*}; use glib::subclass::InitializingObject; -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; +use tokio::sync::Semaphore; +use tracing::{event, Level}; mod imp { use super::*; @@ -12,6 +15,11 @@ mod imp { pub struct Album { #[property(get, set, nullable)] item: RefCell>, + + #[property(get, set, nullable)] + cover_art: RefCell>, + + pub cover_art_loading: Cell>>, } #[glib::object_subclass] @@ -37,6 +45,9 @@ mod imp { impl BinImpl for Album {} } +// only fetch 10 thumbnails at a time +static SEM: Semaphore = Semaphore::const_new(10); + glib::wrapper! { pub struct Album(ObjectSubclass) @extends adw::Bin, gtk::Widget, @@ -44,11 +55,37 @@ glib::wrapper! { } impl Album { - pub fn bind(&self, album: &model::Album) { + pub fn bind(&self, client: &crate::wrappers::Client, album: &model::Album) { self.set_item(Some(album)); + + let client = client.clone(); + let id = album.id(); + let this = self.downgrade(); + let scale_factor = self.scale_factor() as u32; + let handle = glib::spawn_future_local(async move { + let _permit = SEM.acquire().await.unwrap(); + + // see pixel-size in album_carousel_album.blp + let pixbuf = match client.cover_art(&id, Some(160 * scale_factor)).await { + Ok(image) => audrey::util::image_to_pixbuf(image), + Err(err) => { + event!(Level::ERROR, "could not fetch cover for album {id}: {err}"); + return; + } + }; + + let this = this.upgrade().unwrap(); + this.set_cover_art(Some(gdk::Texture::for_pixbuf(&pixbuf))); + }); + + self.imp().cover_art_loading.replace(Some(handle)); } pub fn unbind(&self) { self.set_item(None::); + if let Some(handle) = self.imp().cover_art_loading.take() { + handle.abort(); + } + self.set_cover_art(None::); } }