Compare commits

...

4 Commits

Author SHA1 Message Date
canvrno-oai
fbba491779 Merge branch 'main' into canvrno/simple_pop_all 2026-04-16 10:57:12 -07:00
canvrno-oai
5494e6cf7b Add two additon pop all calls to /review feature 2026-04-15 20:55:51 -07:00
canvrno-oai
d8e9eab3d1 Add regression test for pop all scenario 2026-04-15 20:55:51 -07:00
canvrno-oai
e969be67c1 Add simple pop-all overlay flow 2026-04-15 20:55:51 -07:00
5 changed files with 86 additions and 0 deletions

View File

@@ -5701,6 +5701,9 @@ impl App {
AppEvent::OpenReviewCustomPrompt => {
self.chat_widget.show_review_custom_prompt();
}
AppEvent::DismissAllBottomPaneViews => {
self.chat_widget.dismiss_all_bottom_pane_views();
}
AppEvent::SubmitUserMessageWithMode {
text,
collaboration_mode,

View File

@@ -553,6 +553,9 @@ pub(crate) enum AppEvent {
/// Open the custom prompt option from the review popup.
OpenReviewCustomPrompt,
/// Dismiss all active bottom-pane views.
DismissAllBottomPaneViews,
/// Submit a user message with an explicit collaboration mask.
SubmitUserMessageWithMode {
text: String,

View File

@@ -404,6 +404,12 @@ impl BottomPane {
}
}
pub(crate) fn pop_all_views(&mut self) {
while !self.view_stack.is_empty() {
self.pop_active_view();
}
}
fn on_view_stack_depth_decreased(&mut self) {
if self.view_stack.is_empty() {
self.on_active_view_complete();

View File

@@ -5221,6 +5221,11 @@ impl ChatWidget {
self.request_redraw();
}
pub(crate) fn dismiss_all_bottom_pane_views(&mut self) {
self.bottom_pane.pop_all_views();
self.request_redraw();
}
pub(crate) fn no_modal_or_popup_active(&self) -> bool {
self.bottom_pane.no_modal_or_popup_active()
}
@@ -10543,6 +10548,7 @@ impl ChatWidget {
},
user_facing_hint: None,
});
tx3.send(AppEvent::DismissAllBottomPaneViews);
})],
dismiss_on_select: true,
search_value: Some(option),
@@ -10579,6 +10585,7 @@ impl ChatWidget {
},
user_facing_hint: None,
});
tx3.send(AppEvent::DismissAllBottomPaneViews);
})],
dismiss_on_select: true,
search_value: Some(search_val),
@@ -10614,6 +10621,7 @@ impl ChatWidget {
},
user_facing_hint: None,
});
tx.send(AppEvent::DismissAllBottomPaneViews);
}),
);
self.bottom_pane.show_view(Box::new(view));

View File

@@ -1327,6 +1327,72 @@ async fn review_branch_picker_escape_navigates_back_then_dismisses() {
);
}
#[tokio::test]
async fn review_branch_picker_submit_dismisses_parent_review_popup() {
use std::process::Command;
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
let repo = tempdir().expect("tempdir");
let run_git = |args: &[&str]| {
let status = Command::new("git")
.args(args)
.current_dir(repo.path())
.status()
.expect("run git");
assert!(status.success(), "git command failed: {args:?}");
};
run_git(&["init"]);
run_git(&["config", "user.name", "Codex Test"]);
run_git(&["config", "user.email", "codex-tests@example.com"]);
std::fs::write(repo.path().join("tracked.txt"), "tracked\n").expect("write tracked file");
run_git(&["add", "tracked.txt"]);
run_git(&["commit", "-m", "init"]);
run_git(&["checkout", "-b", "review-work"]);
run_git(&["branch", "review-base"]);
chat.open_review_popup();
chat.show_review_branch_picker(repo.path()).await;
let header = render_bottom_first_row(&chat, /*width*/ 60);
assert!(
header.contains("Select a base branch"),
"expected branch picker header: {header:?}"
);
chat.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE));
let review_event = rx.try_recv().expect("expected review event");
match review_event {
AppEvent::CodexOp(Op::Review { review_request }) => {
assert!(
matches!(
review_request.target,
ReviewTarget::BaseBranch { ref branch } if !branch.is_empty()
),
"expected base-branch review request, got {review_request:?}"
);
}
other => panic!("unexpected first app event: {other:?}"),
}
let dismiss_event = rx.try_recv().expect("expected dismiss-all event");
assert!(
matches!(dismiss_event, AppEvent::DismissAllBottomPaneViews),
"unexpected second app event: {dismiss_event:?}"
);
// Simulate the app loop consuming the dismissal request after the picker
// submits its review operation.
chat.dismiss_all_bottom_pane_views();
assert!(
chat.is_normal_backtrack_mode(),
"expected branch submit to dismiss the full review popup stack"
);
}
#[tokio::test]
async fn review_ended_keeps_unified_exec_processes() {
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;