rush_sync_server/input/
event.rs

1use 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        // Shutdown-Kanal für Input-Task
23        let (input_shutdown_tx, mut input_shutdown_rx) = mpsc::channel(1);
24        shutdown_tx.push(input_shutdown_tx);
25
26        // Input-Handler Task
27        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        // Tick-Handler Task
59        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); // Verwende den übergebenen tick_rate Parameter
65            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}