use super::event::AppEvent;
use super::term_reader::run_term_read;
use super::tui_loop::run_ui_loop;
use crate::Result;
use crate::event::{Rx, Tx, new_channel};
use crate::exec::cli::CliArgs;
use crate::exec::{ExecActionEvent, ExecutorTx};
use crate::hub::get_hub;
use crate::model::ModelManager;
use crate::term::TermTitleGuard;
use crossterm::event::{DisableMouseCapture, EnableMouseCapture};
use crossterm::execute;
use derive_more::{Deref, From};
use ratatui::DefaultTerminal;
use std::io::stdout;
pub async fn start_tui(mm: ModelManager, executor_tx: ExecutorTx, args: CliArgs) -> Result<()> {
let title_guard = TermTitleGuard::capture();
let terminal = ratatui::init();
execute!(stdout(), EnableMouseCapture)?;
let _ = exec_app(terminal, mm, executor_tx, args).await;
let _ = title_guard.restore();
ratatui::restore();
execute!(stdout(), DisableMouseCapture)?;
Ok(())
}
#[derive(Clone, From, Deref)]
pub struct ExitTx(Tx<()>);
#[derive(Clone, From, Deref)]
pub struct AppTx(Tx<AppEvent>);
#[derive(Clone, From, Deref)]
pub struct AppRx(Rx<AppEvent>);
async fn exec_app(
mut terminal: DefaultTerminal,
mm: ModelManager,
executor_tx: ExecutorTx,
args: CliArgs,
) -> Result<()> {
let (exit_tx, exit_rx) = new_channel::<()>("exit_term");
let exit_tx = ExitTx::from(exit_tx);
terminal.clear()?;
let (app_tx, app_rx) = new_channel::<AppEvent>("app_event");
let app_tx = AppTx::from(app_tx);
let app_rx = AppRx::from(app_rx);
let _tin_read_handle = run_term_read(app_tx.clone())?;
let _tui_handle = run_ui_loop(terminal, mm, executor_tx.clone(), app_rx, app_tx.clone(), exit_tx)?;
let hub_rx = get_hub().take_rx()?;
tokio::spawn(async move {
loop {
let hub_evt = hub_rx.recv().await;
match hub_evt {
Ok(hub_evt) => {
let _ = app_tx.send(hub_evt).await;
}
Err(err) => {
eprintln!("Error on tui hub_rx loop. Cause {err}");
return;
}
}
}
});
let exec_cmd: ExecActionEvent = args.cmd.into();
tokio::spawn(async move {
let _ = executor_tx.send(exec_cmd).await;
});
let _ = exit_rx.recv().await;
Ok(())
}