#![allow(dead_code)]
mod action;
mod animation;
mod app;
mod backend;
mod event;
mod gallery_scan;
mod history;
mod model_info;
mod session;
#[cfg(test)]
pub(crate) mod test_env;
mod thumbnails;
mod ui;
use std::io;
use std::panic;
use anyhow::Result;
use crossterm::{
event::{DisableMouseCapture, EnableMouseCapture},
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use ratatui::prelude::*;
use app::App;
pub async fn run_tui(host: Option<String>, local: bool) -> Result<()> {
let picker = ratatui_image::picker::Picker::from_query_stdio()
.unwrap_or_else(|_| ratatui_image::picker::Picker::from_fontsize((8, 16)));
enable_raw_mode()?;
let mut stdout = io::stdout();
execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
let original_hook = panic::take_hook();
panic::set_hook(Box::new(move |panic_info| {
let _ = disable_raw_mode();
let _ = execute!(io::stdout(), LeaveAlternateScreen, DisableMouseCapture);
original_hook(panic_info);
}));
let version = mold_core::build_info::version_string();
tracing::info!(%version, "starting mold tui");
let mut app = App::new(host, local, picker)?;
let result = run_event_loop(&mut terminal, &mut app).await;
app.shutdown();
disable_raw_mode()?;
execute!(
terminal.backend_mut(),
LeaveAlternateScreen,
DisableMouseCapture
)?;
terminal.show_cursor()?;
result
}
async fn run_event_loop(
terminal: &mut Terminal<CrosstermBackend<io::Stdout>>,
app: &mut App,
) -> Result<()> {
let mut last_resource_refresh = std::time::Instant::now();
if app.should_poll_remote() {
app.spawn_server_status_fetch();
} else {
app.resource_info.refresh_local();
}
loop {
terminal.draw(|frame| ui::render(frame, app))?;
if crossterm::event::poll(std::time::Duration::from_millis(16))? {
let event = crossterm::event::read()?;
app.handle_crossterm_event(event);
}
app.process_background_events();
app.tick_animations();
if last_resource_refresh.elapsed() >= std::time::Duration::from_secs(2) {
if app.should_poll_remote() {
app.spawn_server_status_fetch();
} else {
app.resource_info.refresh_local();
}
last_resource_refresh = std::time::Instant::now();
}
if app.should_quit {
return Ok(());
}
}
}