rust_kanban/inputs/
events.rs

1use 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}