Diff review comments: store locally and batch submit to agent (#46669)
Doesn't support editing or deleting comments yet, but inputs work: <img width="797" height="881" alt="Screenshot 2026-01-14 at 11 51 36 AM" src="https://github.com/user-attachments/assets/746e085b-a919-475a-b804-ee0377e40a0b" /> <img width="698" height="178" alt="Screenshot 2026-01-14 at 11 47 51 AM" src="https://github.com/user-attachments/assets/3edac0e8-62e5-4af5-a324-df2bd293f3ca" /> <img width="695" height="695" alt="Screenshot 2026-01-14 at 11 47 58 AM" src="https://github.com/user-attachments/assets/64795ffd-62b4-48ea-a46c-7724221095d7" /> ### Features implemented: - **Local comment storage**: Comments are stored per-hunk in the Editor, with chronological ordering - **Expandable comments section**: Shows "N Comments" header that can expand/collapse - **Inline editing**: Click edit to transform a comment row into an editable text field with confirm/cancel buttons - **Delete functionality**: Remove individual comments - **Send Review to Agent**: Toolbar button with badge showing comment count, batch-submits all comments across all files/hunks to the Agent panel - **User avatars**: Shows the current user's avatar (from their Zed account) next to comments, falls back to Person icon when not logged in - **Visual tests**: Added tests for one comment, multiple comments expanded, and comments collapsed Note that this is behind a feature flag, so no release notes yet. Release Notes: - N/A --------- Co-authored-by: Zed Zippy <234243425+zed-zippy[bot]@users.noreply.github.com> Co-authored-by: David Baldwin <baldwindavid@gmail.com>
This commit is contained in:
10 files changed
+2491
-42
No files matched your search
@@ -9,7 +9,7 @@ use buffer_diff::{BufferDiff, DiffHunkSecondaryStatus};
|
||||
use collections::{HashMap, HashSet};
|
||||
use editor::{
|
||||
Addon, Editor, EditorEvent, SelectionEffects, SplittableEditor,
|
||||
actions::{GoToHunk, GoToPreviousHunk},
|
||||
actions::{GoToHunk, GoToPreviousHunk, SendReviewToAgent},
|
||||
multibuffer_context_lines,
|
||||
scroll::Autoscroll,
|
||||
};
|
||||
@@ -70,6 +70,7 @@ pub struct ProjectDiff {
|
||||
workspace: WeakEntity<Workspace>,
|
||||
focus_handle: FocusHandle,
|
||||
pending_scroll: Option<PathKey>,
|
||||
review_comment_count: usize,
|
||||
_task: Task<Result<()>>,
|
||||
_subscription: Subscription,
|
||||
}
|
||||
@@ -311,8 +312,16 @@ impl ProjectDiff {
|
||||
});
|
||||
diff_display_editor
|
||||
});
|
||||
cx.subscribe_in(&editor, window, Self::handle_editor_event)
|
||||
.detach();
|
||||
let editor_subscription = cx.subscribe_in(&editor, window, Self::handle_editor_event);
|
||||
|
||||
let primary_editor = editor.read(cx).primary_editor().clone();
|
||||
let review_comment_subscription =
|
||||
cx.subscribe(&primary_editor, |this, _editor, event: &EditorEvent, cx| {
|
||||
if let EditorEvent::ReviewCommentsChanged { total_count } = event {
|
||||
this.review_comment_count = *total_count;
|
||||
cx.notify();
|
||||
}
|
||||
});
|
||||
|
||||
let branch_diff_subscription = cx.subscribe_in(
|
||||
&branch_diff,
|
||||
@@ -363,8 +372,12 @@ impl ProjectDiff {
|
||||
multibuffer,
|
||||
buffer_diff_subscriptions: Default::default(),
|
||||
pending_scroll: None,
|
||||
review_comment_count: 0,
|
||||
_task: task,
|
||||
_subscription: branch_diff_subscription,
|
||||
_subscription: Subscription::join(
|
||||
branch_diff_subscription,
|
||||
Subscription::join(editor_subscription, review_comment_subscription),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,6 +466,16 @@ impl ProjectDiff {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the total count of review comments across all hunks/files.
|
||||
pub fn total_review_comment_count(&self) -> usize {
|
||||
self.review_comment_count
|
||||
}
|
||||
|
||||
/// Returns a reference to the splittable editor.
|
||||
pub fn editor(&self) -> &Entity<SplittableEditor> {
|
||||
&self.editor
|
||||
}
|
||||
|
||||
fn button_states(&self, cx: &App) -> ButtonStates {
|
||||
let editor = self.editor.read(cx).primary_editor().read(cx);
|
||||
let snapshot = self.multibuffer.read(cx).snapshot(cx);
|
||||
@@ -1278,6 +1301,7 @@ impl Render for ProjectDiffToolbar {
|
||||
};
|
||||
let focus_handle = project_diff.focus_handle(cx);
|
||||
let button_states = project_diff.read(cx).button_states(cx);
|
||||
let review_count = project_diff.read(cx).total_review_comment_count();
|
||||
|
||||
h_group_xl()
|
||||
.my_neg_1()
|
||||
@@ -1419,6 +1443,25 @@ impl Render for ProjectDiffToolbar {
|
||||
})),
|
||||
),
|
||||
)
|
||||
// "Send Review to Agent" button (only shown when there are review comments)
|
||||
.when(review_count > 0, |el| {
|
||||
el.child(vertical_divider()).child(
|
||||
Button::new(
|
||||
"send-review",
|
||||
format!("Send Review to Agent ({})", review_count),
|
||||
)
|
||||
.icon(IconName::ZedAssistant)
|
||||
.icon_position(IconPosition::Start)
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Send all review comments to the Agent panel",
|
||||
&SendReviewToAgent,
|
||||
&focus_handle,
|
||||
))
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_action(&SendReviewToAgent, window, cx)
|
||||
})),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user