agent_ui: Improve message editor history navigation (#35532)
- We no longer move through history if a message has been edited by the user - It is possible to navigate back down to an empty message Co-authored-by: Cole Miller <cole@zed.dev> Release Notes: - N/A Co-authored-by: Cole Miller <cole@zed.dev>
This commit is contained in:
parent
f4391ed631
commit
986e3e7cbc
1 changed files with 63 additions and 19 deletions
|
@ -31,7 +31,7 @@ use markdown::{HeadingLevelStyles, Markdown, MarkdownElement, MarkdownStyle};
|
|||
use parking_lot::Mutex;
|
||||
use project::Project;
|
||||
use settings::Settings as _;
|
||||
use text::Anchor;
|
||||
use text::{Anchor, BufferSnapshot};
|
||||
use theme::ThemeSettings;
|
||||
use ui::{Disclosure, Divider, DividerColor, KeyBinding, Tooltip, prelude::*};
|
||||
use util::ResultExt;
|
||||
|
@ -61,7 +61,7 @@ pub struct AcpThreadView {
|
|||
thread_state: ThreadState,
|
||||
diff_editors: HashMap<EntityId, Entity<Editor>>,
|
||||
message_editor: Entity<Editor>,
|
||||
message_set_from_history: bool,
|
||||
message_set_from_history: Option<BufferSnapshot>,
|
||||
_message_editor_subscription: Subscription,
|
||||
mention_set: Arc<Mutex<MentionSet>>,
|
||||
notifications: Vec<WindowHandle<AgentNotification>>,
|
||||
|
@ -144,14 +144,28 @@ impl AcpThreadView {
|
|||
editor
|
||||
});
|
||||
|
||||
let message_editor_subscription = cx.subscribe(&message_editor, |this, _, event, _| {
|
||||
if let editor::EditorEvent::BufferEdited = &event {
|
||||
if !this.message_set_from_history {
|
||||
this.message_history.borrow_mut().reset_position();
|
||||
let message_editor_subscription =
|
||||
cx.subscribe(&message_editor, |this, editor, event, cx| {
|
||||
if let editor::EditorEvent::BufferEdited = &event {
|
||||
let buffer = editor
|
||||
.read(cx)
|
||||
.buffer()
|
||||
.read(cx)
|
||||
.as_singleton()
|
||||
.unwrap()
|
||||
.read(cx)
|
||||
.snapshot();
|
||||
if let Some(message) = this.message_set_from_history.clone()
|
||||
&& message.version() != buffer.version()
|
||||
{
|
||||
this.message_set_from_history = None;
|
||||
}
|
||||
|
||||
if this.message_set_from_history.is_none() {
|
||||
this.message_history.borrow_mut().reset_position();
|
||||
}
|
||||
}
|
||||
this.message_set_from_history = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
let mention_set = mention_set.clone();
|
||||
|
||||
|
@ -178,7 +192,7 @@ impl AcpThreadView {
|
|||
project: project.clone(),
|
||||
thread_state: Self::initial_state(agent, workspace, project, window, cx),
|
||||
message_editor,
|
||||
message_set_from_history: false,
|
||||
message_set_from_history: None,
|
||||
_message_editor_subscription: message_editor_subscription,
|
||||
mention_set,
|
||||
notifications: Vec::new(),
|
||||
|
@ -424,11 +438,21 @@ impl AcpThreadView {
|
|||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
if self.message_set_from_history.is_none() && !self.message_editor.read(cx).is_empty(cx) {
|
||||
self.message_editor.update(cx, |editor, cx| {
|
||||
editor.move_up(&Default::default(), window, cx);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
self.message_set_from_history = Self::set_draft_message(
|
||||
self.message_editor.clone(),
|
||||
self.mention_set.clone(),
|
||||
self.project.clone(),
|
||||
self.message_history.borrow_mut().prev(),
|
||||
self.message_history
|
||||
.borrow_mut()
|
||||
.prev()
|
||||
.map(|blocks| blocks.as_slice()),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
|
@ -440,14 +464,35 @@ impl AcpThreadView {
|
|||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.message_set_from_history = Self::set_draft_message(
|
||||
if self.message_set_from_history.is_none() {
|
||||
self.message_editor.update(cx, |editor, cx| {
|
||||
editor.move_down(&Default::default(), window, cx);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let mut message_history = self.message_history.borrow_mut();
|
||||
let next_history = message_history.next();
|
||||
|
||||
let set_draft_message = Self::set_draft_message(
|
||||
self.message_editor.clone(),
|
||||
self.mention_set.clone(),
|
||||
self.project.clone(),
|
||||
self.message_history.borrow_mut().next(),
|
||||
Some(
|
||||
next_history
|
||||
.map(|blocks| blocks.as_slice())
|
||||
.unwrap_or_else(|| &[]),
|
||||
),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
// If we reset the text to an empty string because we ran out of history,
|
||||
// we don't want to mark it as coming from the history
|
||||
self.message_set_from_history = if next_history.is_some() {
|
||||
set_draft_message
|
||||
} else {
|
||||
None
|
||||
};
|
||||
}
|
||||
|
||||
fn open_agent_diff(&mut self, _: &OpenAgentDiff, window: &mut Window, cx: &mut Context<Self>) {
|
||||
|
@ -481,15 +526,13 @@ impl AcpThreadView {
|
|||
message_editor: Entity<Editor>,
|
||||
mention_set: Arc<Mutex<MentionSet>>,
|
||||
project: Entity<Project>,
|
||||
message: Option<&Vec<acp::ContentBlock>>,
|
||||
message: Option<&[acp::ContentBlock]>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> bool {
|
||||
) -> Option<BufferSnapshot> {
|
||||
cx.notify();
|
||||
|
||||
let Some(message) = message else {
|
||||
return false;
|
||||
};
|
||||
let message = message?;
|
||||
|
||||
let mut text = String::new();
|
||||
let mut mentions = Vec::new();
|
||||
|
@ -553,7 +596,8 @@ impl AcpThreadView {
|
|||
}
|
||||
}
|
||||
|
||||
true
|
||||
let snapshot = snapshot.as_singleton().unwrap().2.clone();
|
||||
Some(snapshot.text)
|
||||
}
|
||||
|
||||
fn handle_thread_event(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue