use std::{
sync::mpsc::{channel, Receiver, Sender},
thread::{self, JoinHandle},
time::{Duration, Instant},
};
use anyhow::Result;
use super::key::Key;
pub enum InputEvent {
Input(Key),
Tick,
}
pub struct EventHandler {
receiver: Receiver<InputEvent>,
sender: Sender<InputEvent>,
handler: JoinHandle<()>,
}
impl EventHandler {
pub fn new(tick_rate: Duration) -> Self {
let (sender, receiver) = channel();
let handler = {
let sender = sender.clone();
thread::spawn(move || {
let mut last_tick = Instant::now();
loop {
let timeout = tick_rate
.checked_sub(last_tick.elapsed())
.unwrap_or(tick_rate);
if crossterm::event::poll(timeout).expect("No events available") {
if let crossterm::event::Event::Key(key) =
crossterm::event::read().expect("Undable to read event")
{
if key.kind == crossterm::event::KeyEventKind::Press {
let key = Key::from(key);
sender
.send(InputEvent::Input(key))
.expect("Failed to send terminal event");
}
}
}
if last_tick.elapsed() >= tick_rate {
sender
.send(InputEvent::Tick)
.expect("failed to send tick event");
last_tick = Instant::now();
}
}
})
};
EventHandler {
receiver,
sender,
handler,
}
}
pub fn next(&self) -> Result<InputEvent> {
Ok(self.receiver.recv()?)
}
}