| | import { useCallback, useState, useRef } from 'react'; |
| | import { Toast, Modal } from '@douyinfe/semi-ui'; |
| | import { useTranslation } from 'react-i18next'; |
| | import { getTextContent, buildApiPayload, createLoadingAssistantMessage } from '../helpers'; |
| | import { MESSAGE_ROLES } from '../constants/playground.constants'; |
| |
|
| | export const useMessageEdit = ( |
| | setMessage, |
| | inputs, |
| | parameterEnabled, |
| | sendRequest, |
| | saveMessages |
| | ) => { |
| | const { t } = useTranslation(); |
| | const [editingMessageId, setEditingMessageId] = useState(null); |
| | const [editValue, setEditValue] = useState(''); |
| | const editingMessageRef = useRef(null); |
| |
|
| | const handleMessageEdit = useCallback((targetMessage) => { |
| | const editableContent = getTextContent(targetMessage); |
| | setEditingMessageId(targetMessage.id); |
| | editingMessageRef.current = targetMessage; |
| | setEditValue(editableContent); |
| | }, []); |
| |
|
| | const handleEditSave = useCallback(() => { |
| | if (!editingMessageId || !editValue.trim()) return; |
| |
|
| | setMessage(prevMessages => { |
| | let messageIndex = prevMessages.findIndex(msg => msg === editingMessageRef.current); |
| |
|
| | if (messageIndex === -1) { |
| | messageIndex = prevMessages.findIndex(msg => msg.id === editingMessageId); |
| | } |
| |
|
| | const targetMessage = prevMessages[messageIndex]; |
| | let newContent; |
| |
|
| | if (Array.isArray(targetMessage.content)) { |
| | newContent = targetMessage.content.map(item => |
| | item.type === 'text' ? { ...item, text: editValue.trim() } : item |
| | ); |
| | } else { |
| | newContent = editValue.trim(); |
| | } |
| |
|
| | const updatedMessages = prevMessages.map(msg => |
| | msg.id === editingMessageId ? { ...msg, content: newContent } : msg |
| | ); |
| |
|
| | |
| | if (targetMessage.role === MESSAGE_ROLES.USER) { |
| | const hasSubsequentAssistantReply = messageIndex < prevMessages.length - 1 && |
| | prevMessages[messageIndex + 1].role === MESSAGE_ROLES.ASSISTANT; |
| |
|
| | if (hasSubsequentAssistantReply) { |
| | Modal.confirm({ |
| | title: t('消息已编辑'), |
| | content: t('检测到该消息后有AI回复,是否删除后续回复并重新生成?'), |
| | okText: t('重新生成'), |
| | cancelText: t('仅保存'), |
| | onOk: () => { |
| | const messagesUntilUser = updatedMessages.slice(0, messageIndex + 1); |
| | setMessage(messagesUntilUser); |
| | |
| | setTimeout(() => saveMessages(messagesUntilUser), 0); |
| |
|
| | setTimeout(() => { |
| | const payload = buildApiPayload(messagesUntilUser, null, inputs, parameterEnabled); |
| | setMessage(prevMsg => [...prevMsg, createLoadingAssistantMessage()]); |
| | sendRequest(payload, inputs.stream); |
| | }, 100); |
| | }, |
| | onCancel: () => { |
| | setMessage(updatedMessages); |
| | |
| | setTimeout(() => saveMessages(updatedMessages), 0); |
| | } |
| | }); |
| | return prevMessages; |
| | } |
| | } |
| |
|
| | |
| | setTimeout(() => saveMessages(updatedMessages), 0); |
| | return updatedMessages; |
| | }); |
| |
|
| | setEditingMessageId(null); |
| | editingMessageRef.current = null; |
| | setEditValue(''); |
| | Toast.success({ content: t('消息已更新'), duration: 2 }); |
| | }, [editingMessageId, editValue, t, inputs, parameterEnabled, sendRequest, setMessage, saveMessages]); |
| |
|
| | const handleEditCancel = useCallback(() => { |
| | setEditingMessageId(null); |
| | editingMessageRef.current = null; |
| | setEditValue(''); |
| | }, []); |
| |
|
| | return { |
| | editingMessageId, |
| | editValue, |
| | setEditValue, |
| | handleMessageEdit, |
| | handleEditSave, |
| | handleEditCancel |
| | }; |
| | }; |