mirror of
https://github.com/jesseduffield/lazygit.git
synced 2024-12-12 11:15:00 +02:00
9cc1d65280
We're piggybacking on our existing integration test framework to record demos that we can include in our docs
177 lines
4.6 KiB
Go
177 lines
4.6 KiB
Go
package popup
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/jesseduffield/gocui"
|
|
"github.com/jesseduffield/lazygit/pkg/common"
|
|
gctx "github.com/jesseduffield/lazygit/pkg/gui/context"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/style"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
|
"github.com/sasha-s/go-deadlock"
|
|
)
|
|
|
|
type PopupHandler struct {
|
|
*common.Common
|
|
index int
|
|
deadlock.Mutex
|
|
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)
|
|
toastFn func(message string)
|
|
getPromptInputFn func() string
|
|
onWorker func(func(gocui.Task))
|
|
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),
|
|
toastFn func(message string),
|
|
getPromptInputFn func() string,
|
|
onWorker func(func(gocui.Task)),
|
|
inDemo func() bool,
|
|
) *PopupHandler {
|
|
return &PopupHandler{
|
|
Common: common,
|
|
index: 0,
|
|
createPopupPanelFn: createPopupPanelFn,
|
|
onErrorFn: onErrorFn,
|
|
popContextFn: popContextFn,
|
|
currentContextFn: currentContextFn,
|
|
createMenuFn: createMenuFn,
|
|
withWaitingStatusFn: withWaitingStatusFn,
|
|
toastFn: toastFn,
|
|
getPromptInputFn: getPromptInputFn,
|
|
onWorker: onWorker,
|
|
inDemo: inDemo,
|
|
}
|
|
}
|
|
|
|
func (self *PopupHandler) Menu(opts types.CreateMenuOptions) error {
|
|
return self.createMenuFn(opts)
|
|
}
|
|
|
|
func (self *PopupHandler) Toast(message string) {
|
|
self.toastFn(message)
|
|
}
|
|
|
|
func (self *PopupHandler) WithWaitingStatus(message string, f func(gocui.Task) error) error {
|
|
self.withWaitingStatusFn(message, f)
|
|
return nil
|
|
}
|
|
|
|
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 {
|
|
self.Lock()
|
|
self.index++
|
|
self.Unlock()
|
|
|
|
// 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 {
|
|
self.Lock()
|
|
self.index++
|
|
self.Unlock()
|
|
|
|
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 {
|
|
self.Lock()
|
|
self.index++
|
|
self.Unlock()
|
|
|
|
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,
|
|
})
|
|
}
|
|
|
|
func (self *PopupHandler) WithLoaderPanel(message string, f func(gocui.Task) error) error {
|
|
index := 0
|
|
self.Lock()
|
|
self.index++
|
|
index = self.index
|
|
self.Unlock()
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
err := self.createPopupPanelFn(ctx, types.CreatePopupPanelOpts{
|
|
Prompt: message,
|
|
HasLoader: true,
|
|
})
|
|
if err != nil {
|
|
self.Log.Error(err)
|
|
cancel()
|
|
return nil
|
|
}
|
|
|
|
self.onWorker(func(task gocui.Task) {
|
|
// emulating a delay due to network latency
|
|
if self.inDemo() {
|
|
time.Sleep(500 * time.Millisecond)
|
|
}
|
|
|
|
if err := f(task); err != nil {
|
|
self.Log.Error(err)
|
|
}
|
|
|
|
cancel()
|
|
|
|
self.Lock()
|
|
if index == self.index && self.currentContextFn().GetKey() == gctx.CONFIRMATION_CONTEXT_KEY {
|
|
_ = self.popContextFn()
|
|
}
|
|
self.Unlock()
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
// 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()
|
|
}
|