use std::{
sync::Arc,
thread,
time::{
Duration,
Instant,
},
};
use crossterm::{
event,
event::Event,
};
use futures::{
channel::mpsc,
lock::Mutex,
prelude::*,
};
use crate::widget::{
input::InputBuffer,
scrollback::ScrollbackBuffer,
};
pub struct User {
_input_handle: thread::JoinHandle<()>,
events: mpsc::Receiver<Event>,
}
impl User {
pub fn new() -> Self {
let (mut tx, rx) = mpsc::channel(32);
let input_handle = {
thread::spawn(move || loop {
let event = match event::read() {
Ok(e) => e,
Err(err) => {
tracing::error!(?err, "error reading event from terminal");
continue;
}
};
tracing::trace!(?event, "got input event");
if let Err(err) = futures::executor::block_on(tx.send(event)) {
tracing::error!(?err, "error sending user event");
return;
}
})
};
Self {
_input_handle: input_handle,
events: rx,
}
}
pub fn dispatch_events(
mut self,
input_handle: Arc<Mutex<InputBuffer>>,
scrollback_handle: Arc<Mutex<ScrollbackBuffer>>,
mut render_ticks: impl Sink<Instant> + Unpin + Send + 'static,
) {
tokio::spawn(async move {
let mut last_resize = Instant::now();
let resize_limit = Duration::from_millis(100);
while let Some(event) = self.events.next().await {
if let Event::Resize(_, _) = event {
let now = Instant::now();
if now - last_resize > resize_limit {
last_resize = now;
let _ = render_ticks.send(Instant::now()).await;
}
continue;
}
if input_handle.lock().await.handle_user_event(&event).await {
let _ = render_ticks.send(Instant::now()).await;
continue;
}
if scrollback_handle
.lock()
.await
.handle_user_event(&event)
.await
{
let _ = render_ticks.send(Instant::now()).await;
continue;
}
}
});
}
}