Skip to main content

rgx/
event.rs

1use crossterm::event::{Event, EventStream, KeyEvent};
2use std::time::Duration;
3use tokio::sync::mpsc;
4use tokio_stream::StreamExt;
5
6#[derive(Debug)]
7pub enum AppEvent {
8    Key(KeyEvent),
9    Tick,
10    Resize(u16, u16),
11}
12
13pub struct EventHandler {
14    rx: mpsc::UnboundedReceiver<AppEvent>,
15    _task: tokio::task::JoinHandle<()>,
16}
17
18impl EventHandler {
19    pub fn new(tick_rate: Duration) -> Self {
20        let (tx, rx) = mpsc::unbounded_channel();
21
22        let task = tokio::spawn(async move {
23            let mut reader = EventStream::new();
24            let mut tick_interval = tokio::time::interval(tick_rate);
25
26            loop {
27                tokio::select! {
28                    _ = tick_interval.tick() => {
29                        if tx.send(AppEvent::Tick).is_err() {
30                            break;
31                        }
32                    }
33                    event = reader.next() => {
34                        match event {
35                            Some(Ok(Event::Key(key))) => {
36                                if tx.send(AppEvent::Key(key)).is_err() {
37                                    break;
38                                }
39                            }
40                            Some(Ok(Event::Resize(w, h))) => {
41                                if tx.send(AppEvent::Resize(w, h)).is_err() {
42                                    break;
43                                }
44                            }
45                            Some(Err(_)) | None => break,
46                            _ => {}
47                        }
48                    }
49                }
50            }
51        });
52
53        Self { rx, _task: task }
54    }
55
56    pub async fn next(&mut self) -> Option<AppEvent> {
57        self.rx.recv().await
58    }
59}