From ceaba36c7fdd0eff4ebd5a4bb43af39ec55a0669 Mon Sep 17 00:00:00 2001 From: easong-openai Date: Wed, 1 Oct 2025 11:42:04 -0700 Subject: [PATCH] fix ctr-n hint (#4566) don't show or enable ctr-n to choose best of n while not in the composer --- codex-rs/cloud-tasks/src/lib.rs | 3 +++ codex-rs/cloud-tasks/src/ui.rs | 34 ++++++++++++++++++++------------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/codex-rs/cloud-tasks/src/lib.rs b/codex-rs/cloud-tasks/src/lib.rs index d57a4057..cea19b97 100644 --- a/codex-rs/cloud-tasks/src/lib.rs +++ b/codex-rs/cloud-tasks/src/lib.rs @@ -839,6 +839,9 @@ pub async fn run_main(_cli: Cli, _codex_linux_sandbox_exe: Option) -> a && matches!(key.code, KeyCode::Char('n') | KeyCode::Char('N')) || matches!(key.code, KeyCode::Char('\u{000E}')); if is_ctrl_n { + if app.new_task.is_none() { + continue; + } if app.best_of_modal.is_some() { app.best_of_modal = None; needs_redraw = true; diff --git a/codex-rs/cloud-tasks/src/ui.rs b/codex-rs/cloud-tasks/src/ui.rs index 94fb3ad9..fe91b0ce 100644 --- a/codex-rs/cloud-tasks/src/ui.rs +++ b/codex-rs/cloud-tasks/src/ui.rs @@ -262,9 +262,9 @@ fn draw_footer(frame: &mut Frame, area: Rect, app: &mut App) { help.push(": Apply ".dim()); } help.push("o : Set Env ".dim()); - help.push("Ctrl+N".dim()); - help.push(format!(": Attempts {}x ", app.best_of_n).dim()); if app.new_task.is_some() { + help.push("Ctrl+N".dim()); + help.push(format!(": Attempts {}x ", app.best_of_n).dim()); help.push("(editing new task) ".dim()); } else { help.push("n : New Task ".dim()); @@ -1004,32 +1004,40 @@ pub fn draw_best_of_modal(frame: &mut Frame, area: Rect, app: &mut App) { use ratatui::widgets::Wrap; let inner = overlay_outer(area); + const MAX_WIDTH: u16 = 40; + const MIN_WIDTH: u16 = 20; + const MAX_HEIGHT: u16 = 12; + const MIN_HEIGHT: u16 = 6; + let modal_width = inner.width.min(MAX_WIDTH).max(inner.width.min(MIN_WIDTH)); + let modal_height = inner + .height + .min(MAX_HEIGHT) + .max(inner.height.min(MIN_HEIGHT)); + let modal_x = inner.x + (inner.width.saturating_sub(modal_width)) / 2; + let modal_y = inner.y + (inner.height.saturating_sub(modal_height)) / 2; + let modal_area = Rect::new(modal_x, modal_y, modal_width, modal_height); let title = Line::from(vec!["Parallel Attempts".magenta().bold()]); let block = overlay_block().title(title); - frame.render_widget(Clear, inner); - frame.render_widget(block.clone(), inner); - let content = overlay_content(inner); + frame.render_widget(Clear, modal_area); + frame.render_widget(block.clone(), modal_area); + let content = overlay_content(modal_area); let rows = Layout::default() .direction(Direction::Vertical) .constraints([Constraint::Length(2), Constraint::Min(1)]) .split(content); - let hint = Paragraph::new(Line::from( - "Use ↑/↓ to choose, 1-4 jump; Enter confirm, Esc cancel" - .cyan() - .dim(), - )) - .wrap(Wrap { trim: true }); + let hint = Paragraph::new(Line::from("Use ↑/↓ to choose, 1-4 jump".cyan().dim())) + .wrap(Wrap { trim: true }); frame.render_widget(hint, rows[0]); let selected = app.best_of_modal.as_ref().map(|m| m.selected).unwrap_or(0); let options = [1usize, 2, 3, 4]; let mut items: Vec = Vec::new(); for &attempts in &options { - let mut spans: Vec = - vec![format!("{attempts} attempt{}", if attempts == 1 { "" } else { "s" }).into()]; + let noun = if attempts == 1 { "attempt" } else { "attempts" }; + let mut spans: Vec = vec![format!("{attempts} {noun:<8}").into()]; spans.push(" ".into()); spans.push(format!("{attempts}x parallel").dim()); if attempts == app.best_of_n {