Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 65 additions & 7 deletions app/src/ai/blocklist/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,7 @@ pub(super) struct ImportedCommentElementState {
pub(super) open_in_code_review_button: ViewHandle<ActionButton>,
pub(super) chevron_button: ViewHandle<ActionButton>,
pub(super) header_click_handler: HeaderClickHandler,
added_to_code_review: bool,
}

impl ImportedCommentElementState {
Expand Down Expand Up @@ -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<AIBlock>) {
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<String>) {
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<AIBlock>,
) {
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);
});
}
}

Comment thread
dhruvac29 marked this conversation as resolved.
pub(super) struct ImportedCommentGroup {
Expand Down Expand Up @@ -617,12 +662,13 @@ impl ImportedCommentGroup {

fn set_buttons_disabled(&self, should_disable: bool, ctx: &mut ViewContext<AIBlock>) {
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<AIBlock>) {
for state in &mut self.element_states {
state.mark_added_to_code_review(ctx);
}
}
}
Expand Down Expand Up @@ -5256,6 +5302,15 @@ impl AIBlock {
})
}

pub(crate) fn mark_imported_comments_added_to_code_review(
&mut self,
ctx: &mut ViewContext<Self>,
) {
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
Expand Down Expand Up @@ -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);
}
Comment thread
dhruvac29 marked this conversation as resolved.
}
}
}
Expand Down
51 changes: 50 additions & 1 deletion app/src/ai/blocklist/block_tests.rs
Original file line number Diff line number Diff line change
@@ -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]
Expand Down Expand Up @@ -85,3 +86,51 @@ 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(format!(
"Navigate to {} to open these comments",
repo_path.display()
))
);
}

#[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);
}
22 changes: 18 additions & 4 deletions app/src/terminal/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19006,14 +19006,20 @@ 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 {
open_code_review: self.imported_comments_panel_arg(),
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 {
Expand Down Expand Up @@ -19114,20 +19120,28 @@ impl TerminalView {
&self,
conversation_id: &AIConversationId,
ctx: &AppContext,
) -> (Vec<AttachedReviewComment>, Option<String>) {
) -> (
Vec<AttachedReviewComment>,
Option<String>,
Vec<ViewHandle<AIBlock>>,
) {
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
Expand Down