1use crossterm::event::{Event as CrosstermEvent, KeyEvent};
2use futures::{FutureExt, StreamExt};
3use tokio::sync::mpsc;
4
5use crate::app::AppResult;
6
7#[derive(Clone, Copy, Debug)]
9pub enum Event {
10 Tick,
12 Key(KeyEvent),
14 Resize(u16, u16),
16}
17
18#[allow(dead_code)]
20#[derive(Debug)]
21pub struct EventHandler {
22 pub sender: mpsc::UnboundedSender<Event>,
24 receiver: mpsc::UnboundedReceiver<Event>,
26 handler: tokio::task::JoinHandle<()>,
28}
29
30impl EventHandler {
31 pub fn new() -> Self {
33 let (sender, receiver) = mpsc::unbounded_channel();
34 let _sender = sender.clone();
35 let handler = tokio::spawn(async move {
36 let mut reader = crossterm::event::EventStream::new();
37 loop {
38 let crossterm_event = reader.next().fuse();
39
40 tokio::select! {
41 _ = _sender.closed() => {
42 break;
43 }
44 Some(Ok(evt)) = crossterm_event => {
45 match evt {
46 CrosstermEvent::Key(key) => {
47 if key.kind == crossterm::event::KeyEventKind::Press {
48 _sender.send(Event::Key(key)).unwrap();
49 }
50 },
51 CrosstermEvent::Resize(x, y) => {
52 _sender.send(Event::Resize(x, y)).unwrap();
53 },
54 _ => {},
55 }
56 }
57 };
58 }
59 });
60 Self {
61 sender,
62 receiver,
63 handler,
64 }
65 }
66
67 pub async fn next(&mut self) -> AppResult<Event> {
72 self.receiver
73 .recv()
74 .await
75 .ok_or(Box::new(std::io::Error::new(
76 std::io::ErrorKind::Other,
77 "This is an IO error",
78 )))
79 }
80}