import { useState, useCallback } from 'react';
import { cn } from '@/lib/utils';
import { renderMarkdown } from '@/lib/markdown';
import { Bot, User, Copy, Trash2, ChevronDown, ChevronRight, RefreshCw, ArrowRight, Quote, Check, Brain } from 'lucide-react';
import type { Message } from '@/types';
type MessageState = 'streaming' | 'thinking' | 'done';
interface Props {
message: Message;
isLast?: boolean;
isThinking?: boolean;
onRegenerate?: (msgId: string) => void;
onContinue?: () => void;
onQuote?: (content: string) => void;
onDelete?: (msgId: string) => void;
}
function getState(msg: Message, isLast: boolean, isThinking: boolean): MessageState {
if (msg.role === 'user') return 'done';
if (isThinking && isLast) return 'thinking';
if (!msg.content && !msg.reasoningContent) return 'streaming';
return 'done';
}
export function ChatMessage({ message, isLast, isThinking, onRegenerate, onContinue, onQuote, onDelete }: Props) {
const isUser = message.role === 'user';
const isTool = message.role === 'tool';
const [copied, setCopied] = useState(false);
const [reasoningOpen, setReasoningOpen] = useState(false);
const state = getState(message, !!isLast, !!isThinking);
const handleCopy = useCallback(() => {
navigator.clipboard.writeText(message.content).then(() => {
setCopied(true);
setTimeout(() => setCopied(false), 2000);
});
}, [message.content]);
// Tool messages
if (isTool) {
let toolName = '';
try { const p = JSON.parse(message.content); toolName = p.tool || ''; } catch {}
return (
工具调用: {toolName}
);
}
const showActions = state === 'done' && !isUser && message.content;
return (
{/* Avatar */}
{isUser ? : }
{/* Body */}
{/* Thinking indicator */}
{state === 'thinking' && !message.content && !message.reasoningContent && (
)}
{/* Reasoning block (collapsible) */}
{message.reasoningContent && (
{(reasoningOpen || state !== 'done') && (
{message.reasoningContent}
)}
)}
{/* Main content bubble */}
{!(message.content === '(调用工具)' && state === 'done' && message.reasoningContent) && (
{state === 'streaming' && !message.content ? (
) : isUser ? (
{message.content}
) : (
)}
)}
{/* Actions - visible on hover or when done */}
{showActions && (
)}
);
}