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