From 79fe885dcdc13f25e8d9cd0e6e4d5eba4de9fb53 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sun, 27 Aug 2023 16:29:14 +0200 Subject: [PATCH] Add WithWaitingStatusSync --- pkg/gui/controllers.go | 1 + .../controllers/helpers/app_status_helper.go | 56 +++++++++++++++++-- pkg/gui/controllers/helpers/mode_helper.go | 7 ++- pkg/gui/gui.go | 3 + pkg/gui/popup/popup_handler.go | 48 +++++++++------- pkg/gui/types/common.go | 1 + 6 files changed, 91 insertions(+), 25 deletions(-) diff --git a/pkg/gui/controllers.go b/pkg/gui/controllers.go index 6a751e1ef..5a104352b 100644 --- a/pkg/gui/controllers.go +++ b/pkg/gui/controllers.go @@ -77,6 +77,7 @@ func (gui *Gui) resetHelpersAndControllers() { appStatusHelper := helpers.NewAppStatusHelper( helperCommon, func() *status.StatusManager { return gui.statusManager }, + modeHelper, ) setSubCommits := func(commits []*models.Commit) { diff --git a/pkg/gui/controllers/helpers/app_status_helper.go b/pkg/gui/controllers/helpers/app_status_helper.go index 37cab2728..8e4741bd5 100644 --- a/pkg/gui/controllers/helpers/app_status_helper.go +++ b/pkg/gui/controllers/helpers/app_status_helper.go @@ -11,13 +11,15 @@ import ( type AppStatusHelper struct { c *HelperCommon - statusMgr func() *status.StatusManager + statusMgr func() *status.StatusManager + modeHelper *ModeHelper } -func NewAppStatusHelper(c *HelperCommon, statusMgr func() *status.StatusManager) *AppStatusHelper { +func NewAppStatusHelper(c *HelperCommon, statusMgr func() *status.StatusManager, modeHelper *ModeHelper) *AppStatusHelper { return &AppStatusHelper{ - c: c, - statusMgr: statusMgr, + c: c, + statusMgr: statusMgr, + modeHelper: modeHelper, } } @@ -68,6 +70,18 @@ func (self *AppStatusHelper) WithWaitingStatus(message string, f func(gocui.Task }) } +func (self *AppStatusHelper) WithWaitingStatusSync(message string, f func() error) { + self.statusMgr().WithWaitingStatus(message, func() {}, func(*status.WaitingStatusHandle) { + stop := make(chan struct{}) + defer func() { close(stop) }() + self.renderAppStatusSync(stop) + + if err := f(); err != nil { + _ = self.c.Error(err) + } + }) +} + func (self *AppStatusHelper) HasStatus() bool { return self.statusMgr().HasStatus() } @@ -93,3 +107,37 @@ func (self *AppStatusHelper) renderAppStatus() { } }) } + +func (self *AppStatusHelper) renderAppStatusSync(stop chan struct{}) { + go func() { + ticker := time.NewTicker(time.Millisecond * 50) + defer ticker.Stop() + + // Forcing a re-layout and redraw after we added the waiting status; + // this is needed in case the gui.showBottomLine config is set to false, + // to make sure the bottom line appears. It's also useful for redrawing + // once after each of several consecutive keypresses, e.g. pressing + // ctrl-j to move a commit down several steps. + _ = self.c.GocuiGui().ForceLayoutAndRedraw() + + self.modeHelper.SetSuppressRebasingMode(true) + defer func() { self.modeHelper.SetSuppressRebasingMode(false) }() + + outer: + for { + select { + case <-ticker.C: + appStatus := self.statusMgr().GetStatusString() + self.c.SetViewContent(self.c.Views().AppStatus, appStatus) + // Redraw all views of the bottom line: + bottomLineViews := []*gocui.View{ + self.c.Views().AppStatus, self.c.Views().Options, self.c.Views().Information, + self.c.Views().StatusSpacer1, self.c.Views().StatusSpacer2, + } + _ = self.c.GocuiGui().ForceRedrawViews(bottomLineViews...) + case <-stop: + break outer + } + } + }() +} diff --git a/pkg/gui/controllers/helpers/mode_helper.go b/pkg/gui/controllers/helpers/mode_helper.go index b3d9549a4..27c2b9aec 100644 --- a/pkg/gui/controllers/helpers/mode_helper.go +++ b/pkg/gui/controllers/helpers/mode_helper.go @@ -19,6 +19,7 @@ type ModeHelper struct { cherryPickHelper *CherryPickHelper mergeAndRebaseHelper *MergeAndRebaseHelper bisectHelper *BisectHelper + suppressRebasingMode bool } func NewModeHelper( @@ -114,7 +115,7 @@ func (self *ModeHelper) Statuses() []ModeStatus { }, { IsActive: func() bool { - return self.c.Git().Status.WorkingTreeState() != enums.REBASE_MODE_NONE + return !self.suppressRebasingMode && self.c.Git().Status.WorkingTreeState() != enums.REBASE_MODE_NONE }, Description: func() string { workingTreeState := self.c.Git().Status.WorkingTreeState() @@ -168,3 +169,7 @@ func (self *ModeHelper) ClearFiltering() error { return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.COMMITS}}) } + +func (self *ModeHelper) SetSuppressRebasingMode(value bool) { + self.suppressRebasingMode = value +} diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 787bdd169..dd685dc72 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -513,6 +513,9 @@ func NewGui( func() types.Context { return gui.State.ContextMgr.Current() }, gui.createMenu, func(message string, f func(gocui.Task) error) { gui.helpers.AppStatus.WithWaitingStatus(message, f) }, + func(message string, f func() error) { + gui.helpers.AppStatus.WithWaitingStatusSync(message, f) + }, func(message string) { gui.helpers.AppStatus.Toast(message) }, func() string { return gui.Views.Confirmation.TextArea.GetContent() }, func() bool { return gui.c.InDemo() }, diff --git a/pkg/gui/popup/popup_handler.go b/pkg/gui/popup/popup_handler.go index cd34bc20e..33c01e0cc 100644 --- a/pkg/gui/popup/popup_handler.go +++ b/pkg/gui/popup/popup_handler.go @@ -15,15 +15,16 @@ 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 - inDemo func() bool + 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) + toastFn func(message string) + getPromptInputFn func() string + inDemo func() bool } var _ types.IPopupHandler = &PopupHandler{} @@ -36,22 +37,24 @@ func NewPopupHandler( 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), toastFn func(message string), getPromptInputFn func() string, 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, - inDemo: inDemo, + Common: common, + index: 0, + createPopupPanelFn: createPopupPanelFn, + onErrorFn: onErrorFn, + popContextFn: popContextFn, + currentContextFn: currentContextFn, + createMenuFn: createMenuFn, + withWaitingStatusFn: withWaitingStatusFn, + withWaitingStatusSyncFn: withWaitingStatusSyncFn, + toastFn: toastFn, + getPromptInputFn: getPromptInputFn, + inDemo: inDemo, } } @@ -68,6 +71,11 @@ func (self *PopupHandler) WithWaitingStatus(message string, f func(gocui.Task) e return nil } +func (self *PopupHandler) WithWaitingStatusSync(message string, f func() error) error { + self.withWaitingStatusSyncFn(message, f) + return nil +} + func (self *PopupHandler) Error(err error) error { if err == gocui.ErrQuit { return err diff --git a/pkg/gui/types/common.go b/pkg/gui/types/common.go index 84ad874f3..366b0fcf0 100644 --- a/pkg/gui/types/common.go +++ b/pkg/gui/types/common.go @@ -141,6 +141,7 @@ type IPopupHandler interface { // Shows a popup prompting the user for input. Prompt(opts PromptOpts) error WithWaitingStatus(message string, f func(gocui.Task) error) error + WithWaitingStatusSync(message string, f func() error) error Menu(opts CreateMenuOptions) error Toast(message string) GetPromptInput() string