WIP: TUI actor
This commit is contained in:
parent
08d2377404
commit
f0a1d43e96
7 changed files with 144 additions and 1 deletions
|
@ -5,10 +5,13 @@ mod forge;
|
||||||
mod init;
|
mod init;
|
||||||
mod repo;
|
mod repo;
|
||||||
mod server;
|
mod server;
|
||||||
mod webhook;
|
|
||||||
|
#[cfg(feature = "tui")]
|
||||||
|
mod tui;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
mod webhook;
|
||||||
|
|
||||||
use git_next_core::git;
|
use git_next_core::git;
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,15 @@ pub fn start(
|
||||||
let fw_shutdown = watch_file("git-next-server.toml".into(), server.clone().recipient())
|
let fw_shutdown = watch_file("git-next-server.toml".into(), server.clone().recipient())
|
||||||
.expect("file watcher");
|
.expect("file watcher");
|
||||||
|
|
||||||
|
// info!("Start Terminal...");
|
||||||
|
// #[cfg(feature = "tui")]
|
||||||
|
// {
|
||||||
|
// info!("Start Terminal...");
|
||||||
|
// let tui = crate::tui::Tui::default();
|
||||||
|
// let tui_addr = tui.start();
|
||||||
|
// tui_addr.do_send(crate::tui::Start);
|
||||||
|
// }
|
||||||
|
|
||||||
info!("Server running - Press Ctrl-C to stop...");
|
info!("Server running - Press Ctrl-C to stop...");
|
||||||
let _ = actix_rt::signal::ctrl_c().await;
|
let _ = actix_rt::signal::ctrl_c().await;
|
||||||
info!("Ctrl-C received, shutting down...");
|
info!("Ctrl-C received, shutting down...");
|
||||||
|
|
2
crates/cli/src/tui/actor/handlers/mod.rs
Normal file
2
crates/cli/src/tui/actor/handlers/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
//
|
||||||
|
mod start;
|
58
crates/cli/src/tui/actor/handlers/start.rs
Normal file
58
crates/cli/src/tui/actor/handlers/start.rs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
use std::io::Stderr;
|
||||||
|
|
||||||
|
//
|
||||||
|
use actix::{ContextFutureSpawner, Handler, WrapFuture};
|
||||||
|
use ratatui::{
|
||||||
|
crossterm::event::{self, KeyCode, KeyEventKind},
|
||||||
|
prelude::CrosstermBackend,
|
||||||
|
style::Stylize,
|
||||||
|
widgets::Paragraph,
|
||||||
|
Terminal,
|
||||||
|
};
|
||||||
|
use tracing::Instrument;
|
||||||
|
|
||||||
|
use crate::tui::actor::{messages::Start, Tui};
|
||||||
|
|
||||||
|
impl Handler<Start> for Tui {
|
||||||
|
type Result = ();
|
||||||
|
|
||||||
|
fn handle(&mut self, _msg: Start, ctx: &mut Self::Context) -> Self::Result {
|
||||||
|
let Some(mut terminal) = self.terminal.take() else {
|
||||||
|
tracing::error!("Unable to start without terminal");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
async move { terminal_loop_wrapper(&mut terminal) }
|
||||||
|
.in_current_span()
|
||||||
|
.into_actor(self)
|
||||||
|
.wait(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn terminal_loop_wrapper(terminal: &mut Terminal<CrosstermBackend<Stderr>>) {
|
||||||
|
match terminal_loop(terminal) {
|
||||||
|
Ok(()) => tracing::info!("Terminal closed"),
|
||||||
|
Err(err) => tracing::error!(?err, "Terminal closed"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn terminal_loop(terminal: &mut Terminal<CrosstermBackend<Stderr>>) -> std::io::Result<()> {
|
||||||
|
loop {
|
||||||
|
terminal.draw(|frame| {
|
||||||
|
let area = frame.area();
|
||||||
|
frame.render_widget(
|
||||||
|
Paragraph::new("Hello Ratatui! (press 'q' to quit)")
|
||||||
|
.white()
|
||||||
|
.on_blue(),
|
||||||
|
area,
|
||||||
|
);
|
||||||
|
})?;
|
||||||
|
if event::poll(std::time::Duration::from_millis(16))? {
|
||||||
|
if let event::Event::Key(key) = event::read()? {
|
||||||
|
if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('q') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
4
crates/cli/src/tui/actor/messages.rs
Normal file
4
crates/cli/src/tui/actor/messages.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
//
|
||||||
|
use git_next_core::message;
|
||||||
|
|
||||||
|
message!(Start, "Start the TUI");
|
62
crates/cli/src/tui/actor/mod.rs
Normal file
62
crates/cli/src/tui/actor/mod.rs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
//
|
||||||
|
mod handlers;
|
||||||
|
pub mod messages;
|
||||||
|
|
||||||
|
use std::io::{stderr, Stderr};
|
||||||
|
|
||||||
|
use actix::{Actor, Context};
|
||||||
|
|
||||||
|
use ratatui::{
|
||||||
|
crossterm::{
|
||||||
|
execute,
|
||||||
|
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
||||||
|
},
|
||||||
|
prelude::CrosstermBackend,
|
||||||
|
Terminal,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct Tui {
|
||||||
|
terminal: Option<Terminal<CrosstermBackend<Stderr>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Actor for Tui {
|
||||||
|
type Context = Context<Self>;
|
||||||
|
|
||||||
|
fn started(&mut self, _ctx: &mut Self::Context) {
|
||||||
|
match init() {
|
||||||
|
Ok(terminal) => {
|
||||||
|
self.terminal.replace(terminal);
|
||||||
|
}
|
||||||
|
Err(err) => tracing::error!(?err, "Failed to start terminal UI"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stopped(&mut self, _ctx: &mut Self::Context) {
|
||||||
|
if let Err(err) = restore() {
|
||||||
|
match std::env::consts::OS {
|
||||||
|
"linux" | "macos" => {
|
||||||
|
tracing::error!(
|
||||||
|
?err,
|
||||||
|
"Failed to restore terminal: Type `reset` to restore terminal"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
"windows" => {
|
||||||
|
tracing::error!(?err, "Failed to restore terminal: Reopen a new terminal");
|
||||||
|
}
|
||||||
|
_ => tracing::error!(?err, "Failed to restore terminal"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init() -> std::io::Result<Terminal<CrosstermBackend<Stderr>>> {
|
||||||
|
execute!(stderr(), EnterAlternateScreen)?;
|
||||||
|
enable_raw_mode()?;
|
||||||
|
Terminal::new(CrosstermBackend::new(stderr()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn restore() -> std::io::Result<()> {
|
||||||
|
execute!(stderr(), LeaveAlternateScreen)?;
|
||||||
|
disable_raw_mode()
|
||||||
|
}
|
5
crates/cli/src/tui/mod.rs
Normal file
5
crates/cli/src/tui/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
//
|
||||||
|
mod actor;
|
||||||
|
|
||||||
|
// pub use actor::messages::Start;
|
||||||
|
// pub use actor::Tui;
|
Loading…
Reference in a new issue