import React, { ReactElement, ReactNode, useMemo } from 'react'; import cls from 'classnames'; import { Message, Metadata, RenderContentProps, MarkdownRenderProps } from '../interface'; import MarkdownRender from '../../markdownRender'; import { cssClasses, strings } from '@douyinfe/semi-foundation/chat/constants'; import { MDXProps } from 'mdx/types'; import { FileAttachment, ImageAttachment } from '../attachment'; import Code from './code'; const { PREFIX_CHAT_BOX } = cssClasses; const { MESSAGE_STATUS, MODE, ROLE } = strings; interface ChatBoxContentProps { mode?: 'bubble' | 'noBubble' | 'userBubble'; customMarkDownComponents?: MDXProps['components']; children?: string; role?: Metadata; message?: Message; customRenderFunc?: (props: RenderContentProps) => ReactNode; markdownRenderProps?: MarkdownRenderProps } const ChatBoxContent = (props: ChatBoxContentProps) => { const { message = {}, customRenderFunc, role: roleInfo, customMarkDownComponents, mode, markdownRenderProps } = props; const { content, role, status } = message; const markdownComponents = useMemo(() => ({ 'code': Code, 'SemiFile': FileAttachment, 'img': ImageAttachment, ...customMarkDownComponents }), [customMarkDownComponents]); const wrapCls = useMemo(() => { const isUser = role === ROLE.USER; const bubble = mode === MODE.BUBBLE; const userBubble = mode === MODE.USER_BUBBLE && isUser; return cls(`${PREFIX_CHAT_BOX}-content`, { [`${PREFIX_CHAT_BOX}-content-${mode}`]: bubble || userBubble, [`${PREFIX_CHAT_BOX}-content-user`]: (bubble && isUser) || userBubble, [`${PREFIX_CHAT_BOX}-content-error`]: status === MESSAGE_STATUS.ERROR && (bubble || userBubble) }); }, [role, status, mode]); const node = useMemo(() => { if (status === MESSAGE_STATUS.LOADING) { return ; } else { let realContent; if (typeof content === 'string') { realContent = ; } else if (Array.isArray(content)) { realContent = content.map((item, index) => { if (item.type === 'text') { return ; } else if (item.type === 'image_url') { return ; } else if (item.type === 'file_url') { const { name, size, url, type } = item.file_url; const realType = name.split('.').pop() ?? type?.split('/').pop(); return ; } return null; }); } return (<> {realContent} ); } }, [status, content]); if (customRenderFunc) { return customRenderFunc({ message, role: roleInfo, defaultContent: node, className: wrapCls, }) as ReactElement; } else { return
{node}
; } }; export default ChatBoxContent;