pub mod components; pub mod screens; use diesel::SqliteConnection; use iced::Element; use schist_models::{Account, Bucket}; use schist_queries::{accounts::get_all_accounts, buckets::get_all_buckets}; use crate::{ config::Config, gui::screens::{files_screen, main_screen, FilesScreen, MainScreen, Screen}, paths::get_file_paths, shortcut::KeyBind, traits::{Component, Viewable}, }; #[derive(Clone, Debug)] pub enum Message { Event(iced::Event), FilesScreenMessage(files_screen::Message), 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, connection: Option, files_screen: FilesScreen, main_screen: MainScreen, config: Config, } impl Gui { pub fn new() -> (Self, iced::Task) { let file_paths = get_file_paths(); let gui = Self { active_screen: Screen::FilesScreen, connection: None, files_screen: FilesScreen::new(&file_paths), main_screen: MainScreen::new(), config: Config::default(), }; (gui, iced::Task::none()) } } impl Gui { pub fn view<'a>(&'a self) -> Element<'a, Message> { match self.active_screen { Screen::FilesScreen => self.files_screen.view().map(Message::FilesScreenMessage), Screen::MainScreen => 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.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() } Message::FilesScreenMessage(message) => match self.files_screen.update(message) { files_screen::Action::None => iced::Task::none(), files_screen::Action::OpenedFile(sqlite_connection) => { let mut connection = sqlite_connection.connection; let buckets = get_all_buckets(&mut connection).map_err(FetchError::new); let accounts = get_all_accounts(&mut connection).map_err(FetchError::new); self.connection = Some(connection); self.active_screen = Screen::MainScreen; iced::Task::batch(vec![ self.update(Message::RefetchedBuckets(buckets)), self.update(Message::RefetchedAccounts(accounts)), ]) } }, } } } pub fn subscription(_state: &Gui) -> iced::Subscription { iced::event::listen().map(Message::Event) }