use std::{any::TypeId, sync::Arc};
use iced::{
advanced::graphics::core::Element,
font::{Stretch, Weight},
futures::StreamExt,
subscription,
widget::{column, scrollable, text, Column, Row},
Font, Renderer, Subscription,
};
use itertools::Itertools;
use time::OffsetDateTime;
use crate::{
oracle::{Oracle, Weather},
theme::Image,
widgets::image_card,
};
#[derive(Debug)]
pub struct Omni {
oracle: Arc<Oracle>,
weather: Weather,
}
impl Omni {
pub fn new(oracle: Arc<Oracle>) -> Self {
Self {
weather: oracle.current_weather(),
oracle,
}
}
}
impl Omni {
#[allow(
clippy::unnecessary_wraps,
clippy::needless_pass_by_value,
clippy::unused_self
)]
pub fn update(&mut self, event: Message) -> Option<Event> {
match event {
Message::OpenRoom(room) => Some(Event::OpenRoom(room)),
Message::UpdateWeather => {
self.weather = self.oracle.current_weather();
None
}
}
}
pub fn view(&self) -> Element<'_, Message, Renderer> {
let greeting = match OffsetDateTime::now_utc().hour() {
5..=11 => "Good morning!",
12..=16 => "Good afternoon!",
17..=23 | 0..=4 => "Good evening!",
_ => "Hello!",
};
let greeting = text(greeting).size(60).font(Font {
weight: Weight::Bold,
stretch: Stretch::Condensed,
..Font::with_name("Helvetica Neue")
});
let room = |id, room, image| {
image_card::image_card(image, room).on_press(Message::OpenRoom(id))
};
let rooms = self
.oracle
.rooms()
.map(|(id, r)| room(id, r.name.as_ref(), determine_image(&r.name)))
.chunks(2)
.into_iter()
.map(|children| children.into_iter().fold(Row::new().spacing(10), Row::push))
.fold(Column::new().spacing(10), Column::push);
scrollable(
column![
greeting,
crate::widgets::cards::weather::WeatherCard::new(self.weather),
rooms,
]
.spacing(20)
.padding(40),
)
.into()
}
pub fn subscription(&self) -> Subscription<Message> {
pub struct WeatherSubscription;
subscription::run_with_id(
TypeId::of::<WeatherSubscription>(),
self.oracle
.subscribe_weather()
.map(|()| Message::UpdateWeather),
)
}
}
fn determine_image(name: &str) -> Image {
match name {
"Kitchen" => Image::Kitchen,
"Bathroom" => Image::Bathroom,
"Bedroom" => Image::Bedroom,
"Dining Room" => Image::DiningRoom,
_ => Image::LivingRoom,
}
}
#[derive(Default, Hash)]
pub struct State {}
#[derive(Clone, Debug)]
pub enum Event {
OpenRoom(&'static str),
}
#[derive(Clone, Debug)]
pub enum Message {
OpenRoom(&'static str),
UpdateWeather,
}