From cb6642b5fb1a67cfe5feb8052df36c7aa55f1c40 Mon Sep 17 00:00:00 2001 From: Kujtim Hoxha Date: Sun, 3 Aug 2025 22:56:26 +0200 Subject: [PATCH 1/3] fix: sidebar files jumping --- internal/tui/components/chat/sidebar/sidebar.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/tui/components/chat/sidebar/sidebar.go b/internal/tui/components/chat/sidebar/sidebar.go index 1f5fd2a672e3d643efbed4ca35b08ed88c55d2eb..ccbc9330f979acd0750279a278ebb8748e5a32cf 100644 --- a/internal/tui/components/chat/sidebar/sidebar.go +++ b/internal/tui/components/chat/sidebar/sidebar.go @@ -400,6 +400,9 @@ func (m *sidebarCmp) filesBlockCompact(maxWidth int) string { fileList := []string{section, ""} sort.Slice(files, func(i, j int) bool { + if files[i].History.latestVersion.CreatedAt == files[j].History.latestVersion.CreatedAt { + return files[i].FilePath < files[j].FilePath + } return files[i].History.latestVersion.CreatedAt > files[j].History.latestVersion.CreatedAt }) @@ -626,8 +629,11 @@ func (m *sidebarCmp) filesBlock() string { } fileList := []string{section, ""} - // order files by the latest version's created time + // order files by the latest version's created time, then by path for stability sort.Slice(files, func(i, j int) bool { + if files[i].History.latestVersion.CreatedAt == files[j].History.latestVersion.CreatedAt { + return files[i].FilePath < files[j].FilePath + } return files[i].History.latestVersion.CreatedAt > files[j].History.latestVersion.CreatedAt }) From dbb998c76e336b6e57a57a11a5478726a3ad7c93 Mon Sep 17 00:00:00 2001 From: Kujtim Hoxha Date: Sun, 3 Aug 2025 22:56:42 +0200 Subject: [PATCH 2/3] fix: width related commands not showing --- internal/tui/components/dialogs/commands/commands.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/tui/components/dialogs/commands/commands.go b/internal/tui/components/dialogs/commands/commands.go index 6c292ce7fd16eb671abc02bf577c6fc420dbd283..139ec1ea5ac0461b0c4fa8de65c61c7293b8ac50 100644 --- a/internal/tui/components/dialogs/commands/commands.go +++ b/internal/tui/components/dialogs/commands/commands.go @@ -119,7 +119,10 @@ func (c *commandDialogCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case tea.WindowSizeMsg: c.wWidth = msg.Width c.wHeight = msg.Height - return c, c.commandList.SetSize(c.listWidth(), c.listHeight()) + return c, tea.Batch( + c.SetCommandType(c.commandType), + c.commandList.SetSize(c.listWidth(), c.listHeight()), + ) case tea.KeyPressMsg: switch { case key.Matches(msg, c.keyMap.Select): @@ -318,7 +321,6 @@ func (c *commandDialogCmp) defaultCommands() []Command { }) } } - // Only show toggle compact mode command if window width is larger than compact breakpoint (90) if c.wWidth > 120 && c.sessionID != "" { commands = append(commands, Command{ From cf72cb88b53588d77725e3af4e49524479b885b2 Mon Sep 17 00:00:00 2001 From: Kujtim Hoxha Date: Sun, 3 Aug 2025 22:57:04 +0200 Subject: [PATCH 3/3] fix: make sure to make rendered string concurrency sage --- internal/tui/exp/list/list.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/internal/tui/exp/list/list.go b/internal/tui/exp/list/list.go index 44a849fcf6027813feb49be5a68c401f4253eeb6..4bf8b2dbbc4ffde261465c8ebd655a26f2344852 100644 --- a/internal/tui/exp/list/list.go +++ b/internal/tui/exp/list/list.go @@ -3,6 +3,7 @@ package list import ( "slices" "strings" + "sync" "github.com/charmbracelet/bubbles/v2/key" tea "github.com/charmbracelet/bubbletea/v2" @@ -90,6 +91,7 @@ type list[T Item] struct { renderedItems *csync.Map[string, renderedItem] + renderMu sync.Mutex rendered string movingByItem bool @@ -328,7 +330,9 @@ func (l *list[T]) render() tea.Cmd { // we are not rendering the first time if l.rendered != "" { // rerender everything will mostly hit cache + l.renderMu.Lock() l.rendered, _ = l.renderIterator(0, false, "") + l.renderMu.Unlock() if l.direction == DirectionBackward { l.recalculateItemPositions() } @@ -338,9 +342,10 @@ func (l *list[T]) render() tea.Cmd { } return focusChangeCmd } + l.renderMu.Lock() rendered, finishIndex := l.renderIterator(0, true, "") l.rendered = rendered - + l.renderMu.Unlock() // recalculate for the initial items if l.direction == DirectionBackward { l.recalculateItemPositions() @@ -348,7 +353,10 @@ func (l *list[T]) render() tea.Cmd { renderCmd := func() tea.Msg { l.offset = 0 // render the rest + + l.renderMu.Lock() l.rendered, _ = l.renderIterator(finishIndex, false, l.rendered) + l.renderMu.Unlock() // needed for backwards if l.direction == DirectionBackward { l.recalculateItemPositions() @@ -357,7 +365,6 @@ func (l *list[T]) render() tea.Cmd { if l.focused { l.scrollToSelection() } - return nil } return tea.Batch(focusChangeCmd, renderCmd)