on main help sign in
fix: make sure to make rendered string concurrency sage
cf72cb8Kujtim Hoxha
internal/tui/exp/list/list.go+9−2
@@ -3,6 +3,7 @@ package list
3import (
3import (
4 "slices"
4 "slices"
5 "strings"
5 "strings"
6+ "sync"
6
7
7 "github.com/charmbracelet/bubbles/v2/key"
8 "github.com/charmbracelet/bubbles/v2/key"
8 tea "github.com/charmbracelet/bubbletea/v2"
9 tea "github.com/charmbracelet/bubbletea/v2"
@@ -90,6 +91,7 @@ type list[T Item] struct {
90
91
91 renderedItems *csync.Map[string, renderedItem]
92 renderedItems *csync.Map[string, renderedItem]
92
93
94+ renderMu sync.Mutex
93 rendered string
95 rendered string
94
96
95 movingByItem bool
97 movingByItem bool
@@ -328,7 +330,9 @@ func (l *list[T]) render() tea.Cmd {
328 // we are not rendering the first time
330 // we are not rendering the first time
329 if l.rendered != "" {
331 if l.rendered != "" {
330 // rerender everything will mostly hit cache
332 // rerender everything will mostly hit cache
333+ l.renderMu.Lock()
331 l.rendered, _ = l.renderIterator(0, false, "")
334 l.rendered, _ = l.renderIterator(0, false, "")
335+ l.renderMu.Unlock()
332 if l.direction == DirectionBackward {
336 if l.direction == DirectionBackward {
333 l.recalculateItemPositions()
337 l.recalculateItemPositions()
334 }
338 }
@@ -338,9 +342,10 @@ func (l *list[T]) render() tea.Cmd {
338 }
342 }
339 return focusChangeCmd
343 return focusChangeCmd
340 }
344 }
345+ l.renderMu.Lock()
341 rendered, finishIndex := l.renderIterator(0, true, "")
346 rendered, finishIndex := l.renderIterator(0, true, "")
342 l.rendered = rendered
347 l.rendered = rendered
343−
348+ l.renderMu.Unlock()
344 // recalculate for the initial items
349 // recalculate for the initial items
345 if l.direction == DirectionBackward {
350 if l.direction == DirectionBackward {
346 l.recalculateItemPositions()
351 l.recalculateItemPositions()
@@ -348,7 +353,10 @@ func (l *list[T]) render() tea.Cmd {
348 renderCmd := func() tea.Msg {
353 renderCmd := func() tea.Msg {
349 l.offset = 0
354 l.offset = 0
350 // render the rest
355 // render the rest
356+
357+ l.renderMu.Lock()
351 l.rendered, _ = l.renderIterator(finishIndex, false, l.rendered)
358 l.rendered, _ = l.renderIterator(finishIndex, false, l.rendered)
359+ l.renderMu.Unlock()
352 // needed for backwards
360 // needed for backwards
353 if l.direction == DirectionBackward {
361 if l.direction == DirectionBackward {
354 l.recalculateItemPositions()
362 l.recalculateItemPositions()
@@ -357,7 +365,6 @@ func (l *list[T]) render() tea.Cmd {
357 if l.focused {
365 if l.focused {
358 l.scrollToSelection()
366 l.scrollToSelection()
359 }
367 }
360−
361 return nil
368 return nil
362 }
369 }
363 return tea.Batch(focusChangeCmd, renderCmd)
370 return tea.Batch(focusChangeCmd, renderCmd)