import React, { PureComponent, ReactNode } from 'react'; import PropTypes from 'prop-types'; import type { ChatBoxProps, DefaultActionNodeObj, RenderActionProps } from '../interface'; import { IconThumbUpStroked, IconDeleteStroked, IconCopyStroked, IconLikeThumb, IconRedoStroked } from '@douyinfe/semi-icons'; import { BaseComponent, Button, Popconfirm } from '../../index'; import copy from 'copy-text-to-clipboard'; import { cssClasses, strings } from '@douyinfe/semi-foundation/chat/constants'; import ChatBoxActionFoundation, { ChatBoxActionAdapter } from '@douyinfe/semi-foundation/chat/chatBoxActionFoundation'; import LocaleConsumer from "../../locale/localeConsumer"; import { Locale } from "../../locale/interface"; import cls from 'classnames'; const { PREFIX_CHAT_BOX_ACTION } = cssClasses; const { ROLE, MESSAGE_STATUS } = strings; interface ChatBoxActionProps extends ChatBoxProps { customRenderFunc?: (props: RenderActionProps) => ReactNode } interface ChatBoxActionState { visible: boolean; showAction: boolean } class ChatBoxAction extends BaseComponent { static propTypes = { role: PropTypes.object, message: PropTypes.object, showReset: PropTypes.bool, onMessageBadFeedback: PropTypes.func, onMessageGoodFeedback: PropTypes.func, onMessageCopy: PropTypes.func, onChatsChange: PropTypes.func, onMessageDelete: PropTypes.func, onMessageReset: PropTypes.func, customRenderFunc: PropTypes.func, } copySuccessNode: ReactNode; foundation: ChatBoxActionFoundation; containerRef: React.RefObject; popconfirmTriggerRef: React.RefObject; clickOutsideHandler: any; constructor(props: ChatBoxProps) { super(props); this.foundation = new ChatBoxActionFoundation(this.adapter); this.copySuccessNode = null; this.state = { visible: false, showAction: false, }; this.clickOutsideHandler = null; this.containerRef = React.createRef(); this.popconfirmTriggerRef = React.createRef(); } componentDidMount(): void { this.copySuccessNode = componentName="Chat" > {(locale: Locale["Chat"]) => locale['copySuccess']} ; } componentWillUnmount(): void { this.foundation.destroy(); } get adapter(): ChatBoxActionAdapter { return { ...super.adapter, notifyDeleteMessage: () => { const { message, onMessageDelete } = this.props; onMessageDelete?.(message); }, notifyMessageCopy: () => { const { message, onMessageCopy } = this.props; onMessageCopy?.(message); }, copyToClipboardAndToast: () => { const { message = {}, toast } = this.props; if (typeof message.content === 'string') { copy(message.content); } else if (Array.isArray(message.content)) { const content = message.content?.map(item => item.text).join(''); copy(content); } toast.success({ content: this.copySuccessNode }); }, notifyLikeMessage: () => { const { message, onMessageGoodFeedback } = this.props; onMessageGoodFeedback?.(message); }, notifyDislikeMessage: () => { const { message, onMessageBadFeedback } = this.props; onMessageBadFeedback?.(message); }, notifyResetMessage: () => { const { message, onMessageReset } = this.props; onMessageReset?.(message); }, setVisible: (visible) => { this.setState({ visible }); }, setShowAction: (showAction) => { this.setState({ showAction }); }, registerClickOutsideHandler: (cb: () => void) => { if (this.clickOutsideHandler) { this.adapter.unregisterClickOutsideHandler(); } this.clickOutsideHandler = (e: React.MouseEvent): any => { let el = this.popconfirmTriggerRef && this.popconfirmTriggerRef.current; const target = e.target as Element; const path = (e as any).composedPath && (e as any).composedPath() || [target]; if ( el && !(el as any).contains(target) && ! path.includes(el) ) { cb(); } }; window.addEventListener('mousedown', this.clickOutsideHandler); }, unregisterClickOutsideHandler: () => { if (this.clickOutsideHandler) { window.removeEventListener('mousedown', this.clickOutsideHandler); this.clickOutsideHandler = null; } }, }; } copyNode = () => { return