Skip to content

Commit 26c3e0d

Browse files
authored
Stagger popup panels (#3694)
- **PR Description** Sometimes we open a popup panel on top of another one; an example is the `<c-o>` menu in the commit message editor, or the "add co-author" prompt that appears on top of the commit message panel. We just added a new one in #3676, which is the confirmation that appears when pasting a commit message over an existing one. Currently, these panels are sized and positioned independently of each other, which looks ugly and makes it hard to see what's going on: <img width="720" alt="image" src="https://github.com/jesseduffield/lazygit/assets/1225667/6d84fc85-fadb-4f03-a973-868bc29d79f5"> Improve this by offsetting the new panel a bit down and to the right from the one below it: <img width="750" alt="image" src="https://github.com/jesseduffield/lazygit/assets/1225667/c0c39f88-356b-4add-b335-4db2e54496ed"> Along the way we clean up the code a bit and fix a few minor issues; see the individual commit messages for details. - **Please check if the PR fulfills these requirements** * [x] Cheatsheets are up-to-date (run `go generate ./...`) * [x] Code has been formatted (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#code-formatting)) * [ ] Tests have been added/updated (see [here](https://github.com/jesseduffield/lazygit/blob/master/pkg/integration/README.md) for the integration test guide) * [ ] Text is internationalised (see [here](https://github.com/jesseduffield/lazygit/blob/master/CONTRIBUTING.md#internationalisation)) * [ ] Docs have been updated if necessary * [x] You've read through your own file changes for silly mistakes etc
2 parents 63a523c + 4b6479b commit 26c3e0d

File tree

15 files changed

+75
-96
lines changed

15 files changed

+75
-96
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ require (
1616
github.com/integrii/flaggy v1.4.0
1717
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68
1818
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d
19-
github.com/jesseduffield/gocui v0.3.1-0.20240623124136-ce5274be521d
19+
github.com/jesseduffield/gocui v0.3.1-0.20240628061234-aed9e133e65b
2020
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10
2121
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5
2222
github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,8 @@ github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68 h1:EQP2Tv8T
188188
github.com/jesseduffield/generics v0.0.0-20220320043834-727e535cbe68/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk=
189189
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d h1:bO+OmbreIv91rCe8NmscRwhFSqkDJtzWCPV4Y+SQuXE=
190190
github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o=
191-
github.com/jesseduffield/gocui v0.3.1-0.20240623124136-ce5274be521d h1:I6rViLB+ZW5SnS8P7ZE0FdY6lMfx803qZ9ZYEYCvfro=
192-
github.com/jesseduffield/gocui v0.3.1-0.20240623124136-ce5274be521d/go.mod h1:XtEbqCbn45keRXEu+OMZkjN5gw6AEob59afsgHjokZ8=
191+
github.com/jesseduffield/gocui v0.3.1-0.20240628061234-aed9e133e65b h1:oxCq0DvR2GMGf4UaoaASb0nQK/fJMQW3c3PNCLWCjS8=
192+
github.com/jesseduffield/gocui v0.3.1-0.20240628061234-aed9e133e65b/go.mod h1:XtEbqCbn45keRXEu+OMZkjN5gw6AEob59afsgHjokZ8=
193193
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10 h1:jmpr7KpX2+2GRiE91zTgfq49QvgiqB0nbmlwZ8UnOx0=
194194
github.com/jesseduffield/kill v0.0.0-20220618033138-bfbe04675d10/go.mod h1:aA97kHeNA+sj2Hbki0pvLslmE4CbDyhBeSSTUUnOuVo=
195195
github.com/jesseduffield/lazycore v0.0.0-20221012050358-03d2e40243c5 h1:CDuQmfOjAtb1Gms6a1p5L2P8RhbLUq5t8aL7PiQd2uY=

pkg/gui/context.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,3 +391,12 @@ func (self *ContextMgr) ContextForKey(key types.ContextKey) types.Context {
391391

392392
return nil
393393
}
394+
395+
func (self *ContextMgr) PopupContexts() []types.Context {
396+
self.RLock()
397+
defer self.RUnlock()
398+
399+
return lo.Filter(self.ContextStack, func(context types.Context, _ int) bool {
400+
return context.GetKind() == types.TEMPORARY_POPUP || context.GetKind() == types.PERSISTENT_POPUP
401+
})
402+
}

pkg/gui/context/commit_message_context.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ func (self *CommitMessageContext) SetPanelState(
116116
"togglePanelKeyBinding": keybindings.Label(self.c.UserConfig.Keybinding.Universal.TogglePanel),
117117
"commitMenuKeybinding": keybindings.Label(self.c.UserConfig.Keybinding.CommitMessage.CommitMenu),
118118
})
119+
120+
self.c.Views().CommitDescription.Visible = true
119121
}
120122

