rust_kanban/inputs/
events.rs1use crate::inputs::{key::Key, mouse::Mouse, InputEvent};
2use log::error;
3use portable_atomic::{AtomicBool, Ordering};
4use std::{sync::Arc, time::Duration};
5
6pub struct Events {
7 rx: tokio::sync::mpsc::Receiver<InputEvent>,
8 _tx: tokio::sync::mpsc::Sender<InputEvent>,
9 stop_capture: Arc<AtomicBool>,
10}
11
12impl Events {
13 pub fn new(tick_rate: Duration) -> Events {
14 let (tx, rx) = tokio::sync::mpsc::channel(100);
15 let stop_capture = Arc::new(AtomicBool::new(false));
16
17 let event_tx = tx.clone();
18 let event_stop_capture = stop_capture.clone();
19 tokio::spawn(async move {
20 loop {
21 if crossterm::event::poll(tick_rate).unwrap() {
22 let event = crossterm::event::read().unwrap();
23 if let crossterm::event::Event::Mouse(mouse_action) = event {
24 let mouse_action = Mouse::from(mouse_action);
25 if let Err(err) = event_tx.send(InputEvent::MouseAction(mouse_action)).await
26 {
27 error!("Oops!, {}", err);
28 }
29 } else if let crossterm::event::Event::Key(key) = event {
30 let key = Key::from(key);
31 if let Err(err) = event_tx.send(InputEvent::KeyBoardInput(key)).await {
32 error!("Oops!, {}", err);
33 }
34 }
35 }
36 if let Err(err) = event_tx.send(InputEvent::Tick).await {
37 error!("Oops!, {}", err);
38 }
39 if event_stop_capture.load(Ordering::Relaxed) {
40 break;
41 }
42 }
43 });
44
45 Events {
46 rx,
47 _tx: tx,
48 stop_capture,
49 }
50 }
51
52 pub async fn next(&mut self) -> InputEvent {
53 let new_event = self.rx.recv().await.unwrap_or(InputEvent::Tick);
54 if (new_event == InputEvent::KeyBoardInput(Key::Unknown))
55 || (new_event == InputEvent::MouseAction(Mouse::Unknown))
56 {
57 InputEvent::Tick
58 } else {
59 new_event
60 }
61 }
62
63 pub fn close(&mut self) {
64 self.stop_capture.store(true, Ordering::Relaxed)
65 }
66}