fix: Disable global keybinds when confirmation is active (#4284)

- **PR Description**

Adds a guard around all global keybinds except for quitting the
application when a popup window is active. Users must now confirm, or
cancel, the popup prior to taking other action. This fixes
https://github.com/jesseduffield/lazygit/issues/4052, and will also
prevent other such confusing cases where popups are created, but never
removed.
This commit is contained in:
Stefan Haller 2025-02-23 08:47:37 +01:00 committed by GitHub
commit 1e05055fff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 22 additions and 48 deletions

View file

@ -36,25 +36,25 @@ func (self *GlobalController) GetKeybindings(opts types.KeybindingsOpts) []*type
},
{
Key: opts.GetKey(opts.Config.Universal.CreateRebaseOptionsMenu),
Handler: self.c.Helpers().MergeAndRebase.CreateRebaseOptionsMenu,
Handler: opts.Guards.NoPopupPanel(self.c.Helpers().MergeAndRebase.CreateRebaseOptionsMenu),
Description: self.c.Tr.ViewMergeRebaseOptions,
Tooltip: self.c.Tr.ViewMergeRebaseOptionsTooltip,
OpensMenu: true,
},
{
Key: opts.GetKey(opts.Config.Universal.Refresh),
Handler: self.refresh,
Handler: opts.Guards.NoPopupPanel(self.refresh),
Description: self.c.Tr.Refresh,
Tooltip: self.c.Tr.RefreshTooltip,
},
{
Key: opts.GetKey(opts.Config.Universal.NextScreenMode),
Handler: self.nextScreenMode,
Handler: opts.Guards.NoPopupPanel(self.nextScreenMode),
Description: self.c.Tr.NextScreenMode,
},
{
Key: opts.GetKey(opts.Config.Universal.PrevScreenMode),
Handler: self.prevScreenMode,
Handler: opts.Guards.NoPopupPanel(self.prevScreenMode),
Description: self.c.Tr.PrevScreenMode,
},
{
@ -78,21 +78,21 @@ func (self *GlobalController) GetKeybindings(opts types.KeybindingsOpts) []*type
{
ViewName: "",
Key: opts.GetKey(opts.Config.Universal.FilteringMenu),
Handler: self.createFilteringMenu,
Handler: opts.Guards.NoPopupPanel(self.createFilteringMenu),
Description: self.c.Tr.OpenFilteringMenu,
Tooltip: self.c.Tr.OpenFilteringMenuTooltip,
OpensMenu: true,
},
{
Key: opts.GetKey(opts.Config.Universal.DiffingMenu),
Handler: self.createDiffingMenu,
Handler: opts.Guards.NoPopupPanel(self.createDiffingMenu),
Description: self.c.Tr.ViewDiffingOptions,
Tooltip: self.c.Tr.ViewDiffingOptionsTooltip,
OpensMenu: true,
},
{
Key: opts.GetKey(opts.Config.Universal.DiffingMenuAlt),
Handler: self.createDiffingMenu,
Handler: opts.Guards.NoPopupPanel(self.createDiffingMenu),
Description: self.c.Tr.ViewDiffingOptions,
Tooltip: self.c.Tr.ViewDiffingOptionsTooltip,
OpensMenu: true,

View file

@ -42,7 +42,7 @@ func (self *JumpToSideWindowController) GetKeybindings(opts types.KeybindingsOpt
// by default the keys are 1, 2, 3, etc
Key: opts.GetKey(opts.Config.Universal.JumpToBlock[index]),
Modifier: gocui.ModNone,
Handler: self.goToSideWindow(window),
Handler: opts.Guards.NoPopupPanel(self.goToSideWindow(window)),
}
})
}

View file

@ -1012,9 +1012,16 @@ func (gui *Gui) showIntroPopupMessage() {
return err
}
introMessage := utils.ResolvePlaceholderString(
gui.c.Tr.IntroPopupMessage,
map[string]string{
"confirmationKey": gui.c.UserConfig().Keybinding.Universal.Confirm,
},
)
gui.c.Confirm(types.ConfirmOpts{
Title: "",
Prompt: gui.c.Tr.IntroPopupMessage,
Prompt: introMessage,
HandleConfirm: onConfirm,
HandleClose: onConfirm,
})

View file

@ -83,7 +83,7 @@ func (self *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBi
{
ViewName: "",
Key: opts.GetKey(opts.Config.Universal.OpenRecentRepos),
Handler: self.helpers.Repos.CreateRecentReposMenu,
Handler: opts.Guards.NoPopupPanel(self.helpers.Repos.CreateRecentReposMenu),
Description: self.c.Tr.SwitchRepo,
},
{
@ -195,7 +195,7 @@ func (self *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBi
{
ViewName: "",
Key: opts.GetKey(opts.Config.Universal.ExtrasMenu),
Handler: self.handleCreateExtrasMenuPanel,
Handler: opts.Guards.NoPopupPanel(self.handleCreateExtrasMenuPanel),
Description: self.c.Tr.OpenCommandLogMenu,
Tooltip: self.c.Tr.OpenCommandLogMenuTooltip,
OpensMenu: true,
@ -330,14 +330,14 @@ func (self *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBi
{
ViewName: "",
Key: opts.GetKey(opts.Config.Universal.NextTab),
Handler: self.handleNextTab,
Handler: opts.Guards.NoPopupPanel(self.handleNextTab),
Description: self.c.Tr.NextTab,
Tag: "navigation",
},
{
ViewName: "",
Key: opts.GetKey(opts.Config.Universal.PrevTab),
Handler: self.handlePrevTab,
Handler: opts.Guards.NoPopupPanel(self.handlePrevTab),
Description: self.c.Tr.PrevTab,
Tag: "navigation",
},

View file

@ -1019,6 +1019,8 @@ Thanks for using lazygit! Seriously you rock. Three things to share with you:
You can also sponsor me and tell me what to work on by clicking the donate
button at the bottom right.
Or even just star the repo to share the love!
Press {{confirmationKey}} to get started.
`
const englishDeprecatedEditConfigWarning = `

View file

@ -371,7 +371,6 @@ var tests = []*components.IntegrationTest{
tag.Reset,
ui.Accordion,
ui.DisableSwitchTabWithPanelJumpKeys,
ui.DoublePopup,
ui.EmptyMenu,
ui.KeybindingSuggestionsWhenSwitchingRepos,
ui.ModeSpecificKeybindingSuggestions,

View file

@ -1,34 +0,0 @@
package ui
import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)
var DoublePopup = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Open a popup from within another popup and assert you can escape back to the side panels",
ExtraCmdArgs: []string{},
Skip: false,
SetupConfig: func(config *config.AppConfig) {},
SetupRepo: func(shell *Shell) {
shell.EmptyCommit("one")
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
t.Views().Branches().
Focus().
// arbitrarily bringing up a popup
PressPrimaryAction()
t.ExpectPopup().Alert().
Title(Contains("Error")).
Content(Contains("You have already checked out this branch"))
t.GlobalPress(keys.Universal.OpenRecentRepos)
t.ExpectPopup().Menu().Title(Contains("Recent repositories")).Cancel()
t.Views().Branches().IsFocused()
t.Views().Files().Focus()
},
})