1use crate::input::key::Key;
2use crate::input::InputEvent;
3use std::sync::atomic::{AtomicBool, Ordering};
4use std::sync::Arc;
5use std::time::Duration;
6use tokio::select;
7use tokio::time::{interval, Interval};
8
9pub struct Events {
12 rx: tokio::sync::mpsc::Receiver<InputEvent>,
13 _tx: tokio::sync::mpsc::Sender<InputEvent>,
15 stop_capture: Arc<AtomicBool>,
17 interval: Interval,
19}
20
21impl Events {
22 pub fn new(render_rate: Duration) -> Events {
24 let (tx, rx) = tokio::sync::mpsc::channel(100);
25 let stop_capture = Arc::new(AtomicBool::new(false));
26
27 let event_tx = tx.clone();
28 let event_stop_capture = stop_capture.clone();
29 tokio::spawn(async move {
30 loop {
31 if crossterm::event::poll(render_rate).unwrap() {
33 if let crossterm::event::Event::Key(key) = crossterm::event::read().unwrap() {
34 let key = Key::from(key);
35 if let Err(err) = event_tx.send(InputEvent::Input(key)).await {
36 log::error!("Oops (event)!, {}", err);
37 }
38 }
39 }
40 if event_stop_capture.load(Ordering::Relaxed) {
41 break;
42 }
43 }
44 });
45
46 Events {
47 rx,
48 _tx: tx,
49 stop_capture,
50 interval: interval(render_rate),
51 }
52 }
53
54 pub async fn next(&mut self) -> InputEvent {
56 select! {
57 msg = self.rx.recv() => msg.unwrap_or(InputEvent::Quit),
58 _ = self.interval.tick() => InputEvent::Render,
59 }
60 }
61}
62
63impl Drop for Events {
64 fn drop(&mut self) {
65 self.stop_capture.store(true, Ordering::Relaxed)
66 }
67}