From 47c455b12508c56ddbf5ac9dbccfc45ac22a2ee5 Mon Sep 17 00:00:00 2001 From: kangfenmao Date: Mon, 30 Dec 2024 14:09:59 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E4=BF=9D=E6=8C=81?= =?UTF-8?q?=E5=B9=B6=E5=8F=91=E9=80=81=E7=9A=84=E5=8A=9F=E8=83=BD=20#527?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/Popups/TextEditPopup.tsx | 9 +++- src/renderer/src/i18n/locales/en-us.json | 3 +- src/renderer/src/i18n/locales/ja-jp.json | 3 +- src/renderer/src/i18n/locales/ru-ru.json | 3 +- src/renderer/src/i18n/locales/zh-cn.json | 3 +- src/renderer/src/i18n/locales/zh-tw.json | 3 +- .../src/pages/home/Messages/Message.tsx | 8 ++- .../pages/home/Messages/MessageMenubar.tsx | 49 +++++++++++++++++-- src/renderer/src/services/EventService.ts | 3 +- 9 files changed, 71 insertions(+), 13 deletions(-) diff --git a/src/renderer/src/components/Popups/TextEditPopup.tsx b/src/renderer/src/components/Popups/TextEditPopup.tsx index dea34f8b..914ce933 100644 --- a/src/renderer/src/components/Popups/TextEditPopup.tsx +++ b/src/renderer/src/components/Popups/TextEditPopup.tsx @@ -4,6 +4,7 @@ import { TextAreaProps } from 'antd/lib/input' import { TextAreaRef } from 'antd/lib/input/TextArea' import { useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' +import styled from 'styled-components' import { TopView } from '../TopView' @@ -11,13 +12,14 @@ interface ShowParams { text: string textareaProps?: TextAreaProps modalProps?: ModalProps + children?: (props: { onOk?: () => void; onCancel?: () => void }) => React.ReactNode } interface Props extends ShowParams { resolve: (data: any) => void } -const PopupContainer: React.FC = ({ text, textareaProps, modalProps, resolve }) => { +const PopupContainer: React.FC = ({ text, textareaProps, modalProps, resolve, children }) => { const [open, setOpen] = useState(true) const { t } = useTranslation() const [textValue, setTextValue] = useState(text) @@ -73,12 +75,17 @@ const PopupContainer: React.FC = ({ text, textareaProps, modalProps, reso onInput={resizeTextArea} onChange={(e) => setTextValue(e.target.value)} /> + {children && children({ onOk, onCancel })} ) } const TopViewKey = 'TextEditPopup' +const ChildrenContainer = styled.div` + position: relative; +` + export default class TextEditPopup { static topviewId = 0 static hide() { diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index e5c3dca0..0257b720 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -112,7 +112,8 @@ "topics.list": "Topic List", "topics.move_to": "Move to", "topics.title": "Topics", - "translate": "Translate" + "translate": "Translate", + "resend": "Resend" }, "common": { "and": "and", diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index 82f27549..4f7b75f2 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -112,7 +112,8 @@ "topics.list": "トピックリスト", "topics.move_to": "移動先", "topics.title": "トピック", - "translate": "翻訳" + "translate": "翻訳", + "resend": "再送信" }, "common": { "and": "と", diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index 63603973..83745f6e 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -112,7 +112,8 @@ "topics.list": "Список топиков", "topics.move_to": "Переместить в", "topics.title": "Топики", - "translate": "Перевести" + "translate": "Перевести", + "resend": "Переотправить" }, "common": { "and": "и", diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index 8e2e8a80..cfb258c4 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -112,7 +112,8 @@ "topics.list": "话题列表", "topics.move_to": "移动到", "topics.title": "话题", - "translate": "翻译" + "translate": "翻译", + "resend": "重新发送" }, "common": { "and": "和", diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index ec54e921..0473de5f 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -112,7 +112,8 @@ "topics.list": "話題列表", "topics.move_to": "移動到", "topics.title": "話題", - "translate": "翻譯" + "translate": "翻譯", + "resend": "重新發送" }, "common": { "and": "與", diff --git a/src/renderer/src/pages/home/Messages/Message.tsx b/src/renderer/src/pages/home/Messages/Message.tsx index 9dc6018d..9aa80940 100644 --- a/src/renderer/src/pages/home/Messages/Message.tsx +++ b/src/renderer/src/pages/home/Messages/Message.tsx @@ -86,9 +86,12 @@ const MessageItem: FC = ({ } useEffect(() => { - const unsubscribes = [EventEmitter.on(EVENT_NAMES.LOCATE_MESSAGE + ':' + message.id, messageHighlightHandler)] + const unsubscribes = [ + EventEmitter.on(EVENT_NAMES.LOCATE_MESSAGE + ':' + message.id, messageHighlightHandler), + EventEmitter.on(EVENT_NAMES.RESEND_MESSAGE + ':' + message.id, onEditMessage) + ] return () => unsubscribes.forEach((unsub) => unsub()) - }, [message]) + }, [message, onEditMessage]) useEffect(() => { if (message.role === 'user' && !message.usage) { @@ -178,6 +181,7 @@ const MessageItem: FC = ({ setModel={setModel} onEditMessage={onEditMessage} onDeleteMessage={onDeleteMessage} + onGetMessages={onGetMessages} /> )} diff --git a/src/renderer/src/pages/home/Messages/MessageMenubar.tsx b/src/renderer/src/pages/home/Messages/MessageMenubar.tsx index a8c4b3fb..1d1ddcb8 100644 --- a/src/renderer/src/pages/home/Messages/MessageMenubar.tsx +++ b/src/renderer/src/pages/home/Messages/MessageMenubar.tsx @@ -15,7 +15,7 @@ import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService' import { translateText } from '@renderer/services/TranslateService' import { Message, Model } from '@renderer/types' import { removeTrailingDoubleSpaces } from '@renderer/utils' -import { Dropdown, Popconfirm, Tooltip } from 'antd' +import { Button, Dropdown, Popconfirm, Tooltip } from 'antd' import dayjs from 'dayjs' import { FC, useCallback, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' @@ -31,6 +31,7 @@ interface Props { setModel: (model: Model) => void onEditMessage?: (message: Message) => void onDeleteMessage?: (message: Message) => void + onGetMessages?: () => Message[] } const MessageMenubar: FC = (props) => { @@ -43,7 +44,8 @@ const MessageMenubar: FC = (props) => { assistantModel, setModel, onEditMessage, - onDeleteMessage + onDeleteMessage, + onGetMessages } = props const { t } = useTranslation() const [copied, setCopied] = useState(false) @@ -75,10 +77,43 @@ const MessageMenubar: FC = (props) => { }) }, [index, t]) + const onResend = useCallback(() => { + const _messages = onGetMessages?.() || [] + const index = _messages.findIndex((m) => m.id === message.id) + const nextIndex = index + 1 + const nextMessage = _messages[nextIndex] + + if (nextMessage && nextMessage.role === 'assistant') { + EventEmitter.emit(EVENT_NAMES.RESEND_MESSAGE + ':' + nextMessage.id, { + ...nextMessage, + content: '', + status: 'sending', + modelId: assistantModel?.id || model?.id, + translatedContent: undefined + }) + } + }, [assistantModel?.id, message.id, model?.id, onGetMessages]) + const onEdit = useCallback(async () => { - const editedText = await TextEditPopup.show({ text: message.content }) + let resendMessage = false + + const editedText = await TextEditPopup.show({ + text: message.content, + children: (props) => ( + } + onClick={() => { + props.onOk?.() + resendMessage = true + }}> + {t('chat.resend')} + + ) + }) + editedText && onEditMessage?.({ ...message, content: editedText }) - }, [message, onEditMessage]) + resendMessage && onResend() + }, [message, onEditMessage, onResend, t]) const handleTranslate = useCallback( async (language: string) => { @@ -287,4 +322,10 @@ const ActionButton = styled.div` } ` +const ReSendButton = styled(Button)` + position: absolute; + top: 10px; + left: 0; +` + export default MessageMenubar diff --git a/src/renderer/src/services/EventService.ts b/src/renderer/src/services/EventService.ts index 78d1e4ed..ee0f3318 100644 --- a/src/renderer/src/services/EventService.ts +++ b/src/renderer/src/services/EventService.ts @@ -20,5 +20,6 @@ export const EVENT_NAMES = { NEW_BRANCH: 'NEW_BRANCH', EXPORT_TOPIC_IMAGE: 'EXPORT_TOPIC_IMAGE', LOCATE_MESSAGE: 'LOCATE_MESSAGE', - ADD_NEW_TOPIC: 'ADD_NEW_TOPIC' + ADD_NEW_TOPIC: 'ADD_NEW_TOPIC', + RESEND_MESSAGE: 'RESEND_MESSAGE' }