feat(ui): scrollable help menu, Esc-to-close, + blush/matrix/wraith themes
The help overlay now scrolls (↑/↓, PgUp/PgDn, Home/End) with a position indicator and only Esc dismisses it, so stray keystrokes can't close a menu that overflows the screen. Adds three bundled vestments (blush, matrix, wraith); they're auto-discovered via Theme::available(), so they appear in the menu and /theme list with no hardcoded entries. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+25
-1
@@ -128,6 +128,8 @@ pub struct App {
|
||||
pub sbx_scroll: usize,
|
||||
/// Whether the help overlay is showing.
|
||||
pub show_help: bool,
|
||||
/// Vertical scroll offset (rows) into the help overlay when it doesn't fit.
|
||||
pub help_scroll: u16,
|
||||
/// A reconnect handshake is in flight (Ctrl-R after a disconnect).
|
||||
pub reconnecting: bool,
|
||||
/// Transient error shown as a popup over the clergy (cleared on next keypress).
|
||||
@@ -159,6 +161,7 @@ impl App {
|
||||
chat_scroll: 0,
|
||||
sbx_scroll: 0,
|
||||
show_help: false,
|
||||
help_scroll: 0,
|
||||
reconnecting: false,
|
||||
error: None,
|
||||
password: String::new(),
|
||||
@@ -610,9 +613,29 @@ pub async fn run(params: net::ConnParams, mut session: Session, mut theme: Theme
|
||||
});
|
||||
}
|
||||
} else if app.show_help {
|
||||
app.show_help = false; // any key dismisses the overlay
|
||||
// While the help overlay is up, arrows / paging scroll it
|
||||
// (when it's taller than the screen); only Esc closes, so
|
||||
// stray keystrokes can't dismiss a menu you're still reading.
|
||||
let max = term
|
||||
.size()
|
||||
.map(|s| ui::help_max_scroll(s.width, s.height, &theme))
|
||||
.unwrap_or(0);
|
||||
match k.code {
|
||||
KeyCode::Up => app.help_scroll = app.help_scroll.saturating_sub(1),
|
||||
KeyCode::Down => app.help_scroll = (app.help_scroll + 1).min(max),
|
||||
KeyCode::PageUp => app.help_scroll = app.help_scroll.saturating_sub(10),
|
||||
KeyCode::PageDown => app.help_scroll = (app.help_scroll + 10).min(max),
|
||||
KeyCode::Home => app.help_scroll = 0,
|
||||
KeyCode::End => app.help_scroll = max,
|
||||
KeyCode::Esc => {
|
||||
app.show_help = false; // Esc dismisses the overlay
|
||||
app.help_scroll = 0;
|
||||
}
|
||||
_ => {} // ignore other keys so the menu stays put
|
||||
}
|
||||
} else if k.code == KeyCode::F(1) {
|
||||
app.show_help = true; // F1 from any mode
|
||||
app.help_scroll = 0;
|
||||
} else if k.code == KeyCode::F(2) {
|
||||
if app.sandbox.is_none() {
|
||||
} else if app.can_drive() {
|
||||
@@ -876,6 +899,7 @@ fn handle_command(
|
||||
let room = &session.room;
|
||||
if line == "/help" || line == "/?" {
|
||||
app.show_help = true;
|
||||
app.help_scroll = 0;
|
||||
} else if line == "/pw" || line == "/password" {
|
||||
// Show the room password locally (never broadcast). Handy when the
|
||||
// server's password was autogenerated and you need to read it off / share
|
||||
|
||||
Reference in New Issue
Block a user