git-next/crates/cli/src/tui/actor/mod.rs

81 lines
2.1 KiB
Rust
Raw Normal View History

//
mod handlers;
pub mod messages;
mod model;
use std::sync::mpsc::Sender;
use actix::{Actor, ActorContext as _, Context};
pub use model::*;
use ratatui::{
crossterm::event::{self, KeyCode, KeyEventKind},
DefaultTerminal,
};
#[derive(Debug)]
pub struct Tui {
terminal: Option<DefaultTerminal>,
signal_shutdown: Sender<()>,
pub state: State,
}
impl Actor for Tui {
type Context = Context<Self>;
fn started(&mut self, _ctx: &mut Self::Context) {
self.terminal.replace(ratatui::init());
}
fn stopped(&mut self, _ctx: &mut Self::Context) {
self.terminal.take();
ratatui::restore();
}
}
impl Tui {
pub fn new(signal_shutdown: Sender<()>) -> Self {
Self {
terminal: None,
signal_shutdown,
state: State::initial(),
}
}
pub const fn state(&self) -> &State {
&self.state
}
fn draw(&mut self) -> std::io::Result<()> {
let t = self.terminal.take();
if let Some(mut terminal) = t {
terminal.draw(|frame| {
frame.render_widget(self.state(), frame.area());
})?;
self.terminal = Some(terminal);
} else {
eprintln!("No terminal setup");
}
Ok(())
}
fn handle_input(&self, ctx: &mut <Self as actix::Actor>::Context) -> std::io::Result<()> {
if event::poll(std::time::Duration::from_millis(16))? {
if let event::Event::Key(key) = event::read()? {
if key.kind == KeyEventKind::Press {
match key.code {
KeyCode::Char('q') => {
ctx.stop();
if let Err(err) = self.signal_shutdown.send(()) {
tracing::error!(?err, "Failed to signal shutdown");
}
}
KeyCode::Esc => {
//
}
_ => (),
}
}
}
}
Ok(())
}
}