1use crate::event::Key;
2use crossterm::event::{self, Event as CEvent};
3use std::{
4 sync::mpsc,
5 thread,
6 time::{Duration, Instant},
7};
8
9#[derive(Debug, Clone, Copy)]
10pub struct EventConfig {
11 pub exit_key: Key,
12 pub tick_rate: Duration,
13}
14
15impl Default for EventConfig {
16 fn default() -> EventConfig {
17 EventConfig {
18 exit_key: Key::Ctrl('c'),
19 tick_rate: Duration::from_millis(250),
20 }
21 }
22}
23
24pub enum Event<I> {
25 Input(I),
26 Tick,
27}
28
29pub struct Events {
30 rx: mpsc::Receiver<Event<Key>>,
31 _tx: mpsc::Sender<Event<Key>>,
32}
33
34impl Events {
35 pub fn new(tick_rate: u64) -> Self {
36 Events::with_config(EventConfig {
37 tick_rate: Duration::from_millis(tick_rate),
38 ..Default::default()
39 })
40 }
41
42 pub fn with_config(config: EventConfig) -> Events {
43 let (tx, rx) = mpsc::channel();
44 let event_tx = tx.clone();
45 let tick_rate = config.tick_rate;
46
47 thread::spawn(move || {
48 let mut last_tick = Instant::now();
49
50 loop {
51 let timeout = tick_rate
52 .checked_sub(last_tick.elapsed())
53 .unwrap_or_else(|| Duration::from_secs(0));
54
55 if event::poll(timeout).unwrap() {
56 if let CEvent::Key(key_event) = event::read().unwrap() {
57 let key = Key::from(key_event);
58 if event_tx.send(Event::Input(key)).is_err() {
59 break;
60 }
61 }
62 }
63
64 if last_tick.elapsed() >= tick_rate {
65 if event_tx.send(Event::Tick).is_err() {
66 break;
67 }
68 last_tick = Instant::now();
69 }
70 }
71 });
72
73 Events { rx, _tx: tx }
74 }
75
76 pub fn next(&self) -> Result<Event<Key>, mpsc::RecvError> {
77 self.rx.recv()
78 }
79}