Up or Down

Peter Tripp created

Change summary

crates/agent_ui/src/agent_diff.rs | 17 +++++++++++++----
crates/editor/src/editor.rs       | 24 ++++++++++++++++++++----
crates/editor/src/element.rs      | 14 +++++++++++---
3 files changed, 44 insertions(+), 11 deletions(-)

Detailed changes

crates/agent_ui/src/agent_diff.rs 🔗

@@ -791,20 +791,29 @@ fn render_diff_hunk_controls(
 ) -> AnyElement {
     let editor = editor.clone();
 
-    h_flex()
+    // Get controls positioning from editor state
+    let controls_above = editor.read(cx).diff_hunk_controls_above();
+
+    let mut container = h_flex()
         .h(line_height)
         .mr_0p5()
         .gap_1()
         .px_0p5()
         .py_0p5()
         .border_x_1()
-        .border_t_1()
         .border_color(cx.theme().colors().border)
-        .rounded_t_md()
         .bg(cx.theme().colors().editor_background)
         .gap_1()
         .block_mouse_except_scroll()
-        .shadow_md()
+        .shadow_md();
+
+    if controls_above {
+        container = container.border_t_1().rounded_t_md();
+    } else {
+        container = container.border_b_1().rounded_b_md();
+    }
+
+    container
         .children(vec![
             Button::new(("reject", row as u64), "Reject")
                 .size(ButtonSize::Compact)

crates/editor/src/editor.rs 🔗

@@ -1126,6 +1126,7 @@ pub struct Editor {
     show_git_blame_inline_delay_task: Option<Task<()>>,
     git_blame_inline_enabled: bool,
     render_diff_hunk_controls: RenderDiffHunkControlsFn,
+    diff_hunk_controls_above: bool,
     serialize_dirty_buffers: bool,
     show_selection_menu: Option<bool>,
     blame: Option<Entity<GitBlame>>,
@@ -2137,6 +2138,7 @@ impl Editor {
             git_blame_inline_enabled: full_mode
                 && ProjectSettings::get_global(cx).git.inline_blame_enabled(),
             render_diff_hunk_controls: Arc::new(render_diff_hunk_controls),
+            diff_hunk_controls_above: true,
             serialize_dirty_buffers: !is_minimap
                 && ProjectSettings::get_global(cx)
                     .session
@@ -23641,6 +23643,12 @@ struct LineManipulationResult {
     pub line_count_after: usize,
 }
 
+impl Editor {
+    pub fn diff_hunk_controls_above(&self) -> bool {
+        self.diff_hunk_controls_above
+    }
+}
+
 fn render_diff_hunk_controls(
     row: u32,
     status: &DiffHunkStatus,
@@ -23651,20 +23659,28 @@ fn render_diff_hunk_controls(
     _window: &mut Window,
     cx: &mut App,
 ) -> AnyElement {
-    h_flex()
+    // Get controls positioning from editor state
+    let controls_above = editor.read(cx).diff_hunk_controls_above();
+    let mut container = h_flex()
         .h(line_height)
         .mr_1()
         .gap_1()
         .px_0p5()
         .py_0p5()
         .border_x_1()
-        .border_t_1()
         .border_color(cx.theme().colors().border_variant)
-        .rounded_t_lg()
         .bg(cx.theme().colors().editor_background)
         .gap_1()
         .block_mouse_except_scroll()
-        .shadow_md()
+        .shadow_md();
+
+    if controls_above {
+        container = container.border_t_1().rounded_t_lg();
+    } else {
+        container = container.border_b_1().rounded_b_lg();
+    }
+
+    container
         .child(if status.has_secondary_hunk() {
             Button::new(("stage", row as u64), "Stage")
                 .size(ButtonSize::Compact)

crates/editor/src/element.rs 🔗

@@ -4985,10 +4985,18 @@ impl EditorElement {
                     .iter()
                     .any(|p| p.map_or(false, |p| display_row_range.contains(&p.row())))
                 {
-                    // Position controls at the end of the previous line to avoid covering diff content
-                    let control_row = if display_row_range.start.0 > 0 {
-                        display_row_range.start.0 - 1
+                    // Get controls positioning from editor state
+                    let controls_above = editor.read(cx).diff_hunk_controls_above();
+
+                    let control_row = if controls_above {
+                        // Position controls one line above the diff hunk to avoid covering diff content
+                        if display_row_range.start.0 > 0 {
+                            display_row_range.start.0 - 1
+                        } else {
+                            display_row_range.start.0
+                        }
                     } else {
+                        // Position controls at the start of the diff hunk (original behavior)
                         display_row_range.start.0
                     };
                     let y = control_row as f32 * line_height + text_hitbox.bounds.top()