summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTimo Clasen <[email protected]>2025-08-19 22:30:54 +0200
committerGitHub <[email protected]>2025-08-19 15:30:54 -0500
commit4913ee6afdb29d9ffbc27fd417aabbf35aaf1749 (patch)
tree250c358ec7ff889a891a340980f618dade8c2197
parentc59ded82b3374b5f11e7c5f1eaee4b27346f697c (diff)
downloadopencode-4913ee6afdb29d9ffbc27fd417aabbf35aaf1749.tar.gz
opencode-4913ee6afdb29d9ffbc27fd417aabbf35aaf1749.zip
fix(TUI): make it less shimmer (#2076)
-rw-r--r--packages/tui/internal/components/chat/editor.go14
-rw-r--r--packages/tui/internal/components/chat/message.go8
-rw-r--r--packages/tui/internal/components/chat/messages.go25
3 files changed, 36 insertions, 11 deletions
diff --git a/packages/tui/internal/components/chat/editor.go b/packages/tui/internal/components/chat/editor.go
index 72daf2886..c5ecdc21d 100644
--- a/packages/tui/internal/components/chat/editor.go
+++ b/packages/tui/internal/components/chat/editor.go
@@ -382,11 +382,9 @@ func (m *editorComponent) Content() string {
status = "waiting for permission"
}
if m.interruptKeyInDebounce && m.app.CurrentPermission.ID == "" {
- bright := t.Accent()
- if status == "waiting for permission" {
- bright = t.Warning()
- }
- hint = util.Shimmer(status, t.Background(), t.TextMuted(), bright) + m.spinner.View() + muted(
+ hint = muted(
+ status,
+ ) + m.spinner.View() + muted(
" ",
) + base(
keyText+" again",
@@ -394,11 +392,7 @@ func (m *editorComponent) Content() string {
" interrupt",
)
} else {
- bright := t.Accent()
- if status == "waiting for permission" {
- bright = t.Warning()
- }
- hint = util.Shimmer(status, t.Background(), t.TextMuted(), bright) + m.spinner.View()
+ hint = muted(status) + m.spinner.View()
if m.app.CurrentPermission.ID == "" {
hint += muted(" ") + base(keyText) + muted(" interrupt")
}
diff --git a/packages/tui/internal/components/chat/message.go b/packages/tui/internal/components/chat/message.go
index 65c476e15..9a1531fb0 100644
--- a/packages/tui/internal/components/chat/message.go
+++ b/packages/tui/internal/components/chat/message.go
@@ -213,6 +213,7 @@ func renderText(
extra string,
isThinking bool,
isQueued bool,
+ shimmer bool,
fileParts []opencode.FilePart,
agentParts []opencode.AgentPart,
toolCalls ...opencode.ToolPart,
@@ -234,7 +235,12 @@ func renderText(
}
content = util.ToMarkdown(text, width, backgroundColor)
if isThinking {
- label := util.Shimmer("Thinking...", backgroundColor, t.TextMuted(), t.Accent())
+ var label string
+ if shimmer {
+ label = util.Shimmer("Thinking...", backgroundColor, t.TextMuted(), t.Accent())
+ } else {
+ label = styles.NewStyle().Background(backgroundColor).Foreground(t.TextMuted()).Render("Thinking...")
+ }
label = styles.NewStyle().Background(backgroundColor).Width(width - 6).Render(label)
content = label + "\n\n" + content
} else if strings.TrimSpace(text) == "Generating..." {
diff --git a/packages/tui/internal/components/chat/messages.go b/packages/tui/internal/components/chat/messages.go
index 83e3e33b5..97c529721 100644
--- a/packages/tui/internal/components/chat/messages.go
+++ b/packages/tui/internal/components/chat/messages.go
@@ -336,6 +336,25 @@ func (m *messagesComponent) renderView() tea.Cmd {
width := m.width // always use full width
+ // Find the last streaming ReasoningPart to only shimmer that one
+ lastStreamingReasoningID := ""
+ if m.showThinkingBlocks {
+ for mi := len(m.app.Messages) - 1; mi >= 0 && lastStreamingReasoningID == ""; mi-- {
+ if _, ok := m.app.Messages[mi].Info.(opencode.AssistantMessage); !ok {
+ continue
+ }
+ parts := m.app.Messages[mi].Parts
+ for pi := len(parts) - 1; pi >= 0; pi-- {
+ if rp, ok := parts[pi].(opencode.ReasoningPart); ok {
+ if strings.TrimSpace(rp.Text) != "" && rp.Time.End == 0 {
+ lastStreamingReasoningID = rp.ID
+ break
+ }
+ }
+ }
+ }
+ }
+
reverted := false
revertedMessageCount := 0
revertedToolCount := 0
@@ -437,6 +456,7 @@ func (m *messagesComponent) renderView() tea.Cmd {
files,
false,
isQueued,
+ false,
fileParts,
agentParts,
)
@@ -513,6 +533,7 @@ func (m *messagesComponent) renderView() tea.Cmd {
"",
false,
false,
+ false,
[]opencode.FilePart{},
[]opencode.AgentPart{},
toolCallParts...,
@@ -530,6 +551,7 @@ func (m *messagesComponent) renderView() tea.Cmd {
"",
false,
false,
+ false,
[]opencode.FilePart{},
[]opencode.AgentPart{},
toolCallParts...,
@@ -600,6 +622,7 @@ func (m *messagesComponent) renderView() tea.Cmd {
}
if part.Text != "" {
text := part.Text
+ shimmer := part.Time.End == 0 && part.ID == lastStreamingReasoningID
content = renderText(
m.app,
message.Info,
@@ -610,6 +633,7 @@ func (m *messagesComponent) renderView() tea.Cmd {
"",
true,
false,
+ shimmer,
[]opencode.FilePart{},
[]opencode.AgentPart{},
)
@@ -644,6 +668,7 @@ func (m *messagesComponent) renderView() tea.Cmd {
"",
false,
false,
+ false,
[]opencode.FilePart{},
[]opencode.AgentPart{},
)