"use client" import { memo, useEffect, useRef, useState } from "react" import { AnimatePresence, motion } from "motion/react" import { Check, Copy, FileIcon, PencilIcon, PencilOffIcon } from "lucide-react" import type { UIMessage } from "@ai-sdk/react" import ChatModelSelector from "../model-selector" import { ReasoningSelector } from "../reasoning-selector" import { SendButton } from "../input/actions" import { getDefaultReasoningEffort, type ModelId, type ReasoningEffort, } from "@/lib/models" import { formatAttachmentSize, getChatMessageAttachments } from "../attachments" interface UserMessageProps { message: UIMessage copiedMessageId: string | null selectedModel: ModelId reasoningEffort: ReasoningEffort onCopy: (messageId: string, text: string) => void onRegenerate: ( messageId: string, text: string, model: ModelId, reasoningEffort: ReasoningEffort, ) => void } export const UserMessage = memo(function UserMessage({ message, copiedMessageId, selectedModel, reasoningEffort, onCopy, onRegenerate, }: UserMessageProps) { const [isEditing, setIsEditing] = useState(false) const [draft, setDraft] = useState("") const [editModel, setEditModel] = useState(selectedModel) const [editReasoningEffort, setEditReasoningEffort] = useState(reasoningEffort) const textareaRef = useRef(null) const text = message.parts .filter((part) => part.type === "text") .map((part) => part.text) .join(" ") const attachments = getChatMessageAttachments(message.metadata) const startEditing = () => { setDraft(text) setEditModel(selectedModel) setEditReasoningEffort(reasoningEffort) setIsEditing(true) } const submitEdit = () => { const nextText = draft.trim() if (!nextText) return setIsEditing(false) onRegenerate(message.id, nextText, editModel, editReasoningEffort) } const handleEditModelChange = (model: ModelId) => { setEditModel(model) setEditReasoningEffort(getDefaultReasoningEffort(model)) } useEffect(() => { if (!isEditing) return textareaRef.current?.focus() }, [isEditing]) return (
{attachments.length > 0 ? (
{attachments.map((attachment) => (
{attachment.filename}
{formatAttachmentSize(attachment.size)} {" | "} {attachment.saveToMemory ? "Saved" : "Chat only"}
))}
) : null} {isEditing ? (