|
1 | 1 | 'use client' |
2 | 2 |
|
3 | | -import { type ComponentPropsWithoutRef, useMemo } from 'react' |
| 3 | +import { type ComponentPropsWithoutRef, useEffect, useMemo, useRef } from 'react' |
4 | 4 | import { Streamdown } from 'streamdown' |
5 | 5 | import 'streamdown/styles.css' |
6 | 6 | import 'prismjs/components/prism-typescript' |
@@ -181,6 +181,18 @@ export function ChatContent({ |
181 | 181 | onOptionSelect, |
182 | 182 | smoothStreaming = true, |
183 | 183 | }: ChatContentProps) { |
| 184 | + const hydratedStreamingRef = useRef(isStreaming && content.trim().length > 0) |
| 185 | + const previousIsStreamingRef = useRef(isStreaming) |
| 186 | + |
| 187 | + useEffect(() => { |
| 188 | + if (!previousIsStreamingRef.current && isStreaming && content.trim().length > 0) { |
| 189 | + hydratedStreamingRef.current = true |
| 190 | + } else if (!isStreaming) { |
| 191 | + hydratedStreamingRef.current = false |
| 192 | + } |
| 193 | + previousIsStreamingRef.current = isStreaming |
| 194 | + }, [content, isStreaming]) |
| 195 | + |
184 | 196 | const rendered = useStreamingText(content, isStreaming && smoothStreaming) |
185 | 197 |
|
186 | 198 | const parsed = useMemo(() => parseSpecialTags(rendered, isStreaming), [rendered, isStreaming]) |
@@ -216,7 +228,7 @@ export function ChatContent({ |
216 | 228 | <Streamdown |
217 | 229 | mode={isStreaming ? undefined : 'static'} |
218 | 230 | isAnimating={isStreaming} |
219 | | - animated={isStreaming} |
| 231 | + animated={isStreaming && !hydratedStreamingRef.current} |
220 | 232 | components={MARKDOWN_COMPONENTS} |
221 | 233 | > |
222 | 234 | {rendered} |
|
0 commit comments