Build the Mutt-style TUI shell and action model
This commit is contained in:
64
apps/tui/src/lib.rs
Normal file
64
apps/tui/src/lib.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(clippy::disallowed_types)]
|
||||
|
||||
//! Presentation-only state, rendering, and event plumbing for the terminal UI.
|
||||
|
||||
pub mod action;
|
||||
pub mod app;
|
||||
pub mod runtime;
|
||||
pub mod terminal;
|
||||
pub mod ui;
|
||||
|
||||
use std::{io, time::Duration};
|
||||
|
||||
use crossterm::event::{self, Event, KeyEventKind};
|
||||
use ratatui::DefaultTerminal;
|
||||
|
||||
use crate::{
|
||||
action::resolve_key,
|
||||
app::{App, AsyncPayload, StartupSummary},
|
||||
runtime::AsyncExecutor,
|
||||
};
|
||||
|
||||
const TICK_INTERVAL: Duration = Duration::from_millis(250);
|
||||
|
||||
/// Run the interactive event loop. Polling keeps input responsive while storage
|
||||
/// work runs on the executor and periodic repaints are pending.
|
||||
pub fn run(terminal: &mut DefaultTerminal) -> io::Result<()> {
|
||||
let mut app = App::new();
|
||||
let executor = AsyncExecutor::new();
|
||||
let startup = app.begin_request();
|
||||
executor.submit(startup, || {
|
||||
ironstorage::config::Config::load(None)
|
||||
.map(|config| {
|
||||
AsyncPayload::Startup(StartupSummary {
|
||||
configuration: config.source().display().to_string(),
|
||||
vault: config.vault().display().to_string(),
|
||||
})
|
||||
})
|
||||
.map_err(|error| error.to_string())
|
||||
});
|
||||
|
||||
while !app.should_quit() {
|
||||
for result in executor.drain() {
|
||||
app.apply_result(result);
|
||||
}
|
||||
|
||||
terminal.draw(|frame| ui::draw(frame, &app))?;
|
||||
if !event::poll(TICK_INTERVAL)? {
|
||||
app.tick();
|
||||
continue;
|
||||
}
|
||||
|
||||
match event::read()? {
|
||||
Event::Key(key) if key.kind == KeyEventKind::Press => {
|
||||
if let Some(action) = resolve_key(app.mode(), key.code, key.modifiers) {
|
||||
app.dispatch(action);
|
||||
}
|
||||
}
|
||||
Event::Resize(width, height) => app.resize(width, height),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user