use std::{collections::BTreeMap, sync::Arc}; use iced::{ futures::StreamExt, subscription, widget::Row, Element, Length, Renderer, Subscription, }; use crate::{ oracle::{Light, Oracle, Room}, theme::Icon, widgets::{self, colour_picker::colour_from_hsb}, }; #[derive(Debug)] pub struct Lights { lights: BTreeMap<&'static str, Light>, oracle: Arc, } impl Lights { pub fn new(oracle: Arc, room: &Room) -> Self { let lights = room.lights(&oracle); Self { lights, oracle } } pub fn update(&mut self, event: Message) -> Option { match event { Message::SetLightState(id, state) => { // give instant feedback before we get the event back from hass if let Some(light) = self.lights.get_mut(id) { light.on = Some(state); } Some(Event::SetLightState(id, state)) } Message::OpenLightOptions(id) => Some(Event::OpenLightContextMenu(id)), Message::UpdateLight(entity_id) => { if let Some(light) = self.oracle.fetch_light(entity_id) { self.lights.insert(entity_id, light); } None } } } pub fn view(&self) -> Element<'_, Message, Renderer> { let light = |id, light: &Light| { let mut toggle_card = widgets::toggle_card::toggle_card( &light.friendly_name, light.on.unwrap_or_default(), light.on.is_none(), ) .icon(if light.on.is_none() { Icon::Dead } else { Icon::Bulb }) .width(Length::Shrink) .active_icon_colour( light .hs_color .zip(light.brightness) .map(|((h, s), b)| colour_from_hsb(h, s, b / 255.)), ); if let Some(state) = light.on { toggle_card = toggle_card .on_press(Message::SetLightState(id, !state)) .on_long_press(Message::OpenLightOptions(id)); } toggle_card }; Row::with_children( self.lights .iter() .map(|(id, item)| light(*id, item)) .map(Element::from) .collect::>(), ) .spacing(10) .into() } pub fn subscription(&self) -> Subscription { Subscription::batch(self.lights.keys().copied().map(|key| { subscription::run_with_id( key, self.oracle .subscribe_id(key) .map(|()| Message::UpdateLight(key)), ) })) } } #[derive(Copy, Clone)] pub enum Event { OpenLightContextMenu(&'static str), SetLightState(&'static str, bool), } #[derive(Clone, Debug, Copy)] pub enum Message { SetLightState(&'static str, bool), UpdateLight(&'static str), OpenLightOptions(&'static str), }