use anyhow::Result;
use crossterm::event::{self, Event as TermEvent, KeyEvent, MouseEvent};
use std::time::Duration;
use tokio::sync::mpsc;
#[derive(Debug)]
pub enum Event {
Key(KeyEvent),
Mouse(MouseEvent),
Resize(u16, u16),
Tick,
Data {
screen: &'static str,
payload: String,
},
ApiError {
screen: &'static str,
message: String,
},
LogLine(String),
}
pub struct EventHandler {
rx: mpsc::UnboundedReceiver<Event>,
_tx: mpsc::UnboundedSender<Event>,
}
impl EventHandler {
pub fn new(tick_rate: Duration) -> Self {
let (tx, rx) = mpsc::unbounded_channel();
let event_tx = tx.clone();
tokio::spawn(async move {
loop {
let has_event = event::poll(tick_rate).unwrap_or(false);
if has_event {
match event::read() {
Ok(TermEvent::Key(key)) => {
if event_tx.send(Event::Key(key)).is_err() {
return;
}
}
Ok(TermEvent::Mouse(mouse)) => {
if event_tx.send(Event::Mouse(mouse)).is_err() {
return;
}
}
Ok(TermEvent::Resize(w, h)) => {
if event_tx.send(Event::Resize(w, h)).is_err() {
return;
}
}
_ => {}
}
} else {
if event_tx.send(Event::Tick).is_err() {
return;
}
}
}
});
Self { rx, _tx: tx }
}
pub fn sender(&self) -> mpsc::UnboundedSender<Event> {
self._tx.clone()
}
pub async fn next(&mut self) -> Result<Event> {
self.rx.recv().await.ok_or_else(|| anyhow::anyhow!("event channel closed"))
}
}