import type { FC, ReactNode, } from 'react' import { memo, useCallback, useEffect, useRef, useState, } from 'react' import type { ChatItem } from '../types' import type { Theme } from '../embedded-chatbot/theme/theme-context' import { CssTransform } from '../embedded-chatbot/theme/utils' import ContentSwitch from './content-switch' import { User } from '@/app/components/base/icons/src/public/avatar' import { Markdown } from '@/app/components/base/markdown' import { FileList } from '@/app/components/base/file-uploader' import ActionButton from '../../action-button' import { RiClipboardLine, RiEditLine } from '@remixicon/react' import Toast from '../../toast' import copy from 'copy-to-clipboard' import { useTranslation } from 'react-i18next' import cn from '@/utils/classnames' import Textarea from 'react-textarea-autosize' import Button from '../../button' import { useChatContext } from './context' type QuestionProps = { item: ChatItem questionIcon?: ReactNode theme: Theme | null | undefined enableEdit?: boolean switchSibling?: (siblingMessageId: string) => void } const Question: FC = ({ item, questionIcon, theme, enableEdit = true, switchSibling, }) => { const { t } = useTranslation() const { content, message_files, } = item const { onRegenerate, } = useChatContext() const [isEditing, setIsEditing] = useState(false) const [editedContent, setEditedContent] = useState(content) const [contentWidth, setContentWidth] = useState(0) const contentRef = useRef(null) const handleEdit = useCallback(() => { setIsEditing(true) setEditedContent(content) }, [content]) const handleResend = useCallback(() => { setIsEditing(false) onRegenerate?.(item, { message: editedContent, files: message_files }) }, [editedContent, message_files, item, onRegenerate]) const handleCancelEditing = useCallback(() => { setIsEditing(false) setEditedContent(content) }, [content]) const handleSwitchSibling = useCallback((direction: 'prev' | 'next') => { if (direction === 'prev') item.prevSibling && switchSibling?.(item.prevSibling) else item.nextSibling && switchSibling?.(item.nextSibling) }, [switchSibling, item.prevSibling, item.nextSibling]) const getContentWidth = () => { if (contentRef.current) setContentWidth(contentRef.current?.clientWidth) } useEffect(() => { if (!contentRef.current) return const resizeObserver = new ResizeObserver(() => { getContentWidth() }) resizeObserver.observe(contentRef.current) return () => { resizeObserver.disconnect() } }, []) return (
{ copy(content) Toast.notify({ type: 'success', message: t('common.actionMsg.copySuccessfully') }) }}> {enableEdit && }
{ !!message_files?.length && ( ) } {!isEditing ? :