🏡 index : ~doyle/shalom.git

author Jordan Doyle <jordan@doyle.la> 2024-01-11 1:30:12.0 +00:00:00
committer Jordan Doyle <jordan@doyle.la> 2024-01-11 1:30:12.0 +00:00:00
commit
e3ca6f0088db7b60cce057b666b109af19f558ca [patch]
tree
323ec95bf3820eed7440dd14aa0834de05523c84
parent
697689c3ab4289810e1dc84c89245a70bf008c00
download
e3ca6f0088db7b60cce057b666b109af19f558ca.tar.gz

Design for enriching search results with metadata



Diff

 shalom/src/pages/room/listen.rs        |  50 ++++++++++++++-
 shalom/src/pages/room/listen/search.rs | 113 ++++++++++++++++++++++++++--------
 2 files changed, 137 insertions(+), 26 deletions(-)

diff --git a/shalom/src/pages/room/listen.rs b/shalom/src/pages/room/listen.rs
index 71e3dc7..84a7124 100644
--- a/shalom/src/pages/room/listen.rs
+++ b/shalom/src/pages/room/listen.rs
@@ -14,8 +14,9 @@ use crate::{
    hass_client::MediaPlayerRepeat,
    magic::header_search::header_search,
    oracle::{MediaPlayerSpeaker, MediaPlayerSpeakerState, Oracle, Room},
    pages::room::listen::search::SearchResult,
    subscriptions::{download_image, find_fanart_urls, find_musicbrainz_artist, MaybePendingImage},
    theme::{darken_image, trim_transparent_padding},
    theme::{darken_image, trim_transparent_padding, Image},
    widgets,
};

@@ -174,7 +175,52 @@ impl Listen {

    pub fn view(&self, style: &Theme) -> Element<'_, Message, Renderer> {
        if self.search_open && !self.search_query.is_empty() {
            container(search::search().view(style))
            let results = vec![
                SearchResult::album(Image::AlbumArtTest.into(), "Some Album".to_string()),
                SearchResult::track(
                    Image::AlbumArtTest.into(),
                    "Some Track".to_string(),
                    "Some Artist".to_string(),
                ),
                SearchResult::playlist(Image::AlbumArtTest.into(), "Some Playlist".to_string()),
                SearchResult::album(Image::AlbumArtTest.into(), "Some Album".to_string()),
                SearchResult::track(
                    Image::AlbumArtTest.into(),
                    "Some Track".to_string(),
                    "Some Artist".to_string(),
                ),
                SearchResult::playlist(Image::AlbumArtTest.into(), "Some Playlist".to_string()),
                SearchResult::album(Image::AlbumArtTest.into(), "Some Album".to_string()),
                SearchResult::track(
                    Image::AlbumArtTest.into(),
                    "Some Track".to_string(),
                    "Some Artist".to_string(),
                ),
                SearchResult::playlist(Image::AlbumArtTest.into(), "Some Playlist".to_string()),
                SearchResult::album(Image::AlbumArtTest.into(), "Some Album".to_string()),
                SearchResult::track(
                    Image::AlbumArtTest.into(),
                    "Some Track".to_string(),
                    "Some Artist".to_string(),
                ),
                SearchResult::playlist(Image::AlbumArtTest.into(), "Some Playlist".to_string()),
                SearchResult::album(Image::AlbumArtTest.into(), "Some Album".to_string()),
                SearchResult::track(
                    Image::AlbumArtTest.into(),
                    "Some Track".to_string(),
                    "Some Artist".to_string(),
                ),
                SearchResult::playlist(Image::AlbumArtTest.into(), "Some Playlist".to_string()),
                SearchResult::album(Image::AlbumArtTest.into(), "Some Album".to_string()),
                SearchResult::track(
                    Image::AlbumArtTest.into(),
                    "Some Track".to_string(),
                    "Some Artist".to_string(),
                ),
                SearchResult::playlist(Image::AlbumArtTest.into(), "Some Playlist".to_string()),
            ];

            container(search::search(style.clone(), results))
                .padding([0, 40, 40, 40])
                .width(Length::Fill)
                .into()
diff --git a/shalom/src/pages/room/listen/search.rs b/shalom/src/pages/room/listen/search.rs
index 64d83cc..486970b 100644
--- a/shalom/src/pages/room/listen/search.rs
+++ b/shalom/src/pages/room/listen/search.rs
@@ -1,40 +1,50 @@
use std::fmt::{Display, Formatter};

use iced::{
    theme,
    widget::{
        column, container, container::Appearance, horizontal_rule, image, image::Handle, row,
        scrollable, text, Column,
        column, component, container, container::Appearance, horizontal_rule, image, image::Handle,
        row, scrollable, text, Column, Component,
    },
    Alignment, Background, Color, Element, Length, Renderer, Theme,
};

use crate::{theme::Image, widgets::mouse_area::mouse_area};
use crate::widgets::mouse_area::mouse_area;

pub fn search<M: Clone + 'static>() -> Search<M> {
pub fn search<M: Clone + 'static>(theme: Theme, results: Vec<SearchResult>) -> Search<M> {
    Search {
        on_track_press: None,
        theme,
        results,
    }
}

pub struct Search<M> {
    on_track_press: Option<fn(String) -> M>,
    theme: Theme,
    results: Vec<SearchResult>,
}

impl<M: Clone + 'static> Search<M> {
    pub fn view(&self, style: &Theme) -> Element<'static, M, Renderer> {
impl<M: Clone + 'static> Component<M, Renderer> for Search<M> {
    type State = ();
    type Event = Event;

    fn update(&mut self, _state: &mut Self::State, event: Self::Event) -> Option<M> {
        match event {
            Event::OnTrackPress(id) => self.on_track_press.map(|f| (f)(id)),
        }
    }

    fn view(&self, _state: &Self::State) -> Element<'_, Self::Event, Renderer> {
        let mut col = Column::new();

        for i in 0..20 {
        for (i, result) in self.results.iter().enumerate() {
            if i != 0 {
                col = col.push(hr());
            }

            let track = mouse_area(search_item_container(track_card(
                "title",
                "artist",
                Image::AlbumArtTest,
                style,
            )))
            .on_press(self.on_track_press.map(|f| (f)("hello world".to_string())));
            let track = mouse_area(search_item_container(result_card(result, &self.theme)))
                .on_press(Event::OnTrackPress("hello world".to_string()));

            col = col.push(track);
        }
@@ -43,18 +53,24 @@ impl<M: Clone + 'static> Search<M> {
    }
}

