diff --git a/pkg/gui/background.go b/pkg/gui/background.go index 6eaf041d4..aa0726568 100644 --- a/pkg/gui/background.go +++ b/pkg/gui/background.go @@ -17,6 +17,9 @@ type BackgroundRoutineMgr struct { // we typically want to pause some things that are running like background // file refreshes pauseBackgroundRefreshes bool + + // a channel to trigger an immediate background fetch; we use this when switching repos + triggerFetch chan struct{} } func (self *BackgroundRoutineMgr) PauseBackgroundRefreshes(pause bool) { @@ -86,7 +89,7 @@ func (self *BackgroundRoutineMgr) startBackgroundFetch() { _ = fetch() userConfig := self.gui.UserConfig() - self.goEvery(time.Second*time.Duration(userConfig.Refresher.FetchInterval), self.gui.stopChan, fetch) + self.triggerFetch = self.goEvery(time.Second*time.Duration(userConfig.Refresher.FetchInterval), self.gui.stopChan, fetch) } func (self *BackgroundRoutineMgr) startBackgroundFilesRefresh(refreshInterval int) { @@ -98,29 +101,40 @@ func (self *BackgroundRoutineMgr) startBackgroundFilesRefresh(refreshInterval in }) } -func (self *BackgroundRoutineMgr) goEvery(interval time.Duration, stop chan struct{}, function func() error) { +// returns a channel that can be used to trigger the callback immediately +func (self *BackgroundRoutineMgr) goEvery(interval time.Duration, stop chan struct{}, function func() error) chan struct{} { done := make(chan struct{}) + retrigger := make(chan struct{}) go utils.Safe(func() { ticker := time.NewTicker(interval) defer ticker.Stop() + doit := func() { + if self.pauseBackgroundRefreshes { + return + } + self.gui.c.OnWorker(func(gocui.Task) error { + _ = function() + done <- struct{}{} + return nil + }) + // waiting so that we don't bunch up refreshes if the refresh takes longer than the + // interval, or if a retrigger comes in while we're still processing a timer-based one + // (or vice versa) + <-done + } for { select { case <-ticker.C: - if self.pauseBackgroundRefreshes { - continue - } - self.gui.c.OnWorker(func(gocui.Task) error { - _ = function() - done <- struct{}{} - return nil - }) - // waiting so that we don't bunch up refreshes if the refresh takes longer than the interval - <-done + doit() + case <-retrigger: + ticker.Reset(interval) + doit() case <-stop: return } } }) + return retrigger } func (self *BackgroundRoutineMgr) backgroundFetch() (err error) { @@ -134,3 +148,9 @@ func (self *BackgroundRoutineMgr) backgroundFetch() (err error) { return err } + +func (self *BackgroundRoutineMgr) triggerImmediateFetch() { + if self.triggerFetch != nil { + self.triggerFetch <- struct{}{} + } +} diff --git a/pkg/gui/controllers.go b/pkg/gui/controllers.go index 2f729a7b5..702ed826d 100644 --- a/pkg/gui/controllers.go +++ b/pkg/gui/controllers.go @@ -26,7 +26,7 @@ func (gui *Gui) resetHelpersAndControllers() { helperCommon := gui.c recordDirectoryHelper := helpers.NewRecordDirectoryHelper(helperCommon) - reposHelper := helpers.NewRecentReposHelper(helperCommon, recordDirectoryHelper, gui.onNewRepo) + reposHelper := helpers.NewRecentReposHelper(helperCommon, recordDirectoryHelper, gui.onSwitchToNewRepo) rebaseHelper := helpers.NewMergeAndRebaseHelper(helperCommon) refsHelper := helpers.NewRefsHelper(helperCommon, rebaseHelper) suggestionsHelper := helpers.NewSuggestionsHelper(helperCommon) diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 3610c9c23..b4b295430 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -305,6 +305,14 @@ func (self *GuiRepoState) GetSplitMainPanel() bool { return self.SplitMainPanel } +func (gui *Gui) onSwitchToNewRepo(startArgs appTypes.StartArgs, contextKey types.ContextKey) error { + err := gui.onNewRepo(startArgs, contextKey) + if err == nil && gui.UserConfig().Git.AutoFetch && gui.UserConfig().Refresher.FetchInterval > 0 { + gui.BackgroundRoutineMgr.triggerImmediateFetch() + } + return err +} + func (gui *Gui) onNewRepo(startArgs appTypes.StartArgs, contextKey types.ContextKey) error { var err error gui.git, err = commands.NewGitCommand(