Scroll to first hunk when clicking on a file to review in Agent Panel (#28075)
Release Notes: - Added the ability to scroll to a file when clicking on it in the Agent Panel review section.
This commit is contained in:
parent
ee4b6a8db4
commit
a7674d3edc
2 changed files with 60 additions and 8 deletions
|
@ -44,7 +44,7 @@ impl AgentDiff {
|
||||||
workspace: WeakEntity<Workspace>,
|
workspace: WeakEntity<Workspace>,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) -> Result<()> {
|
) -> Result<Entity<Self>> {
|
||||||
let existing_diff = workspace.update(cx, |workspace, cx| {
|
let existing_diff = workspace.update(cx, |workspace, cx| {
|
||||||
workspace
|
workspace
|
||||||
.items_of_type::<AgentDiff>(cx)
|
.items_of_type::<AgentDiff>(cx)
|
||||||
|
@ -53,13 +53,15 @@ impl AgentDiff {
|
||||||
if let Some(existing_diff) = existing_diff {
|
if let Some(existing_diff) = existing_diff {
|
||||||
workspace.update(cx, |workspace, cx| {
|
workspace.update(cx, |workspace, cx| {
|
||||||
workspace.activate_item(&existing_diff, true, true, window, cx);
|
workspace.activate_item(&existing_diff, true, true, window, cx);
|
||||||
})
|
})?;
|
||||||
|
Ok(existing_diff)
|
||||||
} else {
|
} else {
|
||||||
let agent_diff =
|
let agent_diff =
|
||||||
cx.new(|cx| AgentDiff::new(thread.clone(), workspace.clone(), window, cx));
|
cx.new(|cx| AgentDiff::new(thread.clone(), workspace.clone(), window, cx));
|
||||||
workspace.update(cx, |workspace, 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<_>>();
|
let mut paths_to_delete = self.multibuffer.read(cx).paths().collect::<HashSet<_>>();
|
||||||
|
|
||||||
for (buffer, diff_handle) in changed_buffers {
|
for (buffer, diff_handle) in changed_buffers {
|
||||||
let Some(file) = buffer.read(cx).file().cloned() else {
|
if buffer.read(cx).file().is_none() {
|
||||||
continue;
|
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);
|
paths_to_delete.remove(&path_key);
|
||||||
|
|
||||||
let snapshot = buffer.read(cx).snapshot();
|
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>) {
|
fn keep(&mut self, _: &crate::Keep, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
let ranges = self
|
let ranges = self
|
||||||
.editor
|
.editor
|
||||||
|
|
|
@ -9,8 +9,10 @@ use gpui::{
|
||||||
Animation, AnimationExt, App, DismissEvent, Entity, Focusable, Subscription, TextStyle,
|
Animation, AnimationExt, App, DismissEvent, Entity, Focusable, Subscription, TextStyle,
|
||||||
WeakEntity, linear_color_stop, linear_gradient, point,
|
WeakEntity, linear_color_stop, linear_gradient, point,
|
||||||
};
|
};
|
||||||
|
use language::Buffer;
|
||||||
use language_model::LanguageModelRegistry;
|
use language_model::LanguageModelRegistry;
|
||||||
use language_model_selector::ToggleModelSelector;
|
use language_model_selector::ToggleModelSelector;
|
||||||
|
use multi_buffer;
|
||||||
use project::Project;
|
use project::Project;
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -320,6 +322,19 @@ impl MessageEditor {
|
||||||
fn handle_review_click(&self, window: &mut Window, cx: &mut Context<Self>) {
|
fn handle_review_click(&self, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
AgentDiff::deploy(self.thread.clone(), self.workspace.clone(), window, cx).log_err();
|
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 {
|
impl Focusable for MessageEditor {
|
||||||
|
@ -487,11 +502,16 @@ impl Render for MessageEditor {
|
||||||
}])
|
}])
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
|
.id("edits-container")
|
||||||
.p_1p5()
|
.p_1p5()
|
||||||
.justify_between()
|
.justify_between()
|
||||||
.when(self.edits_expanded, |this| {
|
.when(self.edits_expanded, |this| {
|
||||||
this.border_b_1().border_color(border_color)
|
this.border_b_1().border_color(border_color)
|
||||||
})
|
})
|
||||||
|
.cursor_pointer()
|
||||||
|
.on_click(cx.listener(|this, _, window, cx| {
|
||||||
|
this.handle_review_click(window, cx)
|
||||||
|
}))
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
|
@ -605,11 +625,21 @@ impl Render for MessageEditor {
|
||||||
.justify_between()
|
.justify_between()
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
.id("file-container")
|
.id(("file-container", index))
|
||||||
.pr_8()
|
.pr_8()
|
||||||
.gap_1p5()
|
.gap_1p5()
|
||||||
.max_w_full()
|
.max_w_full()
|
||||||
.overflow_x_scroll()
|
.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(file_icon)
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue