pub mod components; pub mod screens; use diesel::SqliteConnection; use iced::Element; use schist_models::{account::Account, bucket::Bucket}; use schist_queries::{accounts::get_all_accounts, buckets::get_all_buckets}; use crate::{ config::Config, gui::screens::{main_screen, MainScreen, Screen}, shortcut::KeyBind, traits::{Component, Viewable}, }; #[derive(Clone, Debug)] pub enum Message { Event(iced::Event), MainScreenMessage(main_screen::Message), RefetchedAccounts(FetchResult>), RefetchedBuckets(FetchResult>), } pub type FetchResult = std::result::Result; #[derive(Clone, Debug)] pub struct FetchError { pub message: String, } impl FetchError { pub fn new(err: anyhow::Error) -> Self { Self { message: format!("{}", err), } } } pub struct Gui { active_screen: Screen, buckets: Vec, main_screen: MainScreen, config: Config, } impl Gui { pub fn new(connection: &mut SqliteConnection) -> (Self, iced::Task) { let buckets = Vec::new(); let accounts = Vec::new(); let mut gui = Self { active_screen: Screen::Main, buckets: buckets.clone(), main_screen: MainScreen::new(buckets, accounts), config: Config::default(), }; let buckets = get_all_buckets(connection).map_err(FetchError::new); let accounts = get_all_accounts(connection).map_err(FetchError::new); let tasks = iced::Task::batch(vec![ gui.update(Message::RefetchedBuckets(buckets)), gui.update(Message::RefetchedAccounts(accounts)), ]); (gui, tasks) } } impl Gui { pub fn view<'a>(&'a self) -> Element<'a, Message> { match self.active_screen { Screen::Main => self.main_screen.view().map(Message::MainScreenMessage), } } pub fn update(&mut self, message: Message) -> iced::Task { match message { Message::Event(iced::Event::Keyboard(iced::keyboard::Event::KeyPressed { key, modifiers, .. })) => { let key_bind = KeyBind::from((key.clone(), modifiers)); if let Some(command) = self .config .keyboard .shortcuts() .iter() .find_map(|shortcut| shortcut.execute(&key_bind)) { match command { crate::shortcut::Command::GotoNextView => { self.main_screen.update(main_screen::Message::SelectView( self.main_screen.active_view.next(), )); iced::Task::none() } crate::shortcut::Command::GotoPrevView => { self.main_screen.update(main_screen::Message::SelectView( self.main_screen.active_view.prev(), )); iced::Task::none() } crate::shortcut::Command::GotoView(view) => { self.main_screen .update(main_screen::Message::SelectView(view)); iced::Task::none() } crate::shortcut::Command::GotoNextItem => { self.main_screen.update(main_screen::Message::NextItem); iced::Task::none() } crate::shortcut::Command::GotoPrevItem => { self.main_screen.update(main_screen::Message::PrevItem); iced::Task::none() } } } else { iced::Task::none() } } Message::Event(_) => iced::Task::none(), Message::MainScreenMessage(message) => match self.main_screen.update(message) { main_screen::Action::None => iced::Task::none(), }, Message::RefetchedBuckets(buckets) => { match buckets { Ok(buckets) => { self.buckets = buckets.clone(); self.main_screen .update(main_screen::Message::SetBuckets(buckets)); } Err(err) => println!("Failed to get buckets: {:?}", err.message), }; iced::Task::none() } Message::RefetchedAccounts(accounts) => { match accounts { Ok(accounts) => { self.main_screen .update(main_screen::Message::SetAccounts(accounts)); } Err(err) => println!("Failed to get accounts: {:?}", err.message), } iced::Task::none() } } } } pub fn subscription(_state: &Gui) -> iced::Subscription { iced::event::listen().map(Message::Event) }