rush_sync_server/input/
event.rs1use crossterm::event::{self as crossterm_event, Event as CrosstermEvent, KeyEvent};
2use tokio::sync::mpsc::{self, Sender};
3use tokio::time::{interval, Duration};
4
5#[derive(Debug)]
6pub enum AppEvent {
7 Input(KeyEvent),
8 Tick,
9 Resize(u16, u16),
10}
11
12pub struct EventHandler {
13 rx: mpsc::Receiver<AppEvent>,
14 shutdown_tx: Vec<Sender<()>>,
15}
16
17impl EventHandler {
18 pub fn new(tick_rate: Duration) -> Self {
19 let (tx, rx) = mpsc::channel(100);
20 let mut shutdown_tx = Vec::new();
21
22 let (input_shutdown_tx, mut input_shutdown_rx) = mpsc::channel(1);
24 shutdown_tx.push(input_shutdown_tx);
25
26 let input_tx = tx.clone();
28 tokio::spawn(async move {
29 let mut last_event_time = tokio::time::Instant::now();
30 let min_event_interval = Duration::from_millis(33);
31
32 loop {
33 tokio::select! {
34 _ = input_shutdown_rx.recv() => break,
35 _ = async {
36 if crossterm_event::poll(Duration::from_millis(99)).unwrap() {
37 let now = tokio::time::Instant::now();
38 if now.duration_since(last_event_time) >= min_event_interval {
39 if let Ok(event) = crossterm_event::read() {
40 match event {
41 CrosstermEvent::Key(key) => {
42 let _ = input_tx.send(AppEvent::Input(key)).await;
43 }
44 CrosstermEvent::Resize(width, height) => {
45 let _ = input_tx.send(AppEvent::Resize(width, height)).await;
46 }
47 _ => {}
48 }
49 last_event_time = now;
50 }
51 }
52 }
53 } => {}
54 }
55 }
56 });
57
58 let (tick_shutdown_tx, mut tick_shutdown_rx) = mpsc::channel(1);
60 shutdown_tx.push(tick_shutdown_tx);
61
62 let tick_tx = tx;
63 tokio::spawn(async move {
64 let mut interval = interval(tick_rate); loop {
66 tokio::select! {
67 _ = tick_shutdown_rx.recv() => break,
68 _ = interval.tick() => {
69 let _ = tick_tx.send(AppEvent::Tick).await;
70 }
71 }
72 }
73 });
74
75 EventHandler { rx, shutdown_tx }
76 }
77
78 pub async fn next(&mut self) -> Option<AppEvent> {
79 self.rx.recv().await
80 }
81
82 pub async fn shutdown(&mut self) {
83 for tx in self.shutdown_tx.iter() {
84 let _ = tx.send(()).await;
85 }
86 }
87}