'use client'; import type { BusterChatMessageRequest } from '@/api/asset_interfaces'; import React, { useState, useRef, useEffect } from 'react'; import { Paragraph } from '@/components/ui/typography'; import { MessageContainer } from './MessageContainer'; import { Tooltip } from '@/components/ui/tooltip'; import { cn } from '@/lib/classMerge'; import { PenWriting, Copy } from '@/components/ui/icons'; import { Button } from '@/components/ui/buttons'; import { useBusterNotifications } from '@/context/BusterNotifications'; import { useMemoizedFn, useMount } from '@/hooks'; import { InputTextArea } from '@/components/ui/inputs/InputTextArea'; import { useBusterNewChatContextSelector } from '@/context/Chats'; export const ChatUserMessage: React.FC<{ messageId: string; chatId: string; isCompletedStream: boolean; requestMessage: NonNullable; }> = React.memo(({ messageId, chatId, isCompletedStream, requestMessage }) => { const { openSuccessMessage } = useBusterNotifications(); const [isTooltipOpen, setIsTooltipOpen] = useState(false); const [isEditing, setIsEditing] = useState(false); const { sender_avatar, sender_id, sender_name, request } = requestMessage; const onSetIsEditing = useMemoizedFn((isEditing: boolean) => { setIsEditing(isEditing); setIsTooltipOpen(false); }); const handleCopy = useMemoizedFn((e?: React.ClipboardEvent) => { // Prevent default copy behavior //I do not know why this is needed, but it is... if (e && e.clipboardData) { e.preventDefault(); e.clipboardData.setData('text/plain', request); } else { navigator.clipboard.writeText(request); } openSuccessMessage('Copied to clipboard'); }); return ( setIsTooltipOpen(true)} onMouseLeave={() => setIsTooltipOpen(false)}> {isEditing ? ( ) : ( <>
{request}
{isCompletedStream && ( )} )}
); }); ChatUserMessage.displayName = 'ChatUserMessage'; const RequestMessageTooltip: React.FC<{ isTooltipOpen: boolean; requestMessage: NonNullable; setIsEditing: (isEditing: boolean) => void; onCopy: () => void; }> = React.memo(({ isTooltipOpen, requestMessage, setIsEditing, onCopy }) => { const { openSuccessMessage } = useBusterNotifications(); const onEdit = useMemoizedFn(() => { setIsEditing(true); }); return (
); }); RequestMessageTooltip.displayName = 'RequestMessageTooltip'; const EditMessage: React.FC<{ requestMessage: NonNullable; onSetIsEditing: (isEditing: boolean) => void; messageId: string; chatId: string; }> = React.memo(({ requestMessage, onSetIsEditing, messageId, chatId }) => { const [prompt, setPrompt] = useState(requestMessage.request); const textAreaRef = useRef(null); const onReplaceMessageInChat = useBusterNewChatContextSelector((x) => x.onReplaceMessageInChat); const onSave = useMemoizedFn(() => { onReplaceMessageInChat({ chatId, messageId, prompt }); onSetIsEditing(false); }); useMount(() => { // Using requestAnimationFrame to ensure the DOM is ready requestAnimationFrame(() => { if (textAreaRef.current) { textAreaRef.current.focus(); textAreaRef.current.select(); } }); }); return (
setPrompt(e.target.value)} />
); });