From 20ca3421ab6d97375747f2cfb9b204425e2f3ab0 Mon Sep 17 00:00:00 2001 From: chenchen Date: Sun, 17 May 2026 13:11:37 +0800 Subject: [PATCH] fix(desktop): prevent empty blocks rendering in chat UI - Guard empty thinking events from creating blank ThinkingBlock rows - Skip empty assistant_text from history loading - Hide ToolResultBlock when content is empty (non-error) - Add component-level null returns as safety net Co-Authored-By: Claude Opus 4.6 --- cc-haha/desktop/src/components/chat/AssistantMessage.tsx | 2 ++ cc-haha/desktop/src/components/chat/ThinkingBlock.tsx | 2 ++ cc-haha/desktop/src/components/chat/ToolResultBlock.tsx | 2 ++ cc-haha/desktop/src/stores/chatStore.ts | 7 ++++++- 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/cc-haha/desktop/src/components/chat/AssistantMessage.tsx b/cc-haha/desktop/src/components/chat/AssistantMessage.tsx index f6d6013..23f8eb7 100644 --- a/cc-haha/desktop/src/components/chat/AssistantMessage.tsx +++ b/cc-haha/desktop/src/components/chat/AssistantMessage.tsx @@ -8,6 +8,8 @@ type Props = { } export function AssistantMessage({ content, isStreaming }: Props) { + if (!content.trim() && !isStreaming) return null + const documentLayout = shouldUseDocumentLayout(content) return ( diff --git a/cc-haha/desktop/src/components/chat/ThinkingBlock.tsx b/cc-haha/desktop/src/components/chat/ThinkingBlock.tsx index 3975525..f32b132 100644 --- a/cc-haha/desktop/src/components/chat/ThinkingBlock.tsx +++ b/cc-haha/desktop/src/components/chat/ThinkingBlock.tsx @@ -17,6 +17,8 @@ export function ThinkingBlock({ content, isActive = false }: { content: string; const firstLine = lines[0]?.replace(/\s+/g, ' ').trim() || '' const preview = firstLine.length > 80 ? firstLine.slice(0, 80) + '...' : firstLine + if (!content.trim() && !isActive) return null + return (
diff --git a/cc-haha/desktop/src/components/chat/ToolResultBlock.tsx b/cc-haha/desktop/src/components/chat/ToolResultBlock.tsx index 791ae1b..18062de 100644 --- a/cc-haha/desktop/src/components/chat/ToolResultBlock.tsx +++ b/cc-haha/desktop/src/components/chat/ToolResultBlock.tsx @@ -23,6 +23,8 @@ export function ToolResultBlock({ content, isError, toolName, standalone = true if (!standalone) return null const text = extractText(content) + if (!text.trim() && !isError) return null + const preview = text.slice(0, 200) const hasMore = text.length > 200 diff --git a/cc-haha/desktop/src/stores/chatStore.ts b/cc-haha/desktop/src/stores/chatStore.ts index be2b04b..9516b79 100644 --- a/cc-haha/desktop/src/stores/chatStore.ts +++ b/cc-haha/desktop/src/stores/chatStore.ts @@ -634,6 +634,9 @@ export const useChatStore = create((set, get) => ({ updated[updated.length - 1] = { ...last, content: last.content + msg.text } return { messages: updated, chatState: 'thinking', activeThinkingId: last.id, streamingText: '' } } + if (!msg.text) { + return { chatState: 'thinking', streamingText: '' } + } const id = nextId() return { messages: [...base, { id, type: 'thinking', content: msg.text, timestamp: Date.now() }], @@ -1037,7 +1040,9 @@ export function mapHistoryMessagesToUiMessages( continue } if (msg.type === 'assistant' && typeof msg.content === 'string') { - uiMessages.push({ id: msg.id || nextId(), type: 'assistant_text', content: msg.content, timestamp, model: msg.model }) + if (msg.content.trim()) { + uiMessages.push({ id: msg.id || nextId(), type: 'assistant_text', content: msg.content, timestamp, model: msg.model }) + } continue } if ((msg.type === 'assistant' || msg.type === 'tool_use') && Array.isArray(msg.content)) {