agent_ui: Insert branch diff crease when clicking on menu item (#51509)

Danilo Leal created

Follow up to https://github.com/zed-industries/zed/pull/51487

The PR above added the item to the menu, and this one makes the menu
item actually insert a mention crease with the branch diff. That was
missing in the previous one.

Release Notes:

- N/A

Change summary

crates/agent_ui/src/connection_view/thread_view.rs |  3 
crates/agent_ui/src/mention_set.rs                 |  2 
crates/agent_ui/src/message_editor.rs              | 82 ++++++++++++++++
3 files changed, 84 insertions(+), 3 deletions(-)

Detailed changes

crates/agent_ui/src/connection_view/thread_view.rs 🔗

@@ -3681,9 +3681,8 @@ impl ThreadView {
                         .disabled(!supports_embedded_context)
                         .handler({
                             move |window, cx| {
-                                message_editor.focus_handle(cx).focus(window, cx);
                                 message_editor.update(cx, |editor, cx| {
-                                    editor.insert_context_type("diff", window, cx);
+                                    editor.insert_branch_diff_crease(window, cx);
                                 });
                             }
                         }),

crates/agent_ui/src/mention_set.rs 🔗

@@ -604,7 +604,7 @@ impl MentionSet {
         })
     }
 
-    fn confirm_mention_for_git_diff(
+    pub fn confirm_mention_for_git_diff(
         &self,
         base_ref: SharedString,
         cx: &mut Context<Self>,

crates/agent_ui/src/message_editor.rs 🔗

@@ -1041,6 +1041,88 @@ impl MessageEditor {
         });
     }
 
+    pub fn insert_branch_diff_crease(&mut self, window: &mut Window, cx: &mut Context<Self>) {
+        let Some(workspace) = self.workspace.upgrade() else {
+            return;
+        };
+
+        let project = workspace.read(cx).project().clone();
+
+        let Some(repo) = project.read(cx).active_repository(cx) else {
+            return;
+        };
+
+        let default_branch_receiver = repo.update(cx, |repo, _| repo.default_branch(false));
+        let editor = self.editor.clone();
+        let mention_set = self.mention_set.clone();
+        let weak_workspace = self.workspace.clone();
+
+        window
+            .spawn(cx, async move |cx| {
+                let base_ref: SharedString = default_branch_receiver
+                    .await
+                    .ok()
+                    .and_then(|r| r.ok())
+                    .flatten()
+                    .ok_or_else(|| anyhow!("Could not determine default branch"))?;
+
+                cx.update(|window, cx| {
+                    let mention_uri = MentionUri::GitDiff {
+                        base_ref: base_ref.to_string(),
+                    };
+                    let mention_text = mention_uri.as_link().to_string();
+
+                    let (excerpt_id, text_anchor, content_len) = editor.update(cx, |editor, cx| {
+                        let buffer = editor.buffer().read(cx);
+                        let snapshot = buffer.snapshot(cx);
+                        let (excerpt_id, _, buffer_snapshot) = snapshot.as_singleton().unwrap();
+                        let text_anchor = editor
+                            .selections
+                            .newest_anchor()
+                            .start
+                            .text_anchor
+                            .bias_left(&buffer_snapshot);
+
+                        editor.insert(&mention_text, window, cx);
+                        editor.insert(" ", window, cx);
+
+                        (excerpt_id, text_anchor, mention_text.len())
+                    });
+
+                    let Some((crease_id, tx)) = insert_crease_for_mention(
+                        excerpt_id,
+                        text_anchor,
+                        content_len,
+                        mention_uri.name().into(),
+                        mention_uri.icon_path(cx),
+                        mention_uri.tooltip_text(),
+                        Some(mention_uri.clone()),
+                        Some(weak_workspace),
+                        None,
+                        editor,
+                        window,
+                        cx,
+                    ) else {
+                        return;
+                    };
+                    drop(tx);
+
+                    let confirm_task = mention_set.update(cx, |mention_set, cx| {
+                        mention_set.confirm_mention_for_git_diff(base_ref, cx)
+                    });
+
+                    let mention_task = cx
+                        .spawn(async move |_cx| confirm_task.await.map_err(|e| e.to_string()))
+                        .shared();
+
+                    mention_set.update(cx, |mention_set, _| {
+                        mention_set.insert_mention(crease_id, mention_uri, mention_task);
+                    });
+                })
+            })
+            .detach_and_log_err(cx);
+    }
+
     fn insert_crease_impl(
         &mut self,
         text: String,