mudrs-milk 0.0.1

WIP Mud Client
Documentation
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;
                }
            }
        });
    }
}