intuitive 0.1.0

a react-like library for building text-based user interfaces
Documentation
use std::{
  sync::{
    mpsc::{self, Receiver, Sender},
    Arc,
  },
  thread,
};

use crossterm::event::{self as crossterm_event, Event as CrosstermEvent};
use lazy_static::lazy_static;
use parking_lot::Mutex;

use super::Event;
use crate::error::Result;

lazy_static! {
  static ref CHANNEL: Channel = Channel::new();
}

pub fn read() -> Result<Event> {
  Ok(CHANNEL.receiver.lock().recv()?)
}

pub fn send(event: Event) -> Result<()> {
  Ok(CHANNEL.sender.lock().send(event)?)
}

pub fn re_render() -> Result<()> {
  Ok(CHANNEL.sender.lock().send(Event::Render)?)
}

pub fn quit() {
  CHANNEL.sender.lock().send(Event::Quit).expect("quit")
}

pub fn start_crossterm_events() {
  let sender = CHANNEL.sender();

  thread::spawn(move || loop {
    let event = match crossterm_event::read().expect("read") {
      CrosstermEvent::Key(event) => Event::Key(event),
      CrosstermEvent::Resize(..) => Event::Render,

      _ => continue,
    };

    sender.send(event).expect("send");
  });
}

struct Channel {
  sender: Arc<Mutex<Sender<Event>>>,
  receiver: Arc<Mutex<Receiver<Event>>>,
}

impl Channel {
  pub fn new() -> Self {
    let (sender, receiver) = mpsc::channel();

    Self {
      sender: Arc::new(Mutex::new(sender)),
      receiver: Arc::new(Mutex::new(receiver)),
    }
  }

  pub fn sender(&self) -> Sender<Event> {
    self.sender.lock().clone()
  }
}