Skip to content

Commit f793050

Browse files
Show Toast instead of error panel when invoking a disabled command (#3180)
- **PR Description** Addresses #3116. I'm not 100% sure I like the behavior, but I put it out there so that others can test it and form an opinion. It not only affects keybindings, but also invoking menu items (either with enter or with their key binding): the menu now stays open in that case, which I think is actually better. There's a horrible hack for keeping the integration tests working, I don't have a good idea how to fix that for real. Suggestions welcome.
2 parents 37590a4 + f133224 commit f793050

38 files changed

+280
-166
lines changed

pkg/app/app.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/jesseduffield/lazygit/pkg/env"
2424
"github.com/jesseduffield/lazygit/pkg/gui"
2525
"github.com/jesseduffield/lazygit/pkg/i18n"
26+
integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types"
2627
"github.com/jesseduffield/lazygit/pkg/logs"
2728
"github.com/jesseduffield/lazygit/pkg/updates"
2829
)
@@ -42,7 +43,7 @@ func Run(
4243
common *common.Common,
4344
startArgs appTypes.StartArgs,
4445
) {
45-
app, err := NewApp(config, common)
46+
app, err := NewApp(config, startArgs.IntegrationTest, common)
4647

4748
if err == nil {
4849
err = app.Run(startArgs)
@@ -94,7 +95,7 @@ func newLogger(cfg config.AppConfigurer) *logrus.Entry {
9495
}
9596

9697
// NewApp bootstrap a new application
97-
func NewApp(config config.AppConfigurer, common *common.Common) (*App, error) {
98+
func NewApp(config config.AppConfigurer, test integrationTypes.IntegrationTest, common *common.Common) (*App, error) {
9899
app := &App{
99100
closers: []io.Closer{},
100101
Config: config,
@@ -128,7 +129,7 @@ func NewApp(config config.AppConfigurer, common *common.Common) (*App, error) {
128129
showRecentRepos = true
129130
}
130131

131-
app.Gui, err = gui.NewGui(common, config, gitVersion, updater, showRecentRepos, dirName)
132+
app.Gui, err = gui.NewGui(common, config, gitVersion, updater, showRecentRepos, dirName, test)
132133
if err != nil {
133134
return app, err
134135
}

pkg/cheatsheet/generate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func generateAtDir(cheatsheetDir string) {
6161
if err != nil {
6262
log.Fatal(err)
6363
}
64-
mApp, _ := app.NewApp(mConfig, common)
64+
mApp, _ := app.NewApp(mConfig, nil, common)
6565
path := cheatsheetDir + "/Keybindings_" + lang + ".md"
6666
file, err := os.Create(path)
6767
if err != nil {

pkg/gui/context/menu_context.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ func (self *MenuViewModel) GetDisplayStrings(_ int, _ int) [][]string {
9090

9191
return lo.Map(menuItems, func(item *types.MenuItem, _ int) []string {
9292
displayStrings := item.LabelColumns
93-
if item.DisabledReason != "" {
93+
if item.DisabledReason != nil {
9494
displayStrings[0] = style.FgDefault.SetStrikethrough().Sprint(displayStrings[0])
9595
}
9696

@@ -172,8 +172,13 @@ func (self *MenuContext) GetKeybindings(opts types.KeybindingsOpts) []*types.Bin
172172
}
173173

174174
func (self *MenuContext) OnMenuPress(selectedItem *types.MenuItem) error {
175-
if selectedItem != nil && selectedItem.DisabledReason != "" {
176-
return self.c.ErrorMsg(selectedItem.DisabledReason)
175+
if selectedItem != nil && selectedItem.DisabledReason != nil {
176+
if selectedItem.DisabledReason.ShowErrorInPanel {
177+
return self.c.ErrorMsg(selectedItem.DisabledReason.Text)
178+
}
179+
180+
self.c.ErrorToast(self.c.Tr.DisabledMenuItemPrefix + selectedItem.DisabledReason.Text)
181+
return nil
177182
}
178183

179184
if err := self.c.PopContext(); err != nil {

pkg/gui/controllers/branches_controller.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -264,13 +264,13 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
264264
}
265265

266266
if !selectedBranch.IsTrackingRemote() {
267-
unsetUpstreamItem.DisabledReason = self.c.Tr.UpstreamNotSetError
267+
unsetUpstreamItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.UpstreamNotSetError}
268268
}
269269

270270
if !selectedBranch.RemoteBranchStoredLocally() {
271-
viewDivergenceItem.DisabledReason = self.c.Tr.UpstreamNotSetError
272-
upstreamResetItem.DisabledReason = self.c.Tr.UpstreamNotSetError
273-
upstreamRebaseItem.DisabledReason = self.c.Tr.UpstreamNotSetError
271+
viewDivergenceItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.UpstreamNotSetError}
272+
upstreamResetItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.UpstreamNotSetError}
273+
upstreamRebaseItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.UpstreamNotSetError}
274274
}
275275

276276
options := []*types.MenuItem{
@@ -309,16 +309,16 @@ func (self *BranchesController) press(selectedBranch *models.Branch) error {
309309
return self.c.Helpers().Refs.CheckoutRef(selectedBranch.Name, types.CheckoutRefOptions{})
310310
}
311311

312-
func (self *BranchesController) getDisabledReasonForPress() string {
312+
func (self *BranchesController) getDisabledReasonForPress() *types.DisabledReason {
313313
currentBranch := self.c.Helpers().Refs.GetCheckedOutRef()
314314
if currentBranch != nil {
315315
op := self.c.State().GetItemOperation(currentBranch)
316316
if op == types.ItemOperationFastForwarding || op == types.ItemOperationPulling {
317-
return self.c.Tr.CantCheckoutBranchWhilePulling
317+
return &types.DisabledReason{Text: self.c.Tr.CantCheckoutBranchWhilePulling}
318318
}
319319
}
320320

321-
return ""
321+
return nil
322322
}
323323

324324
func (self *BranchesController) worktreeForBranch(branch *models.Branch) (*models.Worktree, bool) {
@@ -525,7 +525,7 @@ func (self *BranchesController) delete(branch *models.Branch) error {
525525
},
526526
}
527527
if checkedOutBranch.Name == branch.Name {
528-
localDeleteItem.DisabledReason = self.c.Tr.CantDeleteCheckOutBranch
528+
localDeleteItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.CantDeleteCheckOutBranch}
529529
}
530530

531531
remoteDeleteItem := &types.MenuItem{
@@ -536,7 +536,7 @@ func (self *BranchesController) delete(branch *models.Branch) error {
536536
},
537537
}
538538
if !branch.IsTrackingRemote() || branch.UpstreamGone {
539-
remoteDeleteItem.DisabledReason = self.c.Tr.UpstreamNotSetError
539+
remoteDeleteItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.UpstreamNotSetError}
540540
}
541541

542542
menuTitle := utils.ResolvePlaceholderString(
@@ -562,14 +562,14 @@ func (self *BranchesController) rebase() error {
562562
return self.c.Helpers().MergeAndRebase.RebaseOntoRef(selectedBranchName)
563563
}
564564

565-
func (self *BranchesController) getDisabledReasonForRebase() string {
565+
func (self *BranchesController) getDisabledReasonForRebase() *types.DisabledReason {
566566
selectedBranchName := self.context().GetSelected().Name
567567
checkedOutBranch := self.c.Helpers().Refs.GetCheckedOutRef().Name
568568
if selectedBranchName == checkedOutBranch {
569-
return self.c.Tr.CantRebaseOntoSelf
569+
return &types.DisabledReason{Text: self.c.Tr.CantRebaseOntoSelf}
570570
}
571571

572-
return ""
572+
return nil
573573
}
574574

575575
func (self *BranchesController) fastForward(branch *models.Branch) error {

pkg/gui/controllers/files_controller.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -848,15 +848,15 @@ func (self *FilesController) openCopyMenu() error {
848848
}
849849

850850
if node == nil {
851-
copyNameItem.DisabledReason = self.c.Tr.NoContentToCopyError
852-
copyPathItem.DisabledReason = self.c.Tr.NoContentToCopyError
853-
copyFileDiffItem.DisabledReason = self.c.Tr.NoContentToCopyError
851+
copyNameItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
852+
copyPathItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
853+
copyFileDiffItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
854854
}
855855
if node != nil && !node.GetHasStagedOrTrackedChanges() {
856-
copyFileDiffItem.DisabledReason = self.c.Tr.NoContentToCopyError
856+
copyFileDiffItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
857857
}
858858
if !self.anyStagedOrTrackedFile() {
859-
copyAllDiff.DisabledReason = self.c.Tr.NoContentToCopyError
859+
copyAllDiff.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
860860
}
861861

862862
return self.c.Menu(types.CreateMenuOptions{

pkg/gui/controllers/helpers/app_status_helper.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/jesseduffield/gocui"
77
"github.com/jesseduffield/lazygit/pkg/gui/status"
8+
"github.com/jesseduffield/lazygit/pkg/gui/types"
89
"github.com/jesseduffield/lazygit/pkg/utils"
910
)
1011

@@ -23,15 +24,15 @@ func NewAppStatusHelper(c *HelperCommon, statusMgr func() *status.StatusManager,
2324
}
2425
}
2526

26-
func (self *AppStatusHelper) Toast(message string) {
27+
func (self *AppStatusHelper) Toast(message string, kind types.ToastKind) {
2728
if self.c.RunningIntegrationTest() {
2829
// Don't bother showing toasts in integration tests. You can't check for
2930
// them anyway, and they would only slow down the test unnecessarily by
3031
// two seconds.
3132
return
3233
}
3334

34-
self.statusMgr().AddToastStatus(message)
35+
self.statusMgr().AddToastStatus(message, kind)
3536

3637
self.renderAppStatus()
3738
}
@@ -87,15 +88,17 @@ func (self *AppStatusHelper) HasStatus() bool {
8788
}
8889

8990
func (self *AppStatusHelper) GetStatusString() string {
90-
return self.statusMgr().GetStatusString()
91+
appStatus, _ := self.statusMgr().GetStatusString()
92+
return appStatus
9193
}
9294

9395
func (self *AppStatusHelper) renderAppStatus() {
9496
self.c.OnWorker(func(_ gocui.Task) {
9597
ticker := time.NewTicker(time.Millisecond * utils.LoaderAnimationInterval)
9698
defer ticker.Stop()
9799
for range ticker.C {
98-
appStatus := self.statusMgr().GetStatusString()
100+
appStatus, color := self.statusMgr().GetStatusString()
101+
self.c.Views().AppStatus.FgColor = color
99102
self.c.OnUIThread(func() error {
100103
self.c.SetViewContent(self.c.Views().AppStatus, appStatus)
101104
return nil
@@ -127,7 +130,8 @@ func (self *AppStatusHelper) renderAppStatusSync(stop chan struct{}) {
127130
for {
128131
select {
129132
case <-ticker.C:
130-
appStatus := self.statusMgr().GetStatusString()
133+
appStatus, color := self.statusMgr().GetStatusString()
134+
self.c.Views().AppStatus.FgColor = color
131135
self.c.SetViewContent(self.c.Views().AppStatus, appStatus)
132136
// Redraw all views of the bottom line:
133137
bottomLineViews := []*gocui.View{

pkg/gui/controllers/helpers/confirmation_helper.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,11 +378,11 @@ func (self *ConfirmationHelper) IsPopupPanelFocused() bool {
378378

379379
func (self *ConfirmationHelper) TooltipForMenuItem(menuItem *types.MenuItem) string {
380380
tooltip := menuItem.Tooltip
381-
if menuItem.DisabledReason != "" {
381+
if menuItem.DisabledReason != nil {
382382
if tooltip != "" {
383383
tooltip += "\n\n"
384384
}
385-
tooltip += style.FgRed.Sprintf(self.c.Tr.DisabledMenuItemPrefix) + menuItem.DisabledReason
385+
tooltip += style.FgRed.Sprintf(self.c.Tr.DisabledMenuItemPrefix) + menuItem.DisabledReason.Text
386386
}
387387
return tooltip
388388
}

0 commit comments

Comments
 (0)