🏡 index : ~doyle/shalom.git

author Jordan Doyle <jordan@doyle.la> 2024-01-11 3:54:10.0 +00:00:00
committer Jordan Doyle <jordan@doyle.la> 2024-01-12 23:12:42.0 +00:00:00
commit
f600528499f0fe19014c194e094469b1f8aac1cf [patch]
tree
cb86e4152437c0a2b1f7cb73403849a6c7b782cd
parent
a82e1a87ba3b97404558db86765a016226c0b178
download
f600528499f0fe19014c194e094469b1f8aac1cf.tar.gz

Improve reliability of track search



Diff

 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(-)

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 = <iced::advanced::widget::Text<'_, Renderer> as Widget<M, Renderer>>::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<Message> {
            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<Message> {
    )
}

async fn load_album_art(image_url: Option<String>) -> 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<T: IntoUrl>(
) -> image::Handle {
    static CACHE: Lazy<Mutex<LruCache<Url, image::Handle>>> =
        Lazy::new(|| Mutex::new(LruCache::new(NonZeroUsize::new(50).unwrap())));
    static CLIENT: Lazy<reqwest::Client> = Lazy::new(reqwest::Client::new);

    let url = url.into_url().unwrap();

@@ -52,7 +53,9 @@ pub async fn load_image<T: IntoUrl>(
        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"),
        }
    }