From a729bbf6b8a35ee55451e1e327b03d856e4fd1d5 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Sun, 31 Dec 2023 17:51:34 +0000 Subject: [PATCH] Add room sidebar & blurred image background --- assets/icons/hvac.svg | 1 + assets/icons/speaker-full.svg | 1 + assets/images/sunset-blur.jpg | 3 +++ shalom/src/hass_client.rs | 2 +- shalom/src/main.rs | 79 ++++++++----------------------------------------------------------------------- shalom/src/oracle.rs | 2 +- shalom/src/pages/room.rs | 48 ++++++++++++++++++++++++++++++++++++++---------- shalom/src/theme.rs | 6 ++++++ shalom/src/widgets/image_background.rs | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ shalom/src/widgets/media_player.rs | 40 ++++++++++++++++++++++------------------ shalom/src/widgets/mod.rs | 2 ++ shalom/src/widgets/room_navigation.rs | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ shalom/src/widgets/track_card.rs | 8 ++++---- 13 files changed, 503 insertions(+), 105 deletions(-) create mode 100644 assets/icons/hvac.svg create mode 100644 assets/icons/speaker-full.svg create mode 100644 assets/images/sunset-blur.jpg create mode 100644 shalom/src/widgets/image_background.rs create mode 100644 shalom/src/widgets/room_navigation.rs diff --git a/assets/icons/hvac.svg b/assets/icons/hvac.svg new file mode 100644 index 0000000..5442b33 --- /dev/null +++ b/assets/icons/hvac.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/speaker-full.svg b/assets/icons/speaker-full.svg new file mode 100644 index 0000000..47f7d00 --- /dev/null +++ b/assets/icons/speaker-full.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/sunset-blur.jpg b/assets/images/sunset-blur.jpg new file mode 100644 index 0000000..9fa3195 --- /dev/null +++ b/assets/images/sunset-blur.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bdebb781c73a42e84e0884ceb1c1ee7bd460490786e7dd50658fdaf425a0f099 +size 33479 diff --git a/shalom/src/hass_client.rs b/shalom/src/hass_client.rs index 9f8df6d..2304128 100644 --- a/shalom/src/hass_client.rs +++ b/shalom/src/hass_client.rs @@ -760,7 +760,7 @@ pub mod responses { #[serde(borrow)] pub dynamics: Option>, #[serde(borrow)] - pub friendly_name: Cow<'a, str>, + pub friendly_name: Option>, pub color_mode: Option, pub brightness: Option, pub color_temp_kelvin: Option, diff --git a/shalom/src/main.rs b/shalom/src/main.rs index b417c5b..ef847f7 100644 --- a/shalom/src/main.rs +++ b/shalom/src/main.rs @@ -12,18 +12,11 @@ mod widgets; use std::sync::Arc; use iced::{ - alignment::{Horizontal, Vertical}, - widget::{column, container, row, scrollable, svg, Column}, - window, Application, Command, ContentFit, Element, Length, Renderer, Settings, Subscription, - Theme, + widget::{column, Column}, + window, Application, Command, Element, Renderer, Settings, Subscription, Theme, }; -use crate::{ - config::Config, - oracle::Oracle, - theme::{Icon, Image}, - widgets::{context_menu::ContextMenu, mouse_area::mouse_area}, -}; +use crate::{config::Config, oracle::Oracle, theme::Image, widgets::context_menu::ContextMenu}; pub struct Shalom { page: ActivePage, @@ -33,14 +26,6 @@ pub struct Shalom { } impl Shalom { - fn is_on_home_page(&self) -> bool { - match (&self.page, self.home_room) { - (ActivePage::Omni(_), None) => true, - (ActivePage::Room(r), Some(id)) if r.room_id() == id => true, - _ => false, - } - } - fn build_home_route(&self) -> ActivePage { self.home_room.map_or_else( || self.build_omni_route(), @@ -213,6 +198,10 @@ impl Application for Shalom { Message::UpdateLightResult, ) } + Some(pages::room::Event::Exit) => { + self.page = self.build_omni_route(); + Command::none() + } None => Command::none(), }, (Message::LightControlMenu(e), _, Some(ActiveContextMenu::LightControl(menu))) => { @@ -244,59 +233,7 @@ impl Application for Shalom { ActivePage::Omni(omni) => omni.view().map(Message::OmniEvent), }; - let mut content = Column::new().push(scrollable(page_content)); - - let (show_back, show_home) = match &self.page { - _ if self.is_on_home_page() => (true, false), - ActivePage::Loading => (false, false), - ActivePage::Omni(_) => (false, true), - ActivePage::Room(_) => (true, true), - }; - - let back = mouse_area( - svg(Icon::Back) - .height(32) - .width(32) - .content_fit(ContentFit::None), - ) - .on_press(Message::OpenOmniPage); - let home = mouse_area( - svg(Icon::Home) - .height(32) - .width(32) - .content_fit(ContentFit::None), - ) - .on_press(Message::OpenHomePage); - - let navigation = match (show_back, show_home) { - (true, true) => Some(Element::from( - row![ - back, - container(home) - .width(Length::Fill) - .align_x(Horizontal::Right), - ] - .height(32), - )), - (false, true) => Some(Element::from( - row![container(home) - .width(Length::Fill) - .align_x(Horizontal::Right),] - .height(32), - )), - (true, false) => Some(Element::from(back)), - (false, false) => None, - }; - - if let Some(navigation) = navigation { - content = content.push( - container(navigation) - .height(Length::Fill) - .width(Length::Fill) - .align_y(Vertical::Bottom) - .padding(40), - ); - } + let content = Column::new().push(page_content); if let Some(context_menu) = &self.context_menu { let context_menu = match context_menu { diff --git a/shalom/src/oracle.rs b/shalom/src/oracle.rs index 409e7d5..82a719b 100644 --- a/shalom/src/oracle.rs +++ b/shalom/src/oracle.rs @@ -616,7 +616,7 @@ impl From<(StateLightAttributes<'_>, &str)> for Light { supported_color_modes: value.supported_color_modes.clone(), mode: value.mode.map(Cow::into_owned).map(Box::from), dynamics: value.dynamics.map(Cow::into_owned).map(Box::from), - friendly_name: Box::from(value.friendly_name.as_ref()), + friendly_name: Box::from(value.friendly_name.as_deref().unwrap_or("unknown")), color_mode: value.color_mode, brightness: value.brightness, color_temp_kelvin: value.color_temp_kelvin, diff --git a/shalom/src/pages/room.rs b/shalom/src/pages/room.rs index 0f3f245..f3d5e69 100644 --- a/shalom/src/pages/room.rs +++ b/shalom/src/pages/room.rs @@ -4,9 +4,9 @@ use iced::{ advanced::graphics::core::Element, font::{Stretch, Weight}, futures::StreamExt, - subscription, - widget::{container, image::Handle, text, Column, Row}, - Font, Renderer, Subscription, + subscription, theme, + widget::{container, image::Handle, row, text, Column, Row}, + Color, Font, Length, Renderer, Subscription, }; use url::Url; @@ -16,7 +16,11 @@ use crate::{ subscriptions::download_image, theme::Icon, widgets, - widgets::colour_picker::colour_from_hsb, + widgets::{ + colour_picker::colour_from_hsb, + image_background::image_background, + room_navigation::{Page, RoomNavigation}, + }, }; #[derive(Debug)] @@ -27,6 +31,7 @@ pub struct Room { speaker: Option<(&'static str, MediaPlayerSpeaker)>, now_playing_image: Option, lights: BTreeMap<&'static str, Light>, + current_page: Page, } impl Room { @@ -43,6 +48,7 @@ impl Room { speaker, now_playing_image: None, lights, + current_page: Page::Listen, } } @@ -137,15 +143,23 @@ impl Room { speaker.shuffle = new; Some(Event::SetSpeakerShuffle(id, new)) } + Message::ChangePage(page) => { + self.current_page = page; + None + } + Message::Exit => Some(Event::Exit), } } pub fn view(&self) -> Element<'_, Message, Renderer> { - let header = text(self.room.name.as_ref()).size(60).font(Font { - weight: Weight::Bold, - stretch: Stretch::Condensed, - ..Font::with_name("Helvetica Neue") - }); + let header = text(self.room.name.as_ref()) + .size(60) + .font(Font { + weight: Weight::Bold, + stretch: Stretch::Condensed, + ..Font::with_name("Helvetica Neue") + }) + .style(theme::Text::Color(Color::WHITE)); let light = |id, light: &Light| { let mut toggle_card = widgets::toggle_card::toggle_card( @@ -199,7 +213,18 @@ impl Room { .spacing(10); col = col.push(lights); - col.into() + row![ + RoomNavigation::new(self.current_page) + .width(Length::FillPortion(2)) + .on_change(Message::ChangePage) + .on_exit(Message::Exit), + image_background(crate::theme::Image::Sunset, col.width(Length::Fill).into()) + .width(Length::FillPortion(15)) + .height(Length::Fill), + ] + .height(Length::Fill) + .width(Length::Fill) + .into() } pub fn subscription(&self) -> Subscription { @@ -256,6 +281,7 @@ pub enum Event { SetSpeakerRepeat(&'static str, MediaPlayerRepeat), SpeakerNextTrack(&'static str), SpeakerPreviousTrack(&'static str), + Exit, } #[derive(Clone, Debug)] @@ -273,4 +299,6 @@ pub enum Message { OnSpeakerRepeatChange(MediaPlayerRepeat), OnSpeakerNextTrack, OnSpeakerPreviousTrack, + ChangePage(Page), + Exit, } diff --git a/shalom/src/theme.rs b/shalom/src/theme.rs index 76b475b..e2d00f1 100644 --- a/shalom/src/theme.rs +++ b/shalom/src/theme.rs @@ -57,7 +57,9 @@ pub enum Icon { Snow, ClearDay, Wind, + Hvac, Shuffle, + SpeakerFull, } impl Icon { @@ -77,6 +79,7 @@ impl Icon { Self::Hamburger => image!("hamburger"), Self::Speaker => image!("speaker"), Self::SpeakerMuted => image!("speaker-muted"), + Self::SpeakerFull => image!("speaker-full"), Self::Backward => image!("backward"), Self::Forward => image!("forward"), Self::Play => image!("play"), @@ -94,6 +97,7 @@ impl Icon { Self::Rain => image!("rain"), Self::Snow => image!("snow"), Self::ClearDay => image!("clear-day"), + Self::Hvac => image!("hvac"), Self::Wind => image!("wind"), Self::Shuffle => image!("shuffle"), Self::Repeat1 => image!("repeat-1"), @@ -114,6 +118,7 @@ pub enum Image { Bathroom, Bedroom, DiningRoom, + Sunset, } impl Image { @@ -137,6 +142,7 @@ impl Image { Image::Bathroom => image!("../../assets/images/bathroom.jpg"), Image::Bedroom => image!("../../assets/images/bedroom.jpg"), Image::DiningRoom => image!("../../assets/images/dining_room.jpg"), + Image::Sunset => image!("../../assets/images/sunset-blur.jpg"), } } diff --git a/shalom/src/widgets/image_background.rs b/shalom/src/widgets/image_background.rs new file mode 100644 index 0000000..3de7cfb --- /dev/null +++ b/shalom/src/widgets/image_background.rs @@ -0,0 +1,202 @@ +use iced::{ + advanced::{ + image::Data, + layout::{Limits, Node}, + overlay, + renderer::Style, + widget::Tree, + Clipboard, Layout, Shell, Widget, + }, + event::Status, + mouse::Cursor, + widget::image, + Alignment, ContentFit, Element, Event, Length, Point, Rectangle, Size, Vector, +}; + +pub fn image_background<'a, M: 'a, R>( + handle: impl Into, + el: Element<'a, M, R>, +) -> ImageBackground<'a, M, R> { + let image_handle = handle.into(); + + ImageBackground { + image_handle: image_handle.clone(), + el, + width: Length::FillPortion(1), + height: Length::Fixed(128.0), + } +} + +pub struct ImageBackground<'a, M, R> { + image_handle: image::Handle, + el: Element<'a, M, R>, + width: Length, + height: Length, +} + +impl<'a, M, R> ImageBackground<'a, M, R> { + pub fn height(mut self, height: Length) -> Self { + self.height = height; + self + } + + pub fn width(mut self, width: Length) -> Self { + self.width = width; + self + } +} + +impl< + 'a, + M: Clone, + R: iced::advanced::Renderer + + iced::advanced::image::Renderer, + > Widget for ImageBackground<'a, M, R> +{ + fn width(&self) -> Length { + self.width + } + + fn height(&self) -> Length { + self.height + } + + fn layout(&self, _renderer: &R, limits: &Limits) -> Node { + let limits = limits.width(self.width).height(self.height); + let size = limits.resolve(Size::ZERO); + + Node::new(size) + } + + fn draw( + &self, + _state: &Tree, + renderer: &mut R, + _theme: &::Theme, + _style: &Style, + layout: Layout<'_>, + _cursor: Cursor, + _viewport: &Rectangle, + ) { + let bounds = layout.bounds(); + + // The raw w/h of the underlying image, renderer.dimensions is _really_ + // slow so enforce the use of preparsed images from `theme`. + #[allow(clippy::cast_precision_loss)] + let image_size = match self.image_handle.data() { + Data::Rgba { width, height, .. } => Size::new(*width as f32, *height as f32), + Data::Path(_) | Data::Bytes(_) => panic!("only parsed images are supported"), + }; + + let adjusted_fit = ContentFit::Cover.fit(image_size, bounds.size()); + + renderer.with_layer(bounds, |renderer| { + let offset = Vector::new( + (bounds.width - adjusted_fit.width).min(0.0) / 1.5, + (bounds.height - adjusted_fit.height).min(0.0) / 1.5, + ); + + let drawing_bounds = Rectangle { + width: adjusted_fit.width, + height: adjusted_fit.height, + ..bounds + }; + + renderer.draw(self.image_handle.clone(), drawing_bounds + offset); + }); + } + + fn children(&self) -> Vec { + vec![Tree::new(&self.el)] + } + + fn diff(&self, tree: &mut Tree) { + tree.diff_children(&[&self.el]); + } + + fn overlay<'b>( + &'b mut self, + state: &'b mut Tree, + layout: Layout<'_>, + _renderer: &R, + ) -> Option> { + Some( + overlay::Group::with_children(vec![overlay::Element::new( + layout.position(), + Box::new(Overlay { + el: &mut self.el, + tree: &mut state.children[0], + size: layout.bounds().size(), + }), + )]) + .overlay(), + ) + } +} + +struct Overlay<'a, 'b, M, R> { + el: &'b mut Element<'a, M, R>, + tree: &'b mut Tree, + size: Size, +} + +impl<'a, 'b, M: Clone, R: iced::advanced::Renderer> overlay::Overlay + for Overlay<'a, 'b, M, R> +{ + fn layout(&self, renderer: &R, _bounds: Size, position: Point) -> Node { + let limits = Limits::new(Size::ZERO, self.size).pad([0, 0, 10, 0].into()); + + let mut child = self.el.as_widget().layout(renderer, &limits); + child.align(Alignment::Start, Alignment::Start, limits.max()); + + let mut node = Node::with_children(self.size, vec![child]); + node.move_to(position); + + node + } + + fn draw( + &self, + renderer: &mut R, + theme: &::Theme, + style: &Style, + layout: Layout<'_>, + cursor: Cursor, + ) { + self.el.as_widget().draw( + self.tree, + renderer, + theme, + style, + layout.children().next().unwrap(), + cursor, + &layout.bounds(), + ); + } + + fn on_event( + &mut self, + _event: Event, + _layout: Layout<'_>, + _cursor: Cursor, + _renderer: &R, + _clipboard: &mut dyn Clipboard, + _shell: &mut Shell<'_, M>, + ) -> Status { + Status::Ignored + // self.el.as_widget_mut().on_event(self.tree, event, layout, cursor, renderer, clipboard, + // shell, &layout.children().next().unwrap().bounds()) + } +} + +impl<'a, M, R> From> for Element<'a, M, R> +where + M: 'a + Clone, + R: iced::advanced::Renderer + + iced::advanced::image::Renderer + + 'a, +{ + fn from(modal: ImageBackground<'a, M, R>) -> Self { + Element::new(modal) + } +} diff --git a/shalom/src/widgets/media_player.rs b/shalom/src/widgets/media_player.rs index c8be440..3a34173 100644 --- a/shalom/src/widgets/media_player.rs +++ b/shalom/src/widgets/media_player.rs @@ -5,18 +5,18 @@ use std::{ use iced::{ advanced::graphics::core::Element, - theme::{Slider, Svg, Text}, + theme::{Container, Slider, Svg, Text}, widget::{ column as icolumn, component, container, image::Handle, row, slider, svg, text, Component, }, - Alignment, Color, Length, Renderer, Theme, + Alignment, Background, Color, Length, Renderer, Theme, }; use crate::{ hass_client::MediaPlayerRepeat, oracle::{MediaPlayerSpeaker, MediaPlayerSpeakerState}, theme::{ - colours::{SKY_500, SLATE_400, SLATE_600}, + colours::{SKY_500, SLATE_400}, Icon, }, widgets::mouse_area::mouse_area, @@ -274,7 +274,8 @@ impl Component for MediaPlayer { .width(self.width) .center_x() .center_y() - // .style(Container::Custom(Box::new(Style::Inactive))) + .style(Container::Custom(Box::new(Style::Inactive))) + .padding(20) .into() } } @@ -376,19 +377,22 @@ pub enum Style { Inactive, } -// impl container::StyleSheet for Style { -// type Style = Theme; -// -// fn appearance(&self, style: &Self::Style) -> container::Appearance { -// container::Appearance { -// text_color: None, -// background: Some(Background::Color(SLATE_200)), -// border_radius: Default::default(), -// border_width: 0.0, -// border_color: Default::default(), -// } -// } -// } +impl container::StyleSheet for Style { + type Style = Theme; + + fn appearance(&self, _style: &Self::Style) -> container::Appearance { + container::Appearance { + text_color: None, + background: Some(Background::Color(Color { + a: 0.8, + ..Color::BLACK + })), + border_radius: 10.0.into(), + border_width: 0., + border_color: Color::default(), + } + } +} impl svg::StyleSheet for Style { type Style = Theme; @@ -396,7 +400,7 @@ impl svg::StyleSheet for Style { fn appearance(&self, _style: &Self::Style) -> svg::Appearance { let color = match self { Self::Active => SKY_500, - Self::Inactive => SLATE_600, + Self::Inactive => Color::WHITE, }; svg::Appearance { color: Some(color) } diff --git a/shalom/src/widgets/mod.rs b/shalom/src/widgets/mod.rs index 16108ee..e04b2f8 100644 --- a/shalom/src/widgets/mod.rs +++ b/shalom/src/widgets/mod.rs @@ -2,8 +2,10 @@ pub mod cards; pub mod colour_picker; pub mod context_menu; pub mod forced_rounded; +pub mod image_background; pub mod image_card; pub mod media_player; pub mod mouse_area; +pub mod room_navigation; pub mod toggle_card; pub mod track_card; diff --git a/shalom/src/widgets/room_navigation.rs b/shalom/src/widgets/room_navigation.rs new file mode 100644 index 0000000..d71dfba --- /dev/null +++ b/shalom/src/widgets/room_navigation.rs @@ -0,0 +1,214 @@ +use iced::{ + advanced::graphics::core::Element, + alignment::Vertical, + font::{Stretch, Weight}, + theme, + widget::{column, component, container, horizontal_rule, rule, svg, text, Component}, + Alignment, Background, Color, ContentFit, Font, Length, Renderer, Theme, +}; + +use super::mouse_area::mouse_area; +use crate::theme::{ + colours::{SKY_500, SLATE_200}, + Icon, +}; + +pub struct RoomNavigation { + _phantom: std::marker::PhantomData, + width: Length, + current: Page, + on_change: Option M>, + on_exit: Option, +} + +impl RoomNavigation { + pub fn new(current: Page) -> Self { + Self { + _phantom: std::marker::PhantomData, + width: Length::Fill, + current, + on_change: None, + on_exit: None, + } + } + + pub fn width(mut self, width: Length) -> Self { + self.width = width; + self + } + + pub fn on_change(mut self, on_change: fn(Page) -> M) -> Self { + self.on_change = Some(on_change); + self + } + + pub fn on_exit(mut self, event: M) -> Self { + self.on_exit = Some(event); + self + } +} + +impl Component for RoomNavigation { + type State = (); + type Event = Event; + + fn update(&mut self, _state: &mut Self::State, event: Self::Event) -> Option { + match event { + Event::Change(page) => self.on_change.map(|v| v(page)), + Event::Exit => self.on_exit.clone(), + } + } + + fn view(&self, _state: &Self::State) -> Element<'_, Self::Event, Renderer> { + let section = |icon: Icon, t: &'static str, state: Style, page| { + mouse_area( + container( + column![ + svg(icon) + .height(Length::Fixed(64.)) + .width(Length::Fixed(64.)) + .style(theme::Svg::Custom(Box::new(state))), + text(t).size(18.).font(Font { + weight: Weight::Bold, + stretch: Stretch::Condensed, + ..Font::with_name("Helvetica Neue") + }), + ] + .width(Length::Fill) + .align_items(Alignment::Center) + .padding(12.), + ) + .style(theme::Container::Custom(Box::new(state))) + .width(Length::Fill), + ) + .on_press(Event::Change(page)) + }; + + let s = |p: &[Page]| { + if p.contains(&self.current) { + Style::Active + } else { + Style::Inactive + } + }; + + let exit = container( + mouse_area( + svg(Icon::Back) + .height(32) + .width(32) + .content_fit(ContentFit::None), + ) + .on_press(Event::Exit), + ) + .height(Length::Fill) + .width(Length::Fill) + .align_y(Vertical::Bottom) + .padding(40); + + column![ + section(Icon::Speaker, "Listen", s(&[Page::Listen]), Page::Listen), + horizontal_rule(1).style(theme::Rule::Custom(Box::new(s(&[ + Page::Listen, + Page::Climate + ])))), + section(Icon::Hvac, "Climate", s(&[Page::Climate]), Page::Climate), + horizontal_rule(1).style(theme::Rule::Custom(Box::new(s(&[ + Page::Climate, + Page::Lights + ])))), + section(Icon::Bulb, "Lights", s(&[Page::Lights]), Page::Lights), + exit, + ] + .width(self.width) + .height(Length::Fill) + .into() + } +} + +#[derive(Copy, Clone)] +pub enum Event { + Change(Page), + Exit, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum Page { + Listen, + Climate, + Lights, +} + +impl<'a, M> From> for Element<'a, M, Renderer> +where + M: 'a + Clone, +{ + fn from(card: RoomNavigation) -> Self { + component(card) + } +} + +#[derive(Copy, Clone)] +pub enum Style { + Active, + Inactive, +} + +impl container::StyleSheet for Style { + type Style = Theme; + + fn appearance(&self, _style: &Self::Style) -> container::Appearance { + match self { + Self::Active => container::Appearance { + text_color: Some(Color::WHITE), + background: Some(Background::Color(SKY_500)), + border_radius: 0.0.into(), + border_width: 0.0, + border_color: Color::default(), + }, + Self::Inactive => container::Appearance { + text_color: Some(Color::BLACK), + background: Some(Background::Color(Color::WHITE)), + border_radius: 0.0.into(), + border_width: 0.0, + border_color: Color::default(), + }, + } + } +} + +impl svg::StyleSheet for Style { + type Style = Theme; + + fn appearance(&self, _style: &Self::Style) -> svg::Appearance { + match self { + Self::Active => svg::Appearance { + color: Some(Color::WHITE), + }, + Self::Inactive => svg::Appearance { + color: Some(Color::BLACK), + }, + } + } +} + +impl rule::StyleSheet for Style { + type Style = Theme; + + fn appearance(&self, _style: &Self::Style) -> rule::Appearance { + match self { + Self::Active => rule::Appearance { + color: Color::WHITE, + width: 1, + radius: 0.0.into(), + fill_mode: rule::FillMode::Full, + }, + Self::Inactive => rule::Appearance { + color: SLATE_200, + width: 1, + radius: 0.0.into(), + fill_mode: rule::FillMode::Full, + }, + } + } +} diff --git a/shalom/src/widgets/track_card.rs b/shalom/src/widgets/track_card.rs index fcda827..d186b97 100644 --- a/shalom/src/widgets/track_card.rs +++ b/shalom/src/widgets/track_card.rs @@ -6,10 +6,10 @@ use iced::{ image::{self, Image}, row, text, vertical_space, Component, }, - Alignment, Background, Renderer, Theme, + Alignment, Background, Color, Renderer, Theme, }; -use crate::theme::colours::SLATE_400; +use crate::theme::colours::{SLATE_200, SLATE_400}; pub fn track_card(artist: String, song: String, image: Option) -> TrackCard { TrackCard { @@ -40,7 +40,7 @@ impl Component for TrackCard { } else { Element::from(container(vertical_space(0)).width(64).height(64).style( |_t: &Theme| container::Appearance { - background: Some(Background::Color(SLATE_400)), + background: Some(Background::Color(SLATE_200)), ..container::Appearance::default() }, )) @@ -49,7 +49,7 @@ impl Component for TrackCard { row![ image, icolumn![ - text(&self.song).size(14), + text(&self.song).size(14).style(Text::Color(Color::WHITE)), text(&self.artist).style(Text::Color(SLATE_400)).size(14) ] ] -- libgit2 1.7.2