use std::sync::Arc; use crossterm::event::{self, Event, KeyCode}; use tokio; use log::warn; use crate::db::data_cache::DataCache; use crate::db::DB; use crate::uis::history::HistoryState; use crate::uis::navigation_frame::NavigationState; use crate::uis::new_transaction::NewTransactionTabState; pub type AppResult = std::result::Result>; pub enum InputMode { Insert, Normal, } pub struct App<'a> { pub running: bool, pub states: States<'a>, pub input_mode: InputMode, pub db: Arc>, pub data_cache: DataCache, } impl<'a> App<'a> { pub fn new(db: DB, data_cache: DataCache) -> App<'a> { App { running: true, states: States::new(), input_mode: InputMode::Normal, db: Arc::new(tokio::sync::Mutex::new(db)), data_cache, } } pub fn poll_events(&mut self) -> AppResult<()> { if let Event::Key(key) = event::read()? { // 'q' needs to be handled at the top level so it can't be // accidentally handed to a dead end if let KeyCode::Char('q') = key.code { if let Some(_) = self.states.nav_state.message.clone() { self.states.nav_state.message = None; } else { if let ActiveFrame::Navigation = self.states.active_frame { self.running = false; } else { self.states.active_frame = ActiveFrame::Navigation; } } } else if let KeyCode::Esc = key.code { if let Some(_) = self.states.nav_state.message.clone() { self.states.nav_state.message = None; } else { if let ActiveFrame::Navigation = self.states.active_frame { self.running = false; } else { self.states.active_frame = ActiveFrame::Navigation; } } } if let KeyCode::Char('r') = key.code { self.refresh(); } match self.states.active_frame { ActiveFrame::Navigation => { NavigationState::handle_event(key, self); } ActiveFrame::History => { HistoryState::handle_event(key, self); } ActiveFrame::NewTransaction => { NewTransactionTabState::handle_event(key, self); } } } return Ok(()); } pub fn refresh(&mut self) { let fut = Arc::clone(&self.db); tokio::spawn(async move { let res = fut.lock().await.get_all_records().await; match res { Ok(_) => {} Err(e) => warn!("{}", e), } }); } } pub enum ActiveFrame { Navigation, NewTransaction, History, } pub struct States<'a> { pub nav_state: NavigationState<'a>, pub transactions: NewTransactionTabState<'a>, pub history: HistoryState, pub active_frame: ActiveFrame, } impl<'a> States<'a> { pub fn new() -> States<'a> { States { nav_state: NavigationState::new(), transactions: NewTransactionTabState::new(), history: HistoryState::new(), active_frame: ActiveFrame::Navigation, } } }