summaryrefslogtreecommitdiffstats
path: root/pkg/gui/popup/popup_handler.go
blob: c8ff10d851687dbdee0a9c8cac8d52320abcb91d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package popup

import (
	"context"
	"strings"

	"github.com/jesseduffield/gocui"
	"github.com/jesseduffield/lazygit/pkg/common"
	"github.com/jesseduffield/lazygit/pkg/gui/style"
	"github.com/jesseduffield/lazygit/pkg/gui/types"
)

type PopupHandler struct {
	*common.Common
	createPopupPanelFn      func(context.Context, types.CreatePopupPanelOpts) error
	onErrorFn               func() error
	popContextFn            func() error
	currentContextFn        func() types.Context
	createMenuFn            func(types.CreateMenuOptions) error
	withWaitingStatusFn     func(message string, f func(gocui.Task) error)
	withWaitingStatusSyncFn func(message string, f func() error) error
	toastFn                 func(message string, kind types.ToastKind)
	getPromptInputFn        func() string
	inDemo                  func() bool
}

var _ types.IPopupHandler = &PopupHandler{}

func NewPopupHandler(
	common *common.Common,
	createPopupPanelFn func(context.Context, types.CreatePopupPanelOpts) error,
	onErrorFn func() error,
	popContextFn func() error,
	currentContextFn func() types.Context,
	createMenuFn func(types.CreateMenuOptions) error,
	withWaitingStatusFn func(message string, f func(gocui.Task) error),
	withWaitingStatusSyncFn func(message string, f func() error) error,
	toastFn func(message string, kind types.ToastKind),
	getPromptInputFn func() string,
	inDemo func() bool,
) *PopupHandler {
	return &PopupHandler{
		Common:                  common,
		createPopupPanelFn:      createPopupPanelFn,
		onErrorFn:               onErrorFn,
		popContextFn:            popContextFn,
		currentContextFn:        currentContextFn,
		createMenuFn:            createMenuFn,
		withWaitingStatusFn:     withWaitingStatusFn,
		withWaitingStatusSyncFn: withWaitingStatusSyncFn,
		toastFn:                 toastFn,
		getPromptInputFn:        getPromptInputFn,
		inDemo:                  inDemo,
	}
}

func (self *PopupHandler) Menu(opts types.CreateMenuOptions) error {
	return self.createMenuFn(opts)
}

func (self *PopupHandler) Toast(message string) {
	self.toastFn(message, types.ToastKindStatus)
}

func (self *PopupHandler) ErrorToast(message string) {
	self.toastFn(message, types.ToastKindError)
}

func (self *PopupHandler) SetToastFunc(f func(string, types.ToastKind)) {
	self.toastFn = f
}

func (self *PopupHandler) WithWaitingStatus(message string, f func(gocui.Task) error) error {
	self.withWaitingStatusFn(message, f)
	return nil
}

func (self *PopupHandler) WithWaitingStatusSync(message string, f func() error) error {
	return self.withWaitingStatusSyncFn(message, f)
}

func (self *PopupHandler) Error(err error) error {
	if err == gocui.ErrQuit {
		return err
	}

	return self.ErrorMsg(err.Error())
}

func (self *PopupHandler) ErrorMsg(message string) error {
	// Need to set bold here explicitly; otherwise it gets cancelled by the red colouring.
	coloredMessage := style.FgRed.SetBold().Sprint(strings.TrimSpace(message))
	if err := self.onErrorFn(); err != nil {
		return err
	}

	return self.Alert(self.Tr.Error, coloredMessage)
}

func (self *PopupHandler) Alert(title string, message string) error {
	return self.Confirm(types.ConfirmOpts{Title: title, Prompt: message})
}

func (self *PopupHandler) Confirm(opts types.ConfirmOpts) error {
	return self.createPopupPanelFn(context.Background(), types.CreatePopupPanelOpts{
		Title:         opts.Title,
		Prompt:        opts.Prompt,
		HandleConfirm: opts.HandleConfirm,
		HandleClose:   opts.HandleClose,
	})
}

func (self *PopupHandler) Prompt(opts types.PromptOpts) error {
	return self.createPopupPanelFn(context.Background(), types.CreatePopupPanelOpts{
		Title:               opts.Title,
		Prompt:              opts.InitialContent,
		Editable:            true,
		HandleConfirmPrompt: opts.HandleConfirm,
		HandleClose:         opts.HandleClose,
		FindSuggestionsFunc: opts.FindSuggestionsFunc,
		Mask:                opts.Mask,
	})
}

// returns the content that has currently been typed into the prompt. Useful for
// asynchronously updating the suggestions list under the prompt.
func (self *PopupHandler) GetPromptInput() string {
	return self.getPromptInputFn()
}