mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-18 13:23:33 +08:00
60 lines
2.0 KiB
TypeScript
60 lines
2.0 KiB
TypeScript
import { MarkdownRenderer } from '../markdown/MarkdownRenderer'
|
|
import { MessageActionBar } from './MessageActionBar'
|
|
import { InlineImageGallery } from './InlineImageGallery'
|
|
|
|
type Props = {
|
|
content: string
|
|
isStreaming?: boolean
|
|
}
|
|
|
|
export function AssistantMessage({ content, isStreaming }: Props) {
|
|
if (!content.trim()) return null
|
|
|
|
const documentLayout = shouldUseDocumentLayout(content)
|
|
|
|
return (
|
|
<div className="group mb-5 flex justify-start">
|
|
<div
|
|
data-message-shell="assistant"
|
|
data-layout={documentLayout ? 'document' : 'bubble'}
|
|
className={`flex min-w-0 flex-col items-start gap-2 ${
|
|
documentLayout
|
|
? 'w-full max-w-full'
|
|
: 'w-full max-w-[88%] sm:max-w-[80%] lg:max-w-[72%]'
|
|
}`}
|
|
>
|
|
<div className={`rounded-[20px] rounded-tl-[8px] border border-[var(--color-border)]/60 bg-[var(--color-surface)] px-4 py-3 text-sm text-[var(--color-text-primary)] shadow-sm ${
|
|
documentLayout ? 'w-full' : 'max-w-full'
|
|
}`}>
|
|
<MarkdownRenderer content={content} variant={documentLayout ? 'document' : 'default'} />
|
|
{!isStreaming && <InlineImageGallery text={content} />}
|
|
{isStreaming && (
|
|
<span className="ml-0.5 inline-block h-4 w-0.5 animate-shimmer bg-[var(--color-brand)] align-text-bottom" />
|
|
)}
|
|
</div>
|
|
|
|
<MessageActionBar
|
|
copyText={isStreaming ? undefined : content}
|
|
copyLabel="Copy reply"
|
|
align="start"
|
|
/>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function shouldUseDocumentLayout(content: string) {
|
|
const normalized = content.trim()
|
|
if (!normalized) return false
|
|
|
|
if (/```/.test(normalized)) return true
|
|
if (/^\s{0,3}(#{1,6}\s|[-*+]\s|\d+\.\s|>\s|\|.+\|)/m.test(normalized)) return true
|
|
|
|
const paragraphs = normalized
|
|
.split(/\n\s*\n/)
|
|
.map((chunk) => chunk.trim())
|
|
.filter(Boolean)
|
|
|
|
return paragraphs.length >= 2 || normalized.split('\n').filter((line) => line.trim()).length >= 8
|
|
}
|