Remove the Plan mode composer nudge (#40200)

## What changed

- Keep the normal composer footer visible when a draft contains the word `plan`.
- Remove the contextual “Create a plan?” prompt, its Escape dismissal behavior, and its per-thread dismissal state.

## Testing

- Update wide and narrow composer snapshots to cover the standard footer for plan-related drafts.

GitOrigin-RevId: 1a3c8cfce9d4effa2149790975133f652aa7c914
This commit is contained in:
Eric Traut authored and copyberry committed 2026-08-23 07:24:57 +00:00
1 parent 4582c0a498
commit 83d1fe0e67
14 files changed
+22 -295

No files matched your search

@@ -556,19 +556,6 @@ pub(crate) struct ComposerDraftSnapshot {
const FOOTER_SPACING_HEIGHT: u16 = 0;
/// Builds the one-line nudge that replaces the ambient footer without adding layout height.
fn plan_mode_nudge_line() -> Line<'static> {
Line::from(vec![
"Create a plan?".magenta(),
" ".into(),
key_hint::shift(KeyCode::Tab).into(),
" use Plan mode".into(),
" ".into(),
key_hint::plain(KeyCode::Esc).into(),
" dismiss".into(),
])
}
impl ChatComposer {
fn slash_input(&self) -> SlashInput<'_> {
SlashInput::new(
@@ -639,7 +626,6 @@ impl ChatComposer {
use_shift_enter_hint,
mode: FooterMode::ComposerEmpty,
hint_override: None,
plan_mode_nudge_visible: false,
flash: None,
context_window_percent: None,
context_window_used_tokens: None,
@@ -746,7 +732,6 @@ impl ChatComposer {
self.effort_ignition = Some(EffortIgnition::new(tier, style));
self.effort_animation_style = Some(style);
if self.footer.status_line_enabled
&& !self.footer.plan_mode_nudge_visible
&& let Some(previous) = passive_footer_status_line(&self.footer_props())
{
self.effort_status_line_transition =
@@ -1440,23 +1425,6 @@ impl ChatComposer {
self.footer.hint_override = items;
}
/// Updates whether the Plan-mode nudge replaces the ambient footer row.
///
/// Returns `true` only when the rendered footer can change so callers can avoid scheduling
/// redundant redraws while reevaluating nudge policy on routine composer updates.
pub(crate) fn set_plan_mode_nudge_visible(&mut self, visible: bool) -> bool {
if self.footer.plan_mode_nudge_visible == visible {
return false;
}
self.footer.plan_mode_nudge_visible = visible;
true
}
#[cfg(test)]
pub(crate) fn plan_mode_nudge_visible(&self) -> bool {
self.footer.plan_mode_nudge_visible
}
pub(crate) fn set_remote_image_urls(&mut self, urls: Vec<String>) {
self.attachments
.set_remote_image_urls(urls, &mut self.draft.textarea);
@@ -4275,7 +4243,6 @@ impl ChatComposer {
self.footer.quit_shortcut_expires_at = None;
self.footer.mode = FooterMode::ComposerEmpty;
self.footer.hint_override = Some(Vec::new());
self.footer.plan_mode_nudge_visible = false;
self.footer.flash = None;
}
@@ -4596,17 +4563,6 @@ impl ChatComposer {
};
if let Some(line) = self.history_search_footer_line() {
render_footer_line(hint_rect, buf, line);
} else if self.footer.plan_mode_nudge_visible {
let available_width =
hint_rect.width.saturating_sub(FOOTER_INDENT_COLS as u16) as usize;
render_footer_line(
hint_rect,
buf,
truncate_line_with_ellipsis_if_overflow(
plan_mode_nudge_line(),
available_width,
),
);
} else {
let available_width =
hint_rect.width.saturating_sub(FOOTER_INDENT_COLS as u16) as usize;
@@ -19,7 +19,6 @@ pub(super) struct FooterState {
pub(super) use_shift_enter_hint: bool,
pub(super) mode: FooterMode,
pub(super) hint_override: Option<Vec<(String, String)>>,
pub(super) plan_mode_nudge_visible: bool,
pub(super) flash: Option<FooterFlash>,
pub(super) context_window_percent: Option<i64>,
pub(super) context_window_used_tokens: Option<i64>,
@@ -59,25 +59,6 @@ fn effort_transition_does_not_queue_a_missing_outgoing_status_line() {
assert!(composer.effort_status_line_transition.is_none());
}
#[test]
fn effort_transition_does_not_queue_while_plan_mode_nudge_is_visible() {
let (mut composer, _rx) = new_test_composer();
composer.set_status_line_enabled(/*enabled*/ true);
composer.set_status_line(Some(Line::from("gpt-5.4 high · main")));
composer.set_plan_mode_nudge_visible(/*visible*/ true);
composer.set_active_reasoning_effort(
Some(&ReasoningEffort::High),
/*animations_enabled*/ true,
);
assert!(composer.set_active_reasoning_effort(
Some(&ReasoningEffort::Ultra),
/*animations_enabled*/ true,
));
assert!(composer.effort_ignition.is_some());
assert!(composer.effort_status_line_transition.is_none());
}
#[test]
fn effort_composer_restored_baseline_and_reduced_motion_do_not_start() {
let (mut composer, _rx) = new_test_composer();
-12
View File
@@ -933,18 +933,6 @@ impl BottomPane {
self.request_redraw();
}
/// Applies the externally decided Plan-mode nudge visibility to the footer presentation.
pub(crate) fn set_plan_mode_nudge_visible(&mut self, visible: bool) {
if self.composer.set_plan_mode_nudge_visible(visible) {
self.request_redraw();
}
}
#[cfg(test)]
pub(crate) fn plan_mode_nudge_visible(&self) -> bool {
self.composer.plan_mode_nudge_visible()
}
pub(crate) fn set_remote_image_urls(&mut self, urls: Vec<String>) {
self.composer.set_remote_image_urls(urls);
self.request_redraw();