50 lines
1.4 KiB
TypeScript
50 lines
1.4 KiB
TypeScript
"use client";
|
||
/**
|
||
* MessageBubble 消息气泡(容器)
|
||
*
|
||
* 原始 Dart: lib/ui/chat/widgets/message_bubble.dart(52 行)
|
||
*
|
||
* 组成(从左到右):
|
||
* - AI:[Avatar] [Content] [占位 spacer]
|
||
* - 用户:[占位 spacer] [Content] [Avatar]
|
||
*/
|
||
import { useUserState } from "@/stores/user/user-context";
|
||
|
||
import { MessageAvatar } from "./message-avatar";
|
||
import { MessageContent } from "./message-content";
|
||
import styles from "./chat-area.module.css";
|
||
|
||
export interface MessageBubbleProps {
|
||
content: string;
|
||
imageUrl?: string | null;
|
||
isFromAI: boolean;
|
||
}
|
||
|
||
export function MessageBubble({ content, imageUrl, isFromAI }: MessageBubbleProps) {
|
||
const { avatarUrl } = useUserState();
|
||
|
||
if (isFromAI) {
|
||
return (
|
||
<div className={styles.bubbleRowAi} aria-label="AI message">
|
||
<MessageAvatar isFromAI={true} />
|
||
<div style={{ width: 8 }} />
|
||
<MessageContent
|
||
content={content}
|
||
imageUrl={imageUrl}
|
||
isFromAI={true}
|
||
/>
|
||
<div style={{ width: 43 }} /> {/* 占位:保持与头像宽度一致 */}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<div className={styles.bubbleRowUser} aria-label="User message">
|
||
<div style={{ width: 43 }} /> {/* 占位 */}
|
||
<MessageContent content={content} imageUrl={imageUrl} isFromAI={false} />
|
||
<div style={{ width: 8 }} />
|
||
<MessageAvatar isFromAI={false} userAvatarUrl={avatarUrl} />
|
||
</div>
|
||
);
|
||
}
|