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}