tano-tui 0.1.0

Tano terminal user interface
use color_eyre::eyre::Result;
use tokio::{
    sync::{mpsc, oneshot, watch},
    task,
};

use crate::{
    actor::{TuiActor, cmd::TuiCmd, run_tui_actor},
    model::TuiModel,
};

const TUI_ACTOR_KILLED: &str = "TuiActor task has been killed";

#[derive(Clone)]
pub struct TuiActorHandle {
    sender: mpsc::Sender<TuiCmd>,
}

impl TuiActorHandle {
    pub fn new<T: TuiModel>(model_rx: watch::Receiver<T>) -> Result<Self> {
        let (sender, receiver) = mpsc::channel(8);
        let actor = TuiActor::new(receiver, model_rx)?;
        task::spawn_local(run_tui_actor(actor));

        Ok(Self { sender })
    }

    pub async fn render(&self) -> Result<()> {
        let (send, recv) = oneshot::channel();
        let cmd = TuiCmd::Render { respond_to: send };

        let _ = self.sender.send(cmd).await;
        recv.await.expect(TUI_ACTOR_KILLED)
    }

    pub async fn restore(&self) -> Result<()> {
        let (send, recv) = oneshot::channel();
        let cmd = TuiCmd::Restore { respond_to: send };

        let _ = self.sender.send(cmd).await;
        recv.await.expect(TUI_ACTOR_KILLED)
    }

    pub async fn resume(&self) -> Result<()> {
        let (send, recv) = oneshot::channel();
        let cmd = TuiCmd::Resume { respond_to: send };

        let _ = self.sender.send(cmd).await;
        recv.await.expect(TUI_ACTOR_KILLED)
    }
}