Skip to main content

pr_bro/tui/
event.rs

1use crossterm::event::{KeyEvent, KeyEventKind};
2use futures::StreamExt;
3use tokio::sync::mpsc;
4
5#[derive(Debug, Clone)]
6pub enum Event {
7    Key(KeyEvent),
8    Tick,
9    Refresh, // Auto-refresh timer fired
10}
11
12pub struct EventHandler {
13    rx: mpsc::UnboundedReceiver<Event>,
14}
15
16impl EventHandler {
17    pub fn new(tick_rate_ms: u64, refresh_interval_secs: u64) -> Self {
18        let (tx, rx) = mpsc::unbounded_channel();
19
20        tokio::spawn(async move {
21            let mut reader = crossterm::event::EventStream::new();
22            let mut tick_interval =
23                tokio::time::interval(std::time::Duration::from_millis(tick_rate_ms));
24            let mut refresh_interval =
25                tokio::time::interval(std::time::Duration::from_secs(refresh_interval_secs));
26
27            // Skip the first tick of refresh interval (it fires immediately)
28            refresh_interval.tick().await;
29
30            loop {
31                tokio::select! {
32                    maybe_event = reader.next() => {
33                        if let Some(Ok(crossterm::event::Event::Key(key))) = maybe_event {
34                            // Filter for Press only (Windows compatibility)
35                            if key.kind == KeyEventKind::Press && tx.send(Event::Key(key)).is_err() {
36                                break;
37                            }
38                        }
39                    }
40                    _ = tick_interval.tick() => {
41                        if tx.send(Event::Tick).is_err() {
42                            break;
43                        }
44                    }
45                    _ = refresh_interval.tick() => {
46                        if tx.send(Event::Refresh).is_err() {
47                            break;
48                        }
49                    }
50                }
51            }
52        });
53
54        EventHandler { rx }
55    }
56
57    pub async fn next(&mut self) -> Event {
58        self.rx.recv().await.unwrap_or(Event::Tick)
59    }
60}