55 lines
1.6 KiB
Rust
55 lines
1.6 KiB
Rust
use color_eyre::eyre::{eyre, Result};
|
|
use crossterm::event::EventStream;
|
|
use futures::FutureExt;
|
|
use futures::StreamExt;
|
|
use std::time::Duration;
|
|
use tokio::sync::mpsc::UnboundedSender;
|
|
use tokio::task::JoinHandle;
|
|
|
|
#[derive(Clone)]
|
|
pub(crate) enum AppEvent {
|
|
Error,
|
|
Tick,
|
|
Raw(crossterm::event::Event),
|
|
}
|
|
|
|
pub(crate) struct EventHandler {
|
|
_tx: UnboundedSender<AppEvent>,
|
|
rx: tokio::sync::mpsc::UnboundedReceiver<AppEvent>,
|
|
pub task: JoinHandle<()>,
|
|
}
|
|
|
|
impl EventHandler {
|
|
pub fn new(tick_rate: Duration) -> Self {
|
|
let mut interval = tokio::time::interval(tick_rate);
|
|
let mut event_reader = EventStream::new();
|
|
let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
|
|
|
|
let _tx = tx.clone();
|
|
|
|
let task = tokio::spawn(async move {
|
|
loop {
|
|
let delay = interval.tick();
|
|
let crossterm_event = event_reader.next().fuse();
|
|
tokio::select! {
|
|
maybe_event = crossterm_event => {
|
|
if let Some(Err(_)) = maybe_event {
|
|
tx.send(AppEvent::Error).unwrap()
|
|
} else if let Some(Ok(event)) = maybe_event {
|
|
tx.send(AppEvent::Raw(event)).unwrap();
|
|
}
|
|
}
|
|
_ = delay => {
|
|
tx.send(AppEvent::Tick).unwrap()
|
|
}
|
|
}
|
|
}
|
|
});
|
|
Self { _tx, rx, task }
|
|
}
|
|
|
|
pub(crate) async fn next(&mut self) -> Result<AppEvent> {
|
|
self.rx.recv().await.ok_or(eyre!("Unable to get event"))
|
|
}
|
|
}
|