From f600528499f0fe19014c194e094469b1f8aac1cf Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Thu, 11 Jan 2024 03:54:10 +0000 Subject: [PATCH] Improve reliability of track search --- assets/images/album_art_test.jpg | 3 --- assets/images/unknown_artist.jpg | 3 +++ shalom/src/magic/header_search.rs | 16 +++++++++++----- shalom/src/pages/room/listen.rs | 54 ++++++++++++++++++++++++++++++++---------------------- shalom/src/subscriptions.rs | 5 ++++- shalom/src/theme.rs | 4 ++-- 6 files changed, 52 insertions(+), 33 deletions(-) delete mode 100644 assets/images/album_art_test.jpg create mode 100644 assets/images/unknown_artist.jpg diff --git a/assets/images/album_art_test.jpg b/assets/images/album_art_test.jpg deleted file mode 100644 index 0aac16c..0000000 --- a/assets/images/album_art_test.jpg +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4cae52d3c493233ab1681825b15059315572c035937c42937c829e6b359188b8 -size 15475 diff --git a/assets/images/unknown_artist.jpg b/assets/images/unknown_artist.jpg new file mode 100644 index 0000000..33d9539 --- /dev/null +++ b/assets/images/unknown_artist.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c7b209e222e78bc720c814b4696ce301bfe3b0c362a50c2289e5bc055b5fc139 +size 6132 diff --git a/shalom/src/magic/header_search.rs b/shalom/src/magic/header_search.rs index e3412d7..9dbc1cf 100644 --- a/shalom/src/magic/header_search.rs +++ b/shalom/src/magic/header_search.rs @@ -44,6 +44,7 @@ where let current_search_box_size = if open { BoxSize::Fill } else { BoxSize::Min }; HeaderSearch { + original_header: header.clone(), header, current_search_box_size, input: iced::widget::text_input("Search...", search_query) @@ -65,6 +66,7 @@ pub enum BoxSize { } pub struct HeaderSearch<'a, M> { + original_header: Text<'a, Renderer>, header: Text<'a, Renderer>, current_search_box_size: BoxSize, on_state_change: fn(bool) -> M, @@ -87,7 +89,7 @@ where fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node { let text_node = as Widget>::layout( - &self.header, + &self.original_header, renderer, limits, ); @@ -255,10 +257,14 @@ where *last_draw = Instant::now(); text_opacity.advance_by(elapsed); - self.header = self.header.clone().style(iced::theme::Text::Color(Color { - a: text_opacity.now(), - ..Color::WHITE - })); + self.header = self + .header + .clone() + .style(iced::theme::Text::Color(Color { + a: text_opacity.now(), + ..Color::WHITE + })) + .size(60.0 - (2.0 * (1.0 - text_opacity.now()))); search_box_size.advance_by(elapsed); self.current_search_box_size = BoxSize::Fixed(Size { diff --git a/shalom/src/pages/room/listen.rs b/shalom/src/pages/room/listen.rs index 471fdc4..f24ee92 100644 --- a/shalom/src/pages/room/listen.rs +++ b/shalom/src/pages/room/listen.rs @@ -22,7 +22,7 @@ use crate::{ subscriptions::{ download_image, find_fanart_urls, find_musicbrainz_artist, load_image, MaybePendingImage, }, - theme::{darken_image, trim_transparent_padding}, + theme::{darken_image, trim_transparent_padding, Image}, widgets, }; @@ -373,16 +373,16 @@ impl SearchState { pub fn open(&self, search: String) -> SearchState { match self { Self::Open { results, .. } => Self::Open { + needs_result: !search.is_empty(), + waiting_for_result: !search.is_empty(), search, results: results.clone(), - needs_result: true, - waiting_for_result: true, }, Self::Closed => Self::Open { + needs_result: !search.is_empty(), + waiting_for_result: !search.is_empty(), search, results: vec![], - needs_result: true, - waiting_for_result: true, }, } } @@ -456,63 +456,65 @@ fn search_spotify(search: String, token: &str) -> Subscription { let results = FuturesUnordered::new(); for track in &res.tracks.items { - let image_url = track.album.images[0].url.to_string(); + let image_url = track.album.images.last().map(|v| v.url.to_string()); let track_name = track.name.to_string(); let artist_name = track.artists.iter().map(|v| &v.name).join(", "); let uri = track.uri.to_string(); - results.push( + results.push(tokio::spawn( async move { - let image = load_image(image_url, identity).await; + let image = load_album_art(image_url).await; SearchResult::track(image, track_name, artist_name, uri) } .boxed(), - ); + )); } for artist in &res.artists.items { - let image_url = artist.images[0].url.to_string(); + let image_url = artist.images.last().map(|v| v.url.to_string()); let artist_name = artist.name.to_string(); let uri = artist.uri.to_string(); - results.push( + results.push(tokio::spawn( async move { - let image = load_image(image_url, identity).await; + let image = load_album_art(image_url).await; SearchResult::artist(image, artist_name, uri) } .boxed(), - ); + )); } for albums in &res.albums.items { - let image_url = albums.images[0].url.to_string(); + let image_url = albums.images.last().map(|v| v.url.to_string()); let album_name = albums.name.to_string(); let uri = albums.uri.to_string(); - results.push( + results.push(tokio::spawn( async move { - let image = load_image(image_url, identity).await; + let image = load_album_art(image_url).await; SearchResult::album(image, album_name, uri) } .boxed(), - ); + )); } for playlist in &res.playlists.items { - let image_url = playlist.images[0].url.to_string(); + let image_url = playlist.images.last().map(|v| v.url.to_string()); let playlist_name = playlist.name.to_string(); let uri = playlist.uri.to_string(); - results.push( + results.push(tokio::spawn( async move { - let image = load_image(image_url, identity).await; + let image = load_album_art(image_url).await; SearchResult::playlist(image, playlist_name, uri) } .boxed(), - ); + )); } - results.map(Message::SpotifySearchResult) + results + .map(Result::unwrap) + .map(Message::SpotifySearchResult) }) .chain(stream::once(future::ready( Message::SpotifySearchResultDone, @@ -520,6 +522,14 @@ fn search_spotify(search: String, token: &str) -> Subscription { ) } +async fn load_album_art(image_url: Option) -> Handle { + if let Some(image_url) = image_url { + load_image(image_url, identity).await + } else { + Image::UnknownArtist.into() + } +} + #[derive(Deserialize, Yokeable)] pub struct SpotifySearchResult<'a> { #[serde(borrow)] diff --git a/shalom/src/subscriptions.rs b/shalom/src/subscriptions.rs index 60c442a..d3614ae 100644 --- a/shalom/src/subscriptions.rs +++ b/shalom/src/subscriptions.rs @@ -45,6 +45,7 @@ pub async fn load_image( ) -> image::Handle { static CACHE: Lazy>> = Lazy::new(|| Mutex::new(LruCache::new(NonZeroUsize::new(50).unwrap()))); + static CLIENT: Lazy = Lazy::new(reqwest::Client::new); let url = url.into_url().unwrap(); @@ -52,7 +53,9 @@ pub async fn load_image( return handle.clone(); } - let bytes = reqwest::get(url.clone()) + let bytes = CLIENT + .get(url.clone()) + .send() .await .unwrap() .bytes() diff --git a/shalom/src/theme.rs b/shalom/src/theme.rs index 2728ef9..8ee9181 100644 --- a/shalom/src/theme.rs +++ b/shalom/src/theme.rs @@ -225,7 +225,7 @@ pub enum Image { Bedroom, DiningRoom, Sunset, - AlbumArtTest, + UnknownArtist, } impl Image { @@ -250,7 +250,7 @@ impl Image { Image::Bedroom => image!("../../assets/images/bedroom.jpg"), Image::DiningRoom => image!("../../assets/images/dining_room.jpg"), Image::Sunset => image!("../../assets/images/sunset-blur.jpg"), - Image::AlbumArtTest => image!("../../assets/images/album_art_test.jpg"), + Image::UnknownArtist => image!("../../assets/images/unknown_artist.jpg"), } } -- libgit2 1.7.2