diff --git a/crates/tui/src/app.rs b/crates/tui/src/app.rs index 354d29b..8a4ef86 100644 --- a/crates/tui/src/app.rs +++ b/crates/tui/src/app.rs @@ -271,6 +271,10 @@ impl App { } return; } + if key.code == KeyCode::Char('q') { + self.should_quit = true; + return; + } if let Some((_, action)) = self.confirm.clone() { match key.code { KeyCode::Char('y') | KeyCode::Enter => self.perform_confirmed(action).await, @@ -324,8 +328,7 @@ impl App { KeyCode::Char('x') => self.toggle_state().await, KeyCode::Char('d') => self.request_delete(), KeyCode::Char('f') => self.open_files().await, - KeyCode::Char('q') if self.history.is_empty() => self.should_quit = true, - KeyCode::Char('q') | KeyCode::Esc => self.back(), + KeyCode::Esc => self.back(), _ => {} } } @@ -1930,4 +1933,21 @@ mod tests { app.last_input = Instant::now(); assert!(!app.should_auto_reload()); } + + #[tokio::test] + async fn q_quits_from_nested_screens_and_confirmations() { + let mut app = App::new(Config::default(), None).await.unwrap(); + app.history.push(Screen::new(ScreenKind::Home, "Home")); + app.confirm = Some(( + "Delete server?".into(), + ConfirmAction::Server("test".into()), + )); + + app.handle_key(KeyEvent::new(KeyCode::Char('q'), KeyModifiers::NONE)) + .await; + + assert!(app.should_quit); + assert_eq!(app.history.len(), 1); + assert!(app.confirm.is_some()); + } } diff --git a/crates/tui/src/main.rs b/crates/tui/src/main.rs index 5fdbd82..1351d4e 100644 --- a/crates/tui/src/main.rs +++ b/crates/tui/src/main.rs @@ -27,7 +27,7 @@ Keyboard: r reload s choose or manage servers , edit TUI preferences - q back, or quit from a root pane + q quit Editors use Tab/Shift-Tab between fields, normal cursor/editing keys, Ctrl-S to save, and Esc to cancel. Mouse clicks select items, double-click opens them,