From 4981c33bf36f3b2f40d91fbd9433e16e1a0e32c7 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 28 Aug 2025 12:57:09 +0200 Subject: [PATCH] acp: Don't cancel editing when scrolling message out of view (#37020) Release Notes: - agent: Fixed a bug that canceled editing when scrolling the user message out of view. Co-authored-by: Bennet Bo Fenner --- crates/agent_ui/src/acp/entry_view_state.rs | 11 +++++++++-- crates/agent_ui/src/acp/thread_view.rs | 14 +++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/crates/agent_ui/src/acp/entry_view_state.rs b/crates/agent_ui/src/acp/entry_view_state.rs index becf6953fd8e63bd6e208c74234c91beb94c4b44..76b3709325a0c84a72bc71db8a67a3d4bd72dd06 100644 --- a/crates/agent_ui/src/acp/entry_view_state.rs +++ b/crates/agent_ui/src/acp/entry_view_state.rs @@ -6,8 +6,8 @@ use agent2::HistoryStore; use collections::HashMap; use editor::{Editor, EditorMode, MinimapVisibility}; use gpui::{ - AnyEntity, App, AppContext as _, Entity, EntityId, EventEmitter, Focusable, ScrollHandle, - TextStyleRefinement, WeakEntity, Window, + AnyEntity, App, AppContext as _, Entity, EntityId, EventEmitter, FocusHandle, Focusable, + ScrollHandle, TextStyleRefinement, WeakEntity, Window, }; use language::language_settings::SoftWrap; use project::Project; @@ -247,6 +247,13 @@ pub enum Entry { } impl Entry { + pub fn focus_handle(&self, cx: &App) -> Option { + match self { + Self::UserMessage(editor) => Some(editor.read(cx).focus_handle(cx)), + Self::AssistantMessage(_) | Self::Content(_) => None, + } + } + pub fn message_editor(&self) -> Option<&Entity> { match self { Self::UserMessage(editor) => Some(editor), diff --git a/crates/agent_ui/src/acp/thread_view.rs b/crates/agent_ui/src/acp/thread_view.rs index 94b385c04e933fcdf2906db584319ee50702df3a..57d90734ef00d1160eb017d1e1257f63577cbebc 100644 --- a/crates/agent_ui/src/acp/thread_view.rs +++ b/crates/agent_ui/src/acp/thread_view.rs @@ -479,11 +479,14 @@ impl AcpThreadView { .set(thread.read(cx).prompt_capabilities()); let count = thread.read(cx).entries().len(); - this.list_state.splice(0..0, count); this.entry_view_state.update(cx, |view_state, cx| { for ix in 0..count { view_state.sync_entry(ix, &thread, window, cx); } + this.list_state.splice_focusable( + 0..0, + (0..count).map(|ix| view_state.entry(ix)?.focus_handle(cx)), + ); }); if let Some(resume) = resume_thread { @@ -1116,9 +1119,14 @@ impl AcpThreadView { let len = thread.read(cx).entries().len(); let index = len - 1; self.entry_view_state.update(cx, |view_state, cx| { - view_state.sync_entry(index, thread, window, cx) + view_state.sync_entry(index, thread, window, cx); + self.list_state.splice_focusable( + index..index, + [view_state + .entry(index) + .and_then(|entry| entry.focus_handle(cx))], + ); }); - self.list_state.splice(index..index, 1); } AcpThreadEvent::EntryUpdated(index) => { self.entry_view_state.update(cx, |view_state, cx| {