From b068f0b00daea047e65b587e83a03a2d16345305 Mon Sep 17 00:00:00 2001 From: dhruvac29 Date: Thu, 30 Apr 2026 11:27:44 -0700 Subject: [PATCH 1/2] Mark imported comments added to code review --- app/src/ai/blocklist/block.rs | 72 ++++++++++++++++++++++++++--- app/src/ai/blocklist/block_tests.rs | 48 ++++++++++++++++++- app/src/terminal/view.rs | 22 +++++++-- 3 files changed, 130 insertions(+), 12 deletions(-) diff --git a/app/src/ai/blocklist/block.rs b/app/src/ai/blocklist/block.rs index f3a1fdb2f..4da1a3c8a 100644 --- a/app/src/ai/blocklist/block.rs +++ b/app/src/ai/blocklist/block.rs @@ -526,6 +526,7 @@ pub(super) struct ImportedCommentElementState { pub(super) open_in_code_review_button: ViewHandle, pub(super) chevron_button: ViewHandle, pub(super) header_click_handler: HeaderClickHandler, + added_to_code_review: bool, } impl ImportedCommentElementState { @@ -585,8 +586,52 @@ impl ImportedCommentElementState { open_in_code_review_button, chevron_button, header_click_handler, + added_to_code_review: false, } } + + fn mark_added_to_code_review(&mut self, ctx: &mut ViewContext) { + self.added_to_code_review = true; + self.update_open_in_code_review_button(false, None, ctx); + } + + fn open_in_code_review_button_state( + added_to_code_review: bool, + should_disable_for_repo: bool, + repo_path: Option<&Path>, + ) -> (&'static str, bool, Option) { + if added_to_code_review { + return ("Added to code review", true, None); + } + + let tooltip = should_disable_for_repo.then(|| { + repo_path.map(|path| format!("Navigate to {} to open these comments", path.display())) + }); + + ( + "Open in code review", + should_disable_for_repo, + tooltip.flatten(), + ) + } + + fn update_open_in_code_review_button( + &self, + should_disable_for_repo: bool, + repo_path: Option<&Path>, + ctx: &mut ViewContext, + ) { + let (label, disabled, tooltip) = Self::open_in_code_review_button_state( + self.added_to_code_review, + should_disable_for_repo, + repo_path, + ); + self.open_in_code_review_button.update(ctx, |button, ctx| { + button.set_label(label, ctx); + button.set_disabled(disabled, ctx); + button.set_tooltip(tooltip, ctx); + }); + } } pub(super) struct ImportedCommentGroup { @@ -617,12 +662,13 @@ impl ImportedCommentGroup { fn set_buttons_disabled(&self, should_disable: bool, ctx: &mut ViewContext) { for state in &self.element_states { - set_imported_comment_button_disabled( - &state.open_in_code_review_button, - should_disable, - Some(&self.repo_path), - ctx, - ); + state.update_open_in_code_review_button(should_disable, Some(&self.repo_path), ctx); + } + } + + fn mark_comments_added_to_code_review(&mut self, ctx: &mut ViewContext) { + for state in &mut self.element_states { + state.mark_added_to_code_review(ctx); } } } @@ -5256,6 +5302,15 @@ impl AIBlock { }) } + pub(crate) fn mark_imported_comments_added_to_code_review( + &mut self, + ctx: &mut ViewContext, + ) { + for group in self.imported_comments.values_mut() { + group.mark_comments_added_to_code_review(ctx); + } + } + /// Returns `true` if this block has any imported review comments. pub(crate) fn has_any_imported_comments(&self) -> bool { self.has_imported_comments @@ -6287,12 +6342,15 @@ impl TypedActionView for AIBlock { if let Some(group) = self.imported_comments.get_mut(action_id) { let repo_path = group.repo_path.clone(); let base_branch = group.base_branch.clone(); - if let Some(card) = group.card_mut(*comment_index) { + if let Some(card) = group.cards.get(*comment_index) { ctx.emit(AIBlockEvent::OpenImportedCommentInCodeReview { repo_path, comment: Box::new(card.source().clone()), base_branch, }); + if let Some(state) = group.element_states.get_mut(*comment_index) { + state.mark_added_to_code_review(ctx); + } } } } diff --git a/app/src/ai/blocklist/block_tests.rs b/app/src/ai/blocklist/block_tests.rs index d12ab1bdf..e553df186 100644 --- a/app/src/ai/blocklist/block_tests.rs +++ b/app/src/ai/blocklist/block_tests.rs @@ -1,7 +1,8 @@ -use super::{CollapsibleElementState, CollapsibleExpansionState}; +use super::{CollapsibleElementState, CollapsibleExpansionState, ImportedCommentElementState}; use crate::settings::AISettings; use crate::test_util::settings::initialize_settings_for_tests; use settings::Setting; +use std::path::Path; use warpui::{App, SingletonEntity}; #[test] @@ -85,3 +86,48 @@ fn manual_reexpand_while_streaming_stays_expanded_after_finish() { )); }); } + +#[test] +fn imported_comment_code_review_button_is_enabled_without_repo_disable() { + let (label, disabled, tooltip) = + ImportedCommentElementState::open_in_code_review_button_state(false, false, None); + + assert_eq!(label, "Open in code review"); + assert!(!disabled); + assert_eq!(tooltip, None); +} + +#[test] +fn imported_comment_code_review_button_uses_repo_tooltip_when_repo_disabled() { + let repo_path = Path::new("/tmp/repo"); + let (label, disabled, tooltip) = + ImportedCommentElementState::open_in_code_review_button_state(false, true, Some(repo_path)); + + assert_eq!(label, "Open in code review"); + assert!(disabled); + assert_eq!( + tooltip, + Some("Navigate to /tmp/repo to open these comments".to_string()) + ); +} + +#[test] +fn imported_comment_code_review_button_handles_repo_disable_without_path() { + let (label, disabled, tooltip) = + ImportedCommentElementState::open_in_code_review_button_state(false, true, None); + + assert_eq!(label, "Open in code review"); + assert!(disabled); + assert_eq!(tooltip, None); +} + +#[test] +fn imported_comment_code_review_button_prefers_added_state_over_repo_disable() { + let repo_path = Path::new("/tmp/repo"); + let (label, disabled, tooltip) = + ImportedCommentElementState::open_in_code_review_button_state(true, true, Some(repo_path)); + + assert_eq!(label, "Added to code review"); + assert!(disabled); + assert_eq!(tooltip, None); +} diff --git a/app/src/terminal/view.rs b/app/src/terminal/view.rs index bb1cdcd75..7325d9369 100644 --- a/app/src/terminal/view.rs +++ b/app/src/terminal/view.rs @@ -19006,7 +19006,8 @@ impl TerminalView { }); } AIBlockEvent::OpenAllImportedCommentsForConversation { conversation_id } => { - let (all_comments, base_branch) = self.all_comments_in_thread(conversation_id, ctx); + let (all_comments, base_branch, source_blocks) = + self.all_comments_in_thread(conversation_id, ctx); if !all_comments.is_empty() { let diff_mode = self.diff_mode_for_branch(base_branch.as_deref(), ctx); ctx.emit(Event::ImportAllCodeReviewComments { @@ -19014,6 +19015,11 @@ impl TerminalView { comments: all_comments, diff_mode, }); + for source_block in source_blocks { + source_block.update(ctx, |block, ctx| { + block.mark_imported_comments_added_to_code_review(ctx); + }); + } } } AIBlockEvent::OpenAIDocumentPane { @@ -19114,20 +19120,28 @@ impl TerminalView { &self, conversation_id: &AIConversationId, ctx: &AppContext, - ) -> (Vec, Option) { + ) -> ( + Vec, + Option, + Vec>, + ) { let mut all_comments = Vec::new(); let mut base_branch = None; - for ai_block in self.ai_blocks_for_current_thread(conversation_id, ctx) { + let mut source_blocks = Vec::new(); + for ai_metadata in self.ai_block_metadata_for_current_thread(conversation_id, ctx) { + let ai_block = ai_metadata.ai_block_handle.as_ref(ctx); if let Some(imported) = ai_block.collect_imported_comments() { all_comments.extend(imported.comments); if base_branch.is_none() { base_branch = imported.base_branch; } + source_blocks.push(ai_metadata.ai_block_handle.clone()); } } // The iterator yields blocks newest-first; reverse to get chronological order. all_comments.reverse(); - (all_comments, base_branch) + source_blocks.reverse(); + (all_comments, base_branch, source_blocks) } /// Returns `true` if any block in the current thread of the given conversation has imported From 86e97a04bc38e95c5520e3838e3c71bb364f9cca Mon Sep 17 00:00:00 2001 From: Dhruvilkumar Ashokbhai Chodvadiya <50516925+dhruvac29@users.noreply.github.com> Date: Thu, 30 Apr 2026 12:57:51 -0700 Subject: [PATCH 2/2] Make imported comment tooltip test platform-neutral Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- app/src/ai/blocklist/block_tests.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/ai/blocklist/block_tests.rs b/app/src/ai/blocklist/block_tests.rs index e553df186..9e5d5e6d0 100644 --- a/app/src/ai/blocklist/block_tests.rs +++ b/app/src/ai/blocklist/block_tests.rs @@ -107,7 +107,10 @@ fn imported_comment_code_review_button_uses_repo_tooltip_when_repo_disabled() { assert!(disabled); assert_eq!( tooltip, - Some("Navigate to /tmp/repo to open these comments".to_string()) + Some(format!( + "Navigate to {} to open these comments", + repo_path.display() + )) ); }