use crossterm::event; use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind}; use ratatui::{DefaultTerminal, Frame}; use ratatui::style::Stylize; use ratatui::widgets::{Block, Paragraph}; use ratatui::text::Line; #[derive(Debug, Default)] pub struct App { running: bool, } impl App { pub fn new() -> Self { Self::default() } pub fn run(mut self, mut terminal: DefaultTerminal) -> color_eyre::Result<()> { self.running = true; while self.running { terminal.draw(|frame| self.render(frame))?; self.handle_input_events()?; } Ok(()) } fn render(&mut self, frame: &mut Frame) { let title = Line::from("Gal Time Tracker") .bold() .blue() .centered(); let text = "Press `q` to stop running."; frame.render_widget( Paragraph::new(text) .block(Block::bordered().title(title)) .centered(), frame.area(), ) } fn handle_input_events(&mut self) -> color_eyre::Result<()> { match event::read()? { // it's important to check KeyEventKind::Press to avoid handling key release events Event::Key(key) if key.kind == KeyEventKind::Press => self.on_key_event(key), Event::Mouse(_) => {} Event::Resize(_, _) => {} _ => {} } Ok(()) } fn on_key_event(&mut self, key: KeyEvent) { match (key.modifiers, key.code) { (_, KeyCode::Char('q')) => self.quit(), _ => {} } } fn quit(&mut self) { self.running = false; } }