121123
func (self *CommitMessageContext) RenderCommitLength() {

pkg/gui/controllers.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,6 @@ func (gui *Gui) getCommitMessageSetTextareaTextFn(getView func() *gocui.View) fu
404404
view := getView()
405405
view.ClearTextArea()
406406
view.TextArea.TypeString(text)
407-
gui.helpers.Confirmation.ResizeCommitMessagePanels()
408407
view.RenderTextArea()
409408
}
410409
}

pkg/gui/controllers/commit_description_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func (self *CommitDescriptionController) context() *context.CommitMessageContext
5353
}
5454

5555
func (self *CommitDescriptionController) switchToCommitMessage() error {
56-
return self.c.PushContext(self.c.Contexts().CommitMessage)
56+
return self.c.ReplaceContext(self.c.Contexts().CommitMessage)
5757
}
5858

5959
func (self *CommitDescriptionController) close() error {

pkg/gui/controllers/commit_message_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ func (self *CommitMessageController) handleNextCommit() error {
8585
}
8686

8787
func (self *CommitMessageController) switchToCommitDescription() error {
88-
if err := self.c.PushContext(self.c.Contexts().CommitDescription); err != nil {
88+
if err := self.c.ReplaceContext(self.c.Contexts().CommitDescription); err != nil {
8989
return err
9090
}
9191
return nil

pkg/gui/controllers/custom_patch_options_menu_action.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ func (self *CustomPatchOptionsMenuAction) handlePullPatchIntoNewCommit() error {
214214
PreserveMessage: false,
215215
OnConfirm: func(summary string, description string) error {
216216
return self.c.WithWaitingStatus(self.c.Tr.RebasingStatus, func(gocui.Task) error {
217-
_ = self.c.Helpers().Commits.PopCommitMessageContexts()
217+
_ = self.c.Helpers().Commits.CloseCommitMessagePanel()
218218
self.c.LogAction(self.c.Tr.Actions.MovePatchIntoNewCommit)
219219
err := self.c.Git().Patch.PullPatchIntoNewCommit(self.c.Model().Commits, commitIndex, summary, description)
220220
if err := self.c.Helpers().MergeAndRebase.CheckMergeOrRebase(err); err != nil {

pkg/gui/controllers/helpers/commits_helper.go

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ func (self *CommitsHelper) OpenCommitMessagePanel(opts *OpenCommitMessagePanelOp
154154

155155
self.UpdateCommitPanelView(opts.InitialMessage)
156156

157-
return self.pushCommitMessageContexts()
157+
return self.c.PushContext(self.c.Contexts().CommitMessage)
158158
}
159159

160160
func (self *CommitsHelper) OnCommitSuccess() {
@@ -190,28 +190,10 @@ func (self *CommitsHelper) CloseCommitMessagePanel() error {
190190

191191
self.c.Contexts().CommitMessage.SetHistoryMessage("")
192192

193-
return self.PopCommitMessageContexts()
194-
}
195-
196-
func (self *CommitsHelper) PopCommitMessageContexts() error {
197-
return self.c.RemoveContexts(self.commitMessageContexts())
198-
}
193+
self.c.Views().CommitMessage.Visible = false
194+
self.c.Views().CommitDescription.Visible = false
199195

200-
func (self *CommitsHelper) pushCommitMessageContexts() error {
201-
for _, context := range self.commitMessageContexts() {
202-
if err := self.c.PushContext(context); err != nil {
203-
return err
204-
}
205-
}
206-
207-
return nil
208-
}
209-
210-
func (self *CommitsHelper) commitMessageContexts() []types.Context {
211-
return []types.Context{
212-
self.c.Contexts().CommitDescription,
213-
self.c.Contexts().CommitMessage,
214-
}
196+
return self.c.PopContext()
215197
}
216198

217199
func (self *CommitsHelper) OpenCommitMenu(suggestionFunc func(string) []*types.Suggestion) error {

pkg/gui/controllers/helpers/confirmation_helper.go

Lines changed: 32 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import (
55
"fmt"
66
"strings"
77

8-
"github.com/jesseduffield/gocui"
9-
108
"github.com/jesseduffield/lazygit/pkg/gui/style"
119
"github.com/jesseduffield/lazygit/pkg/gui/types"
1210
"github.com/jesseduffield/lazygit/pkg/theme"
@@ -118,21 +116,23 @@ func wrapMessageToWidth(wrap bool, message string, width int) []string {
118116
return wrappedLines
119117
}
120118

121-
func (self *ConfirmationHelper) getPopupPanelDimensions(wrap bool, prompt string) (int, int, int, int) {
122-
panelWidth := self.getPopupPanelWidth()
123-
panelHeight := getMessageHeight(wrap, prompt, panelWidth)
124-
return self.getPopupPanelDimensionsAux(panelWidth, panelHeight)
125-
}
126-
127-
func (self *ConfirmationHelper) getPopupPanelDimensionsForContentHeight(panelWidth, contentHeight int) (int, int, int, int) {
128-
return self.getPopupPanelDimensionsAux(panelWidth, contentHeight)
119+
func (self *ConfirmationHelper) getPopupPanelDimensionsForContentHeight(panelWidth, contentHeight int, parentPopupContext types.Context) (int, int, int, int) {
120+
return self.getPopupPanelDimensionsAux(panelWidth, contentHeight, parentPopupContext)
129121
}
130122

131-
func (self *ConfirmationHelper) getPopupPanelDimensionsAux(panelWidth int, panelHeight int) (int, int, int, int) {
123+
func (self *ConfirmationHelper) getPopupPanelDimensionsAux(panelWidth int, panelHeight int, parentPopupContext types.Context) (int, int, int, int) {
132124
width, height := self.c.GocuiGui().Size()
133125
if panelHeight > height*3/4 {
134126
panelHeight = height * 3 / 4
135127
}
128+
if parentPopupContext != nil {
129+
// If there's already a popup on the screen, offset the new one from its
130+
// parent so that it's clearly distinguished from the parent
131+
x0, y0, _, _ := parentPopupContext.GetView().Dimensions()
132+
x0 += 2
133+
y0 += 1
134+
return x0, y0, x0 + panelWidth, y0 + panelHeight + 1
135+
}
136136
return width/2 - panelWidth/2,
137137
height/2 - panelHeight/2 - panelHeight%2 - 1,
138138
width/2 + panelWidth/2,
@@ -177,7 +177,6 @@ func (self *ConfirmationHelper) prepareConfirmationPanel(
177177
suggestionsView.Subtitle = ""
178178
}
179179

180-
self.ResizeConfirmationPanel()
181180
return nil
182181
}
183182

@@ -227,7 +226,6 @@ func (self *ConfirmationHelper) CreatePopupPanel(ctx goContext.Context, opts typ
227226
textArea := confirmationView.TextArea
228227
textArea.Clear()
229228
textArea.TypeString(opts.Prompt)
230-
self.ResizeConfirmationPanel()
231229
confirmationView.RenderTextArea()
232230
} else {
233231
self.c.ResetViewOrigin(confirmationView)
@@ -325,57 +323,31 @@ func (self *ConfirmationHelper) getSelectedSuggestionValue() string {
325323
return ""
326324
}
327325

328-
func (self *ConfirmationHelper) ResizeConfirmationPanel() {
329-
suggestionsViewHeight := 0
330-
if self.c.Views().Suggestions.Visible {
331-
suggestionsViewHeight = 11
332-
}
333-
panelWidth := self.getPopupPanelWidth()
334-
prompt := self.c.Views().Confirmation.Buffer()
335-
wrap := true
336-
if self.c.Views().Confirmation.Editable {
337-
prompt = self.c.Views().Confirmation.TextArea.GetContent()
338-
wrap = false
339-
}
340-
panelHeight := getMessageHeight(wrap, prompt, panelWidth) + suggestionsViewHeight
341-
x0, y0, x1, y1 := self.getPopupPanelDimensionsAux(panelWidth, panelHeight)
342-
confirmationViewBottom := y1 - suggestionsViewHeight
343-
_, _ = self.c.GocuiGui().SetView(self.c.Views().Confirmation.Name(), x0, y0, x1, confirmationViewBottom, 0)
344-
345-
suggestionsViewTop := confirmationViewBottom + 1
346-
_, _ = self.c.GocuiGui().SetView(self.c.Views().Suggestions.Name(), x0, suggestionsViewTop, x1, suggestionsViewTop+suggestionsViewHeight, 0)
347-
}
348-
349-
func (self *ConfirmationHelper) ResizeCurrentPopupPanel() error {
350-
c := self.c.CurrentContext()
326+
func (self *ConfirmationHelper) ResizeCurrentPopupPanels() {
327+
var parentPopupContext types.Context
328+
for _, c := range self.c.CurrentPopupContexts() {
329+
switch c {
330+
case self.c.Contexts().Menu:
331+
self.resizeMenu(parentPopupContext)
332+
case self.c.Contexts().Confirmation, self.c.Contexts().Suggestions:
333+
self.resizeConfirmationPanel(parentPopupContext)
334+
case self.c.Contexts().CommitMessage, self.c.Contexts().CommitDescription:
335+
self.ResizeCommitMessagePanels(parentPopupContext)
336+
}
351337

352-
switch c {
353-
case self.c.Contexts().Menu:
354-
self.resizeMenu()
355-
case self.c.Contexts().Confirmation, self.c.Contexts().Suggestions:
356-
self.resizeConfirmationPanel()
357-
case self.c.Contexts().CommitMessage, self.c.Contexts().CommitDescription:
358-
self.ResizeCommitMessagePanels()
338+
parentPopupContext = c
359339
}
360-
361-
return nil
362-
}
363-
364-
func (self *ConfirmationHelper) ResizePopupPanel(v *gocui.View, content string) error {
365-
x0, y0, x1, y1 := self.getPopupPanelDimensions(v.Wrap, content)
366-
_, err := self.c.GocuiGui().SetView(v.Name(), x0, y0, x1, y1, 0)
367-
return err
368340
}
369341

370-
func (self *ConfirmationHelper) resizeMenu() {
342+
func (self *ConfirmationHelper) resizeMenu(parentPopupContext types.Context) {
371343
// we want the unfiltered length here so that if we're filtering we don't
372344
// resize the window
373345
itemCount := self.c.Contexts().Menu.UnfilteredLen()
374346
offset := 3
375347
panelWidth := self.getPopupPanelWidth()
376348
contentWidth := panelWidth - 2 // minus 2 for the frame
377349
promptLinesCount := self.layoutMenuPrompt(contentWidth)
378-
x0, y0, x1, y1 := self.getPopupPanelDimensionsForContentHeight(panelWidth, itemCount+offset+promptLinesCount)
350+
x0, y0, x1, y1 := self.getPopupPanelDimensionsForContentHeight(panelWidth, itemCount+offset+promptLinesCount, parentPopupContext)
379351
menuBottom := y1 - offset
380352
_, _ = self.c.GocuiGui().SetView(self.c.Views().Menu.Name(), x0, y0, x1, menuBottom, 0)
381353

@@ -418,7 +390,7 @@ func (self *ConfirmationHelper) layoutMenuPrompt(contentWidth int) int {
418390
return len(promptLines)
419391
}
420392

421-
func (self *ConfirmationHelper) resizeConfirmationPanel() {
393+
func (self *ConfirmationHelper) resizeConfirmationPanel(parentPopupContext types.Context) {
422394
suggestionsViewHeight := 0
423395
if self.c.Views().Suggestions.Visible {
424396
suggestionsViewHeight = 11
@@ -431,15 +403,15 @@ func (self *ConfirmationHelper) resizeConfirmationPanel() {
431403
wrap = false
432404
}
433405
panelHeight := getMessageHeight(wrap, prompt, panelWidth) + suggestionsViewHeight
434-
x0, y0, x1, y1 := self.getPopupPanelDimensionsAux(panelWidth, panelHeight)
406+
x0, y0, x1, y1 := self.getPopupPanelDimensionsAux(panelWidth, panelHeight, parentPopupContext)
435407
confirmationViewBottom := y1 - suggestionsViewHeight
436408
_, _ = self.c.GocuiGui().SetView(self.c.Views().Confirmation.Name(), x0, y0, x1, confirmationViewBottom, 0)
437409

438410
suggestionsViewTop := confirmationViewBottom + 1
439411
_, _ = self.c.GocuiGui().SetView(self.c.Views().Suggestions.Name(), x0, suggestionsViewTop, x1, suggestionsViewTop+suggestionsViewHeight, 0)
440412
}
441413

442-
func (self *ConfirmationHelper) ResizeCommitMessagePanels() {
414+
func (self *ConfirmationHelper) ResizeCommitMessagePanels(parentPopupContext types.Context) {
443415
panelWidth := self.getPopupPanelWidth()
444416
content := self.c.Views().CommitDescription.TextArea.GetContent()
445417
summaryViewHeight := 3
@@ -448,18 +420,18 @@ func (self *ConfirmationHelper) ResizeCommitMessagePanels() {
448420
if panelHeight < minHeight {
449421
panelHeight = minHeight
450422
}
451-
x0, y0, x1, y1 := self.getPopupPanelDimensionsAux(panelWidth, panelHeight)
423+
x0, y0, x1, y1 := self.getPopupPanelDimensionsAux(panelWidth, panelHeight, parentPopupContext)
452424

453425
_, _ = self.c.GocuiGui().SetView(self.c.Views().CommitMessage.Name(), x0, y0, x1, y0+summaryViewHeight-1, 0)
454426
_, _ = self.c.GocuiGui().SetView(self.c.Views().CommitDescription.Name(), x0, y0+summaryViewHeight, x1, y1+summaryViewHeight, 0)
455427
}
456428

457-
func (self *ConfirmationHelper) IsPopupPanel(viewName string) bool {
458-
return viewName == "commitMessage" || viewName == "confirmation" || viewName == "menu"
429+
func (self *ConfirmationHelper) IsPopupPanel(context types.Context) bool {
430+
return context.GetKind() == types.PERSISTENT_POPUP || context.GetKind() == types.TEMPORARY_POPUP
459431
}
460432

461433
func (self *ConfirmationHelper) IsPopupPanelFocused() bool {
462-
return self.IsPopupPanel(self.c.CurrentContext().GetViewName())
434+
return self.IsPopupPanel(self.c.CurrentContext())
463435
}
464436

465437
func (self *ConfirmationHelper) TooltipForMenuItem(menuItem *types.MenuItem) string {

0 commit comments

Comments
 (0)