use crate::action::Action;
use crossterm::event::{self, Event};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;
use tokio::sync::mpsc;
pub struct EventHandler {
rx: mpsc::UnboundedReceiver<Action>,
stop: Arc<AtomicBool>,
}
impl EventHandler {
pub fn new() -> (Self, mpsc::UnboundedSender<Action>) {
let (tx, rx) = mpsc::unbounded_channel();
let event_tx = tx.clone();
let stop = Arc::new(AtomicBool::new(false));
let stop_clone = stop.clone();
std::thread::spawn(move || {
while !stop_clone.load(Ordering::Relaxed) {
if event::poll(Duration::from_millis(50)).unwrap_or(false)
&& let Ok(evt) = event::read()
{
let action = match evt {
Event::Key(key)
if key.kind == crossterm::event::KeyEventKind::Press =>
{
Some(Action::RawKey(key))
}
Event::Resize(w, h) => Some(Action::Resize(w, h)),
Event::Mouse(m) => Some(Action::Mouse(m)),
_ => None,
};
if let Some(action) = action
&& event_tx.send(action).is_err()
{
break;
}
}
}
});
(Self { rx, stop }, tx)
}
pub async fn next(&mut self) -> Option<Action> {
self.rx.recv().await
}
}
impl Drop for EventHandler {
fn drop(&mut self) {
self.stop.store(true, Ordering::Relaxed);
}
}