Skip to content

Commit def48ae

Browse files
committed
Fix TUI scrolling
Only scroll if needed, also make sure that the user can scroll on their own and we don't fight it Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
1 parent 17a95a7 commit def48ae

2 files changed

Lines changed: 21 additions & 26 deletions

File tree

pkg/tui/components/messages/messages.go

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ type Model interface {
4040
AddShellOutputMessage(content string) tea.Cmd
4141
AddSystemMessage(content string) tea.Cmd
4242
PlainTextTranscript() string
43+
IsAtBottom() bool
4344
}
4445

4546
// renderedItem represents a cached rendered message with position information
@@ -426,8 +427,8 @@ func (m *model) invalidateAllItems() {
426427
m.totalHeight = 0
427428
}
428429

429-
// isAtBottom returns true if the viewport is at the bottom
430-
func (m *model) isAtBottom() bool {
430+
// IsAtBottom returns true if the viewport is at the bottom
431+
func (m *model) IsAtBottom() bool {
431432
if len(m.messages) == 0 {
432433
return true
433434
}
@@ -437,6 +438,11 @@ func (m *model) isAtBottom() bool {
437438
return m.scrollOffset >= maxScrollOffset
438439
}
439440

441+
// isAtBottom is kept as a private method for internal use
442+
func (m *model) isAtBottom() bool {
443+
return m.IsAtBottom()
444+
}
445+
440446
// AddUserMessage adds a user message to the chat
441447
func (m *model) AddUserMessage(content string) tea.Cmd {
442448
return m.addMessage(&types.Message{
@@ -568,49 +574,32 @@ func (m *model) AppendToLastMessage(agentName string, messageType types.MessageT
568574
if len(m.messages) == 0 {
569575
return nil
570576
}
577+
571578
lastIdx := len(m.messages) - 1
572579
lastMsg := &m.messages[lastIdx]
573580

574581
if lastMsg.Type == messageType {
575-
wasAtBottom := m.isAtBottom()
576582
lastMsg.Content += content
577-
lastMsg.Sender = agentName
578-
// Update the corresponding view
579583
m.views[lastIdx].(message.Model).SetMessage(lastMsg)
580584
m.invalidateItem(lastIdx)
581-
582-
var cmds []tea.Cmd
583-
if wasAtBottom {
584-
cmds = append(cmds, func() tea.Msg {
585-
m.scrollToBottom()
586-
return nil
587-
})
588-
}
589-
return tea.Batch(cmds...)
585+
return nil
590586
} else {
591587
// Create new assistant message
592588
msg := types.Message{
593589
Type: messageType,
594590
Content: content,
595591
Sender: agentName,
596592
}
597-
wasAtBottom := m.isAtBottom()
598593
m.messages = append(m.messages, msg)
599594

600595
view := m.createMessageView(&msg)
601596
m.views = append(m.views, view)
602597

603-
var cmds []tea.Cmd
598+
var cmd tea.Cmd
604599
if initCmd := view.Init(); initCmd != nil {
605-
cmds = append(cmds, initCmd)
606-
}
607-
if wasAtBottom {
608-
cmds = append(cmds, func() tea.Msg {
609-
m.scrollToBottom()
610-
return nil
611-
})
600+
cmd = initCmd
612601
}
613-
return tea.Batch(cmds...)
602+
return cmd
614603
}
615604
}
616605

pkg/tui/page/chat/chat.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,10 +203,16 @@ func (p *chatPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
203203
return p, tea.Batch(cmd, p.messages.ScrollToBottom(), spinnerCmd)
204204
case *runtime.AgentChoiceEvent:
205205
cmd := p.messages.AppendToLastMessage(msg.AgentName, types.MessageTypeAssistant, msg.Content)
206-
return p, tea.Batch(cmd, p.messages.ScrollToBottom())
206+
if p.messages.IsAtBottom() {
207+
return p, tea.Batch(cmd, p.messages.ScrollToBottom())
208+
}
209+
return p, cmd
207210
case *runtime.AgentChoiceReasoningEvent:
208211
cmd := p.messages.AppendToLastMessage(msg.AgentName, types.MessageTypeAssistantReasoning, msg.Content)
209-
return p, tea.Batch(cmd, p.messages.ScrollToBottom())
212+
if p.messages.IsAtBottom() {
213+
return p, tea.Batch(cmd, p.messages.ScrollToBottom())
214+
}
215+
return p, cmd
210216
case *runtime.SessionTitleEvent:
211217
p.sessionTitle = msg.Title
212218
case *runtime.TokenUsageEvent:

0 commit comments

Comments
 (0)