From 934d728946ac579f48b4f08aa82941dfce4da783 Mon Sep 17 00:00:00 2001 From: Thibault Sottiaux Date: Mon, 15 Sep 2025 08:30:32 -0700 Subject: [PATCH] feat: skip animations on small terminals (#3647) Changes: - skip the welcome animation when the terminal area is below 60x21 - skip the model upgrade animation when the terminal area is below 60x24 to avoid clipping --------- Co-authored-by: Michael Bolin --- codex-rs/tui/src/new_model_popup.rs | 18 ++++++++++++------ codex-rs/tui/src/onboarding/welcome.rs | 16 ++++++++++++---- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/codex-rs/tui/src/new_model_popup.rs b/codex-rs/tui/src/new_model_popup.rs index aad89e48..5ed53e4d 100644 --- a/codex-rs/tui/src/new_model_popup.rs +++ b/codex-rs/tui/src/new_model_popup.rs @@ -22,6 +22,8 @@ use std::time::Duration; use tokio_stream::StreamExt; const FRAME_TICK: Duration = FRAME_TICK_DEFAULT; +const MIN_ANIMATION_HEIGHT: u16 = 24; +const MIN_ANIMATION_WIDTH: u16 = 60; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub(crate) enum ModelUpgradeDecision { @@ -121,13 +123,17 @@ impl WidgetRef for &ModelUpgradePopup { fn render_ref(&self, area: Rect, buf: &mut Buffer) { Clear.render(area, buf); - let mut lines: Vec = self.frames()[self.frame_idx] - .lines() - .map(|l| l.to_string().into()) - .collect(); + // Skip the animation entirely when the viewport is too small so we don't clip frames. + let show_animation = + area.height >= MIN_ANIMATION_HEIGHT && area.width >= MIN_ANIMATION_WIDTH; - // Spacer between animation and text content. - lines.push("".into()); + let mut lines: Vec = Vec::new(); + if show_animation { + let frame = self.frames()[self.frame_idx]; + lines.extend(frame.lines().map(|l| l.into())); + // Spacer between animation and text content. + lines.push("".into()); + } lines.push( format!(" Codex is now powered by {GPT_5_CODEX_DISPLAY_NAME}, a new model that is") diff --git a/codex-rs/tui/src/onboarding/welcome.rs b/codex-rs/tui/src/onboarding/welcome.rs index 40911b84..1e99fbf5 100644 --- a/codex-rs/tui/src/onboarding/welcome.rs +++ b/codex-rs/tui/src/onboarding/welcome.rs @@ -17,6 +17,8 @@ use std::time::Duration; use std::time::Instant; const FRAME_TICK: Duration = FRAME_TICK_DEFAULT; +const MIN_ANIMATION_HEIGHT: u16 = 21; +const MIN_ANIMATION_WIDTH: u16 = 60; pub(crate) struct WelcomeWidget { pub is_logged_in: bool, @@ -44,11 +46,17 @@ impl WidgetRef for &WelcomeWidget { let frames = &FRAMES_DEFAULT; let idx = ((elapsed_ms / FRAME_TICK.as_millis()) % frames.len() as u128) as usize; + // Skip the animation entirely when the viewport is too small so we don't clip frames. + let show_animation = + area.height >= MIN_ANIMATION_HEIGHT && area.width >= MIN_ANIMATION_WIDTH; - let mut lines: Vec = Vec::with_capacity(frames.len() + 2); - lines.extend(frames[idx].lines().map(|l| l.into())); - - lines.push("".into()); + let mut lines: Vec = Vec::new(); + if show_animation { + let frame_line_count = frames[idx].lines().count(); + lines.reserve(frame_line_count + 2); + lines.extend(frames[idx].lines().map(|l| l.into())); + lines.push("".into()); + } lines.push(Line::from(vec![ " ".into(), "Welcome to ".into(),