From e3ca6f0088db7b60cce057b666b109af19f558ca Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Thu, 11 Jan 2024 01:30:12 +0000 Subject: [PATCH] Design for enriching search results with metadata --- 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() -> Search { +pub fn search(theme: Theme, results: Vec) -> Search { Search { on_track_press: None, + theme, + results, } } pub struct Search { on_track_press: Option M>, + theme: Theme, + results: Vec, } -impl Search { - pub fn view(&self, style: &Theme) -> Element<'static, M, Renderer> { +impl Component for Search { + type State = (); + type Event = Event; + + fn update(&mut self, _state: &mut Self::State, event: Self::Event) -> Option { + 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 Search { } } -fn track_card( - title: &str, - artist: &str, - image_handle: impl Into, - 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 From> for Element<'static, M, Renderer> { + fn from(value: Search) -> Self { + component(value) + } +} + +#[derive(Clone)] +pub enum Event { + OnTrackPress(String), +} + +fn result_card(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"), + } + } +} -- libgit2 1.7.2