Skip to main content

rgx/
event.rs

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