52 lines
2.1 KiB
TypeScript
52 lines
2.1 KiB
TypeScript
import { memo, useEffect, useState } from "react";
|
|
|
|
import type { Message } from "../lib/messages";
|
|
import { AssistantMarkdown } from "./AssistantMarkdown";
|
|
|
|
function Bubble({ message, userName }: { message: Message; userName: string }) {
|
|
const [expiredText, setExpiredText] = useState<string | null>(null);
|
|
useEffect(() => {
|
|
if (message.partial) {
|
|
return;
|
|
}
|
|
const timer = setTimeout(() => {
|
|
setExpiredText(message.text);
|
|
}, 5000);
|
|
return () => {
|
|
clearTimeout(timer);
|
|
};
|
|
}, [message.text, message.partial]);
|
|
if (!message.partial && expiredText === message.text) {
|
|
return null;
|
|
}
|
|
return (
|
|
<div
|
|
className={`pointer-events-auto max-w-full rounded-panel border border-solid border-line bg-surface-raised px-3.5 py-2.5 text-[14px] leading-[1.5] wrap-anywhere shadow-[0_4px_18px_rgb(0_0_0/0.32)] compact:text-[13px] ${message.role === "assistant" ? "self-end" : "self-start"} ${message.role === "tool" ? "flex items-center gap-2 font-mono text-[13px] text-muted" : ""}`}
|
|
>
|
|
<div
|
|
className={`mb-1 font-mono text-[11px] font-medium tracking-[0.1em] uppercase opacity-70 compact:text-[10px] ${message.role === "user" ? "text-voice-user" : message.role === "assistant" ? "text-voice-assistant" : "text-voice-tool"}`}
|
|
>
|
|
{message.role === "user" ? userName : message.role === "tool" ? "Herramienta" : "Vocero"}
|
|
</div>
|
|
{message.role === "assistant" ? (
|
|
<AssistantMarkdown text={message.text} className="max-h-60 overflow-auto" />
|
|
) : (
|
|
<div className="max-h-60 overflow-auto">{message.role === "tool" ? message.toolName : message.text}</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
export const Bubbles = memo(function Bubbles({ messages, userName }: { messages: Message[]; userName: string }) {
|
|
return (
|
|
<div
|
|
className="pointer-events-none fixed top-24 right-7 z-100 flex w-[min(300px,calc(100vw-56px))] flex-col gap-2 compact:hidden"
|
|
aria-hidden="true"
|
|
inert
|
|
>
|
|
{messages.slice(-3).map((message) => (
|
|
<Bubble key={message.id} message={message} userName={userName} />
|
|
))}
|
|
</div>
|
|
);
|
|
});
|