use crate::config::types::ApplicationConfig; use crate::event::{AppEvent, EventHandler}; use crate::widgets::views::{AppView, MainView}; use crate::widgets::views::View; use color_eyre::Result; use crossterm::event::{Event}; use rat_cursor::HasScreenCursor; use ratatui::{DefaultTerminal, Frame}; use std::time::Duration; pub(crate) struct App { events: EventHandler, state: AppState, } struct AppState { view: Option, } impl App { pub async fn create() -> Result { let config = ApplicationConfig::get_config()?; let state = AppState { view: Some(AppView::MainView(MainView::new())), }; let app = Self { events: EventHandler::new(Duration::from_millis(config.basic_config.tick_rate)), state, }; Ok(app) } pub async fn run(mut self, terminal: &mut DefaultTerminal) -> Result<()> { loop { terminal.draw(|frame| self.draw(frame))?; let event = self.events.next().await?; self.update(event)?; if let Some(view) = self.state.view.as_mut() && let AppView::MainView(main_view) = view && !main_view.is_running() { break Ok(()); } } } fn update(&mut self, event: AppEvent) -> Result<()> { if let AppEvent::Raw(cross_event) = event { self.handle_event(&cross_event)?; } Ok(()) } fn handle_event(&mut self, key: &Event) -> Result<()> { if let Some(current_view) = self.state.view.as_mut() { match current_view { AppView::MainView(main_view) => { main_view.handle_input(key)? } } } Ok(()) } fn draw(&mut self, frame: &mut Frame) { if let Some(view) = self.state.view.as_mut() { match view { AppView::MainView(main_view) => { frame.render_stateful_widget( MainView::new(), frame.area(), &mut main_view.state, ); if let Some(pos) = main_view.screen_cursor() { frame.set_cursor_position(pos); } } } } } }