Improve performance of spinner in Synchronized events

Instead of redrawing the two views on each tick, only redraw the spinner
This commit is contained in:
Antoine Gaudreau Simard authored and Stefan Haller committed 2026-05-06 20:38:53 +02:00
1 parent 5dcc93e8cc
commit b7edcbad3a
3 files changed
+17 -27

No files matched your search

+2 -2
View File
@@ -64,7 +64,7 @@ func TestFlushContentOnly_SkipsUntaintedViews(t *testing.T) {
assert.False(t, main.IsTainted(), "main view should not be tainted (was not modified)")
// flushContentOnly should succeed and clear status tainted flag
assert.NoError(t, g.flushContentOnly())
assert.NoError(t, g.flushContentOnly(g.views))
assert.False(t, status.IsTainted(), "status view should not be tainted after flushContentOnly")
assert.False(t, main.IsTainted(), "main view should not be tainted after flushContentOnly")
@@ -75,7 +75,7 @@ func TestFlushContentOnly_WritesCorrectContent(t *testing.T) {
status, _ := setupViews(t, g)
status.SetContent("Fetching |")
assert.NoError(t, g.flushContentOnly())
assert.NoError(t, g.flushContentOnly(g.views))
assert.Equal(t, "Fetching |", status.Buffer())
}
+14 -24
View File
@@ -779,7 +779,7 @@ func (g *Gui) processEvent() error {
contentOnly = contentOnly && remainingContentOnly
if contentOnly {
return g.flushContentOnly()
return g.flushContentOnly(g.views)
}
return g.flush()
}
@@ -1167,32 +1167,11 @@ func (g *Gui) flush() error {
return nil
}
func (g *Gui) ForceLayoutAndRedraw() error {
return g.flush()
}
// force redrawing one or more views outside of the normal main loop. Useful during longer
// operations that block the main thread, to update a spinner in a status view.
func (g *Gui) ForceRedrawViews(views ...*View) error {
for _, m := range g.managers {
if err := m.Layout(g); err != nil {
return err
}
}
for _, v := range views {
v.draw()
}
Screen.Show()
return nil
}
// Redraws only tainted views and skips the layout pass.
// tcell's cell-level dirty tracking ensures only
// actually-changed cells are emitted to the terminal.
func (g *Gui) flushContentOnly() error {
for _, v := range g.views {
func (g *Gui) flushContentOnly(views []*View) error {
for _, v := range views {
if !v.tainted {
continue
}
@@ -1205,6 +1184,17 @@ func (g *Gui) flushContentOnly() error {
return nil
}
func (g *Gui) ForceLayoutAndRedraw() error {
return g.flush()
}
// Redraws only tainted views outside of the normal main
// loop, without a layout pass. Useful during longer operations that block the
// main thread, e.g. to update a spinner in a status view.
func (g *Gui) ForceFlushViewsContentOnly(views []*View) error {
return g.flushContentOnly(views)
}
// draw manages the cursor and calls the draw function of a view.
func (g *Gui) draw(v *View) error {
if g.suspended {
@@ -136,7 +136,7 @@ func (self *AppStatusHelper) renderAppStatusSync(stop chan struct{}) {
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...)
_ = self.c.GocuiGui().ForceFlushViewsContentOnly(bottomLineViews)
case <-stop:
break outer
}