fn track_card<M: 'static>(
    title: &str,
    artist: &str,
    image_handle: impl Into<Handle>,
    style: &Theme,
) -> Element<'static, M, Renderer> {
    let title = text(title).style(style.extended_palette().background.base.text);
    let artist = text(artist).style(style.extended_palette().background.strong.color);
impl<M: 'static + Clone> From<Search<M>> for Element<'static, M, Renderer> {
    fn from(value: Search<M>) -> Self {
        component(value)
    }
}

#[derive(Clone)]
pub enum Event {
    OnTrackPress(String),
}

fn result_card<M: 'static>(result: &SearchResult, style: &Theme) -> Element<'static, M, Renderer> {
    let main_text = text(&result.title).style(style.extended_palette().background.base.text);
    let sub_text = text(&result.metadata).style(style.extended_palette().background.strong.color);

    row![
        image(image_handle).width(64).height(64),
        column![title, artist,]
        image(result.image.clone()).width(64).height(64),
        column![main_text, sub_text,]
    ]
    .align_items(Alignment::Center)
    .spacing(10)
@@ -100,3 +116,52 @@ impl container::StyleSheet for SearchContainer {
        }
    }
}

#[allow(clippy::module_name_repetitions)]
pub struct SearchResult {
    image: Handle,
    title: String,
    metadata: ResultMetadata,
}

impl SearchResult {
    pub fn track(image: Handle, title: String, artist: String) -> Self {
        Self {
            image,
            title,
            metadata: ResultMetadata::Track(artist),
        }
    }

    pub fn playlist(image: Handle, title: String) -> Self {
        Self {
            image,
            title,
            metadata: ResultMetadata::Playlist,
        }
    }

    pub fn album(image: Handle, title: String) -> Self {
        Self {
            image,
            title,
            metadata: ResultMetadata::Album,
        }
    }
}

pub enum ResultMetadata {
    Track(String),
    Playlist,
    Album,
}

impl Display for ResultMetadata {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            ResultMetadata::Track(v) => write!(f, "Track • {v}"),
            ResultMetadata::Playlist => write!(f, "Playlist"),
            ResultMetadata::Album => write!(f, "Album"),
        }
    }
}