use crossterm::event::{Event, self, KeyCode}; use ratatui::widgets::ListState; use crate::uis::history::HistoryState; use crate::uis::new_transaction::NewTransactionTabState; use crate::uis::navigation_frame::NavigationState; pub type AppResult = std::result::Result>; pub struct StatefulList { pub state: ListState, pub items: Vec, } impl StatefulList { pub fn with_items(items: Vec) -> StatefulList { StatefulList { state: ListState::default(), items, } } pub fn next(&mut self) { let i = match self.state.selected() { Some(i) => { if i >= self.items.len() - 1 { 0 } else { i + 1 } } None => 0, }; self.state.select(Some(i)); } pub fn previous(&mut self) { let i = match self.state.selected() { Some(i) => { if i == 0 { self.items.len() - 1 } else { i - 1 } } None => 0, }; self.state.select(Some(i)); } pub fn unselect(&mut self) { self.state.select(None); } } pub enum InputMode { Insert, Normal, } pub struct App<'a> { pub running: bool, pub states: States<'a>, pub input_mode: InputMode, } impl<'a> App<'a> { pub fn new() -> App<'a> { App { running: true, states: States::new(), input_mode: InputMode::Normal, } } 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; } } } 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 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, } } }