import type { FC, ReactNode, } from 'react' import { memo, useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import type { ChatConfig, ChatItem, } from '../../types' import Operation from './operation' import AgentContent from './agent-content' import BasicContent from './basic-content' import SuggestedQuestions from './suggested-questions' import More from './more' import WorkflowProcessItem from './workflow-process' import LoadingAnim from '@/app/components/chat/loading-anim' import Citation from '@/app/components/chat/citation' // TODO mars // import { EditTitle } from '@/app/components/app/annotation/edit-annotation-modal/edit-item' import type { AppData } from '@/models/share' import AnswerIcon from '@/app/components/base/answer-icon' import { ChevronRight } from '@/app/components/base/icons/src/vender/line/arrows' import cn from '@/utils/classnames' import { FileList } from '@/app/components/base/file-uploader' type AnswerProps = { item: ChatItem question: string index: number config?: ChatConfig answerIcon?: ReactNode responding?: boolean showPromptLog?: boolean chatAnswerContainerInner?: string hideProcessDetail?: boolean appData?: AppData noChatInput?: boolean switchSibling?: (siblingMessageId: string) => void } const Answer: FC = ({ item, question, index, config, answerIcon, responding, showPromptLog, chatAnswerContainerInner, hideProcessDetail, appData, noChatInput, switchSibling, }) => { const { t } = useTranslation() const { content, citation, agent_thoughts, more, annotation, workflowProcess, allFiles, message_files, } = item const hasAgentThoughts = !!agent_thoughts?.length const [containerWidth, setContainerWidth] = useState(0) const [contentWidth, setContentWidth] = useState(0) const containerRef = useRef(null) const contentRef = useRef(null) const getContainerWidth = () => { if (containerRef.current) setContainerWidth(containerRef.current?.clientWidth + 16) } useEffect(() => { getContainerWidth() }, []) const getContentWidth = () => { if (contentRef.current) setContentWidth(contentRef.current?.clientWidth) } useEffect(() => { if (!responding) getContentWidth() }, [responding]) // Recalculate contentWidth when content changes (e.g., SVG preview/source toggle) useEffect(() => { if (!containerRef.current) return const resizeObserver = new ResizeObserver(() => { getContentWidth() }) resizeObserver.observe(containerRef.current) return () => { resizeObserver.disconnect() } }, []) return (
{answerIcon || } {responding && (
)}
{ !responding && ( ) } {/** Render the normal steps */} { workflowProcess && !hideProcessDetail && ( ) } {/** Hide workflow steps by it's settings in siteInfo */} { workflowProcess && hideProcessDetail && appData && ( ) } { responding && !content && !hasAgentThoughts && (
) } { content && !hasAgentThoughts && ( ) } { hasAgentThoughts && ( ) } { !!allFiles?.length && ( ) } { !!message_files?.length && ( ) } {/* { annotation?.id && annotation.authorName && ( ) } */} { !!citation?.length && !responding && ( ) } {item.siblingCount && item.siblingCount > 1 && item.siblingIndex !== undefined &&
{item.siblingIndex + 1} / {item.siblingCount}
}
) } export default memo(Answer)