on main help sign in
fix: new/update message behavior (#1958)
commit6ba301e6e1214eb8f8f5fcf2d51af0781d8ef7be authorKujtim Hoxha <kujtimii.h@gmail.com> dateFri 23 Jan 2026, 15:47 (9 months ago) parentfb3eeb0
3 files changed+42−8
internal/ui/list/list.go+26 internal/ui/model/chat.go+2−2 internal/ui/model/ui.go+14−6
internal/ui/list/list.go+26
@@ -75,6 +75,32 @@ func (l *List) Gap() int {
7575 return l.gap
7676}
7777
78+// AtBottom returns whether the list is scrolled to the bottom.
79+func (l *List) AtBottom() bool {
80+ if len(l.items) == 0 {
81+ return true
82+ }
83+
84+ // Calculate total height of all items from the bottom.
85+ var totalHeight int
86+ for i := len(l.items) - 1; i >= 0; i-- {
87+ item := l.getItem(i)
88+ totalHeight += item.height
89+ if l.gap > 0 && i < len(l.items)-1 {
90+ totalHeight += l.gap
91+ }
92+ if totalHeight >= l.height {
93+ // This is the expected bottom position.
94+ expectedIdx := i
95+ expectedLine := totalHeight - l.height
96+ return l.offsetIdx == expectedIdx && l.offsetLine >= expectedLine
97+ }
98+ }
99+
100+ // All items fit in viewport - we're at bottom if at top.
101+ return l.offsetIdx == 0 && l.offsetLine == 0
102+}
103+
78104// SetReverse shows the list in reverse order.
79105func (l *List) SetReverse(reverse bool) {
80106 l.reverse = reverse
internal/ui/model/chat.go+2−2
@@ -481,9 +481,9 @@ func (m *Chat) HasHighlight() bool {
481481 return startItemIdx >= 0 && endItemIdx >= 0 && (startLine != endLine || startCol != endCol)
482482}
483483
484−// HighlighContent returns the currently highlighted content based on the mouse
484+// HighlightContent returns the currently highlighted content based on the mouse
485485// selection. It returns an empty string if no content is highlighted.
486−func (m *Chat) HighlighContent() string {
486+func (m *Chat) HighlightContent() string {
487487 startItemIdx, startLine, startCol, endItemIdx, endLine, endCol := m.getHighlightRange()
488488 if startItemIdx < 0 || endItemIdx < 0 || startLine == endLine && startCol == endCol {
489489 return ""
internal/ui/model/ui.go+14−6
@@ -873,6 +873,7 @@ func (m *UI) appendSessionMessage(msg message.Message) tea.Cmd {
873873func (m *UI) updateSessionMessage(msg message.Message) tea.Cmd {
874874 var cmds []tea.Cmd
875875 existingItem := m.chat.MessageItem(msg.ID)
876+ atBottom := m.chat.list.AtBottom()
876877
877878 if existingItem != nil {
878879 if assistantItem, ok := existingItem.(*chat.AssistantMessageItem); ok {
@@ -893,9 +894,6 @@ func (m *UI) updateSessionMessage(msg message.Message) tea.Cmd {
893894 if infoItem := m.chat.MessageItem(chat.AssistantInfoID(msg.ID)); infoItem == nil {
894895 newInfoItem := chat.NewAssistantInfoItem(m.com.Styles, &msg, time.Unix(m.lastUserMessageTime, 0))
895896 m.chat.AppendMessages(newInfoItem)
896− if cmd := m.chat.ScrollToBottomAndAnimate(); cmd != nil {
897− cmds = append(cmds, cmd)
898− }
899897 }
900898 }
901899
@@ -922,9 +920,12 @@ func (m *UI) updateSessionMessage(msg message.Message) tea.Cmd {
922920 }
923921 }
924922 }
923+
925924 m.chat.AppendMessages(items...)
926− if cmd := m.chat.ScrollToBottomAndAnimate(); cmd != nil {
927− cmds = append(cmds, cmd)
925+ if atBottom {
926+ if cmd := m.chat.ScrollToBottomAndAnimate(); cmd != nil {
927+ cmds = append(cmds, cmd)
928+ }
928929 }
929930
930931 return tea.Batch(cmds...)
@@ -934,6 +935,7 @@ func (m *UI) updateSessionMessage(msg message.Message) tea.Cmd {
934935func (m *UI) handleChildSessionMessage(event pubsub.Event[message.Message]) tea.Cmd {
935936 var cmds []tea.Cmd
936937
938+ atBottom := m.chat.list.AtBottom()
937939 // Only process messages with tool calls or results.
938940 if len(event.Payload.ToolCalls()) == 0 && len(event.Payload.ToolResults()) == 0 {
939941 return nil
@@ -1013,6 +1015,12 @@ func (m *UI) handleChildSessionMessage(event pubsub.Event[message.Message]) tea.
10131015 // Update the chat so it updates the index map for animations to work as expected
10141016 m.chat.UpdateNestedToolIDs(toolCallID)
10151017
1018+ if atBottom {
1019+ if cmd := m.chat.ScrollToBottomAndAnimate(); cmd != nil {
1020+ cmds = append(cmds, cmd)
1021+ }
1022+ }
1023+
10161024 return tea.Batch(cmds...)
10171025}
10181026
@@ -2905,7 +2913,7 @@ func (m *UI) runMCPPrompt(clientID, promptID string, arguments map[string]string
29052913}
29062914
29072915func (m *UI) copyChatHighlight() tea.Cmd {
2908− text := m.chat.HighlighContent()
2916+ text := m.chat.HighlightContent()
29092917 return tea.Sequence(
29102918 tea.SetClipboard(text),
29112919 func() tea.Msg {