From 670565c175b0eaec0d0c0ae28b5eba2086668f30 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Thu, 7 May 2026 14:11:57 +0200 Subject: [PATCH] Have renderAppStatus trigger a full layout when the appStatus width changes In 0d195077e4a3 we improved the performance of the status bar spinner by avoiding a layout. This is fine from one spinner tick to the next, but it's a problem when spinning starts or ends (or in the hypothetical case that the status text changes in the middle of the operation, which we never do in lazygit, but theoretically could). In this case a layout is needed so that the rest of the status bar gets pushed over appropriately (or moves back to the left when the spinner ends), and also so that the bottom line is shown or hidden properly for users who set gui.showBottomLine to false. To fix this, keep track of the status string width and force a layout whenever it changes. This includes the beginning and end of an operation when it changes from empty to non-empty or vice versa. There is currently no observable misbehavior from this bug, but that's only because we must have a HandleRender call somewhere that forces a full layout when an operation starts or ends. We will remove the Render() call from HandleRender at the end of this branch, at which point the misbehavior would be visible if we didn't fix it here. --- pkg/gui/controllers/helpers/app_status_helper.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pkg/gui/controllers/helpers/app_status_helper.go b/pkg/gui/controllers/helpers/app_status_helper.go index d71faeb65..83500d3a7 100644 --- a/pkg/gui/controllers/helpers/app_status_helper.go +++ b/pkg/gui/controllers/helpers/app_status_helper.go @@ -6,6 +6,7 @@ import ( "github.com/jesseduffield/lazygit/pkg/gocui" "github.com/jesseduffield/lazygit/pkg/gui/status" "github.com/jesseduffield/lazygit/pkg/gui/types" + "github.com/jesseduffield/lazygit/pkg/utils" ) type AppStatusHelper struct { @@ -93,13 +94,24 @@ func (self *AppStatusHelper) renderAppStatus() { self.c.OnWorker(func(_ gocui.Task) error { ticker := time.NewTicker(time.Millisecond * time.Duration(self.c.UserConfig().Gui.Spinner.Rate)) defer ticker.Stop() + prevAppStatus := "" for range ticker.C { appStatus, color := self.statusMgr().GetStatusString(self.c.UserConfig()) self.c.Views().AppStatus.FgColor = color - self.c.OnUIThreadContentOnly(func() error { + + update := self.c.OnUIThreadContentOnly + if utils.StringWidth(appStatus) != utils.StringWidth(prevAppStatus) { + // Need a full layout whenever the width of the status string changes. This can't + // happen during normal spinning because we validate that all spinner frames have + // the same width, so typically this will only be triggered at the beginning and end + // of a status, or if the status string changes midway for some reason. + update = self.c.OnUIThread + } + update(func() error { self.c.SetViewContent(self.c.Views().AppStatus, appStatus) return nil }) + prevAppStatus = appStatus if appStatus == "" { break