@@ -44,7 +44,7 @@ impl AgentDiff {
workspace: WeakEntity<Workspace>,
window: &mut Window,
cx: &mut App,
- ) -> Result<()> {
+ ) -> Result<Entity<Self>> {
let existing_diff = workspace.update(cx, |workspace, cx| {
workspace
.items_of_type::<AgentDiff>(cx)
@@ -53,13 +53,15 @@ impl AgentDiff {
if let Some(existing_diff) = existing_diff {
workspace.update(cx, |workspace, cx| {
workspace.activate_item(&existing_diff, true, true, window, cx);
- })
+ })?;
+ Ok(existing_diff)
} else {
let agent_diff =
cx.new(|cx| AgentDiff::new(thread.clone(), workspace.clone(), window, cx));
workspace.update(cx, |workspace, cx| {
- workspace.add_item_to_center(Box::new(agent_diff), window, cx);
- })
+ workspace.add_item_to_center(Box::new(agent_diff.clone()), window, cx);
+ })?;
+ Ok(agent_diff)
}
}
@@ -134,11 +136,11 @@ impl AgentDiff {
let mut paths_to_delete = self.multibuffer.read(cx).paths().collect::<HashSet<_>>();
for (buffer, diff_handle) in changed_buffers {
- let Some(file) = buffer.read(cx).file().cloned() else {
+ if buffer.read(cx).file().is_none() {
continue;
- };
+ }
- let path_key = PathKey::namespaced(0, file.full_path(cx).into());
+ let path_key = PathKey::for_buffer(&buffer, cx);
paths_to_delete.remove(&path_key);
let snapshot = buffer.read(cx).snapshot();
@@ -241,6 +243,26 @@ impl AgentDiff {
}
}
+ pub fn move_to_path(&mut self, path_key: PathKey, window: &mut Window, cx: &mut Context<Self>) {
+ if let Some(position) = self.multibuffer.read(cx).location_for_path(&path_key, cx) {
+ self.editor.update(cx, |editor, cx| {
+ let first_hunk = editor
+ .diff_hunks_in_ranges(
+ &[position..editor::Anchor::max()],
+ &self.multibuffer.read(cx).read(cx),
+ )
+ .next();
+
+ if let Some(first_hunk) = first_hunk {
+ let first_hunk_start = first_hunk.multi_buffer_range().start;
+ editor.change_selections(Some(Autoscroll::fit()), window, cx, |selections| {
+ selections.select_anchor_ranges([first_hunk_start..first_hunk_start]);
+ })
+ }
+ });
+ }
+ }
+
fn keep(&mut self, _: &crate::Keep, window: &mut Window, cx: &mut Context<Self>) {
let ranges = self
.editor
@@ -9,8 +9,10 @@ use gpui::{
Animation, AnimationExt, App, DismissEvent, Entity, Focusable, Subscription, TextStyle,
WeakEntity, linear_color_stop, linear_gradient, point,
};
+use language::Buffer;
use language_model::LanguageModelRegistry;
use language_model_selector::ToggleModelSelector;
+use multi_buffer;
use project::Project;
use settings::Settings;
use std::time::Duration;
@@ -320,6 +322,19 @@ impl MessageEditor {
fn handle_review_click(&self, window: &mut Window, cx: &mut Context<Self>) {
AgentDiff::deploy(self.thread.clone(), self.workspace.clone(), window, cx).log_err();
}
+
+ fn handle_file_click(
+ &self,
+ buffer: Entity<Buffer>,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ if let Ok(diff) = AgentDiff::deploy(self.thread.clone(), self.workspace.clone(), window, cx)
+ {
+ let path_key = multi_buffer::PathKey::for_buffer(&buffer, cx);
+ diff.update(cx, |diff, cx| diff.move_to_path(path_key, window, cx));
+ }
+ }
}
impl Focusable for MessageEditor {
@@ -487,11 +502,16 @@ impl Render for MessageEditor {
}])
.child(
h_flex()
+ .id("edits-container")
.p_1p5()
.justify_between()
.when(self.edits_expanded, |this| {
this.border_b_1().border_color(border_color)
})
+ .cursor_pointer()
+ .on_click(cx.listener(|this, _, window, cx| {
+ this.handle_review_click(window, cx)
+ }))
.child(
h_flex()
.gap_1()
@@ -605,11 +625,21 @@ impl Render for MessageEditor {
.justify_between()
.child(
h_flex()
- .id("file-container")
+ .id(("file-container", index))
.pr_8()
.gap_1p5()
.max_w_full()
.overflow_x_scroll()
+ .cursor_pointer()
+ .on_click({
+ let buffer = buffer.clone();
+ cx.listener(move |this, _, window, cx| {
+ this.handle_file_click(buffer.clone(), window, cx);
+ })
+ })
+ .tooltip(
+ Tooltip::text(format!("Review {}", path.display()))
+ )
.child(file_icon)
.child(
h_flex()