fix(git): wire branch-picker merge-mode cancel + Escape

Merge mode had no exit: Escape was gated on branch_create_focused (false
in merge mode) and the painted 取消 hint was inert. Now:

- Escape is mode-based (branch_picker_open && mode != List → List), so it
  steps both create AND merge sub-modes back to the branch list
- new GitPanelHit::BranchPickerCancel: in merge mode a click anywhere but a
  branch row (incl. the 取消 hint) returns to the list
This commit is contained in:
Kayshen-X 2026-05-31 21:05:25 +08:00
parent c81c36da8e
commit 1ef8c45f37
4 changed files with 31 additions and 4 deletions

View file

@ -117,6 +117,8 @@ pub enum GitPanelHit {
BranchCreateInput,
/// The inline create-branch submit button — create + switch.
BranchCreateSubmit,
/// Cancel a create / merge sub-mode — return to the branch list.
BranchPickerCancel,
/// The Remotes-section URL input box — focus it.
RemoteInput,
/// The Remotes-section "Set origin" button.

View file

@ -228,12 +228,23 @@ impl GitPanel<'_> {
let bi = if merging { candidates[i] } else { i };
let is_current = self.state.branches.get(bi) == self.state.branch.as_ref();
let name = truncate(
self.state.branches.get(bi).map(String::as_str).unwrap_or(""),
self.state
.branches
.get(bi)
.map(String::as_str)
.unwrap_or(""),
BRANCH_NAME_MAX,
);
// Line 1 — branch name (always foreground; current branch is
// signalled by the check, not by colour).
self.text(cx, &name, row.origin.x + 10.0, row.origin.y + 16.0, 12.0, t.foreground);
self.text(
cx,
&name,
row.origin.x + 10.0,
row.origin.y + 16.0,
12.0,
t.foreground,
);
// Line 2 — last-commit subtitle (only the current branch's HEAD
// commit is known here; others fall back to the no-commits label).
let subtitle = if is_current {
@ -361,7 +372,9 @@ impl GitPanel<'_> {
return Some(GitPanelHit::MergeBranch(candidates[i]));
}
}
Some(GitPanelHit::Inside)
// A click anywhere else in the popover (including the 取消
// hint) cancels merge mode back to the branch list.
Some(GitPanelHit::BranchPickerCancel)
}
GitBranchPickerMode::List => {
for (i, row) in self.branch_picker_row_rects(panel_rect).iter().enumerate() {

View file

@ -240,6 +240,12 @@ impl WidgetHostNative {
panel.branch_picker_open = false;
}
}
Some(GitPanelHit::BranchPickerCancel) => {
// Step a create / merge sub-mode back to the branch list.
panel.branch_picker_mode = GitBranchPickerMode::List;
panel.branch_create_draft.clear();
panel.branch_create_focused = false;
}
Some(GitPanelHit::ShowWorkingDiff) => {
panel.pending_action = Some(GitPanelAction::ShowDiff(GitDiffTarget::WorkingTree));
}

View file

@ -747,7 +747,13 @@ impl WidgetHostNative {
self.mark_dirty();
return true;
}
if self.git_branch_create_focus_active() {
// …and a branch-picker sub-mode (create / merge): Escape steps it
// back to the branch list (the dropdown stays open). Driven off the
// mode, not input focus, so merge mode (no focused input) exits too.
if self.editor_state.editor_ui.git_panel.branch_picker_open
&& self.editor_state.editor_ui.git_panel.branch_picker_mode
!= op_editor_core::GitBranchPickerMode::List
{
let panel = &mut self.editor_state.editor_ui.git_panel;
panel.branch_picker_mode = op_editor_core::GitBranchPickerMode::List;
panel.branch_create_draft.clear();