1use crossterm::event;
2use crossterm::event::Event as CrosstermEvent;
3use ratatui::prelude::CrosstermBackend;
4use std::sync::mpsc::Receiver;
5use std::time::Duration;
6
7#[derive(Clone, Debug)]
8pub enum Event {
9 Parent(CrosstermEvent),
10 AsyncUpdate,
11}
12
13pub struct Tui<'a> {
14 terminal: &'a mut ratatui::Terminal<CrosstermBackend<std::io::Stdout>>,
15 async_update_rx: Receiver<()>,
16}
17
18impl<'a> Tui<'a> {
19 pub fn new(
20 terminal: &'a mut ratatui::Terminal<CrosstermBackend<std::io::Stdout>>,
21 async_update_rx: Receiver<()>,
22 ) -> Self {
23 Self {
24 terminal,
25 async_update_rx,
26 }
27 }
28
29 pub fn draw(&mut self, f: impl FnOnce(&mut ratatui::Frame<'_>)) -> std::io::Result<()> {
30 self.terminal.draw(f)?;
31 Ok(())
32 }
33
34 pub fn read_event(&mut self) -> anyhow::Result<Event> {
35 loop {
36 if event::poll(Duration::from_micros(100))? {
37 return Ok(event::read().map(Event::Parent)?);
38 } else if self.async_update_rx.try_recv().is_ok() {
39 return Ok(Event::AsyncUpdate);
40 }
41 }
42 }
43}