From 1ef8c45f373ebeb0e95d614849ceff0202ff17d6 Mon Sep 17 00:00:00 2001 From: Kayshen-X Date: Sun, 31 May 2026 21:05:25 +0800 Subject: [PATCH] fix(git): wire branch-picker merge-mode cancel + Escape MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- crates/op-editor-ui/src/widgets/git_panel.rs | 2 ++ .../src/widgets/git_panel_menus.rs | 19 ++++++++++++++++--- .../src/widget_host/git_press.rs | 6 ++++++ .../src/widget_host/keyboard.rs | 8 +++++++- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/crates/op-editor-ui/src/widgets/git_panel.rs b/crates/op-editor-ui/src/widgets/git_panel.rs index 23cdd5d29..19b358ec9 100644 --- a/crates/op-editor-ui/src/widgets/git_panel.rs +++ b/crates/op-editor-ui/src/widgets/git_panel.rs @@ -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. diff --git a/crates/op-editor-ui/src/widgets/git_panel_menus.rs b/crates/op-editor-ui/src/widgets/git_panel_menus.rs index 7b68d77cb..fb3050be2 100644 --- a/crates/op-editor-ui/src/widgets/git_panel_menus.rs +++ b/crates/op-editor-ui/src/widgets/git_panel_menus.rs @@ -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() { diff --git a/crates/op-host-native/src/widget_host/git_press.rs b/crates/op-host-native/src/widget_host/git_press.rs index 67ac62e27..ec922ab17 100644 --- a/crates/op-host-native/src/widget_host/git_press.rs +++ b/crates/op-host-native/src/widget_host/git_press.rs @@ -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)); } diff --git a/crates/op-host-native/src/widget_host/keyboard.rs b/crates/op-host-native/src/widget_host/keyboard.rs index 9381f6b7e..6e2be85aa 100644 --- a/crates/op-host-native/src/widget_host/keyboard.rs +++ b/crates/op-host-native/src/widget_host/keyboard.rs @@ -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();