use crossterm::{
event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode},
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use crate::textui::{ui, App, AppWidgets};
use anyhow::Result;
use matrix65::filehost;
use serialport::SerialPort;
use std::io;
use tui::{
backend::{Backend, CrosstermBackend},
Terminal,
};
pub fn start_tui(
port: &mut Box<dyn SerialPort>,
filehost_items: &[filehost::Record],
) -> Result<()> {
enable_raw_mode()?;
let mut stdout = io::stdout();
execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
let app = App::new(port, filehost_items);
let res = run_app(&mut terminal, app);
disable_raw_mode()?;
execute!(
terminal.backend_mut(),
LeaveAlternateScreen,
DisableMouseCapture
)?;
terminal.show_cursor()?;
if let Err(err) = res {
println!("Error: {}", err)
}
Ok(())
}
fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) -> Result<()> {
loop {
terminal.draw(|f| ui::ui(f, &mut app))?;
if let Event::Key(key) = event::read()? {
match key.code {
KeyCode::Char('q') => return Ok(()),
KeyCode::Char('h') => app.toggle_help(),
KeyCode::Char('s') => app.sort_filehost(),
KeyCode::Esc => app.return_to_filehost(),
KeyCode::Up => app.previous_item(),
KeyCode::Down => app.next_item(),
KeyCode::Enter => {
if app.cbm_browser.is_selected() | app.file_action.is_selected() {
app.busy = true;
terminal.draw(|f| ui::ui(f, &mut app))?;
} else {
app.busy = false;
}
}
_ => {}
}
let result = match key.code {
KeyCode::Char('R') => app.reset(),
KeyCode::Enter => match app.active_widget {
AppWidgets::FileSelector => app.select_filehost_item(),
AppWidgets::FileAction => app.select_file_action(),
AppWidgets::CBMBrowser => app.select_cbm_item(),
_ => Ok(()),
},
_ => Ok(()),
};
match result {
Ok(()) => {}
Err(error) => {
app.add_message(error.to_string().as_str());
app.active_widget = AppWidgets::FileSelector;
app.unselect_all();
}
}
}
}
}