From adb5e4fc319e465d490628c30ddac38a5a871d8d Mon Sep 17 00:00:00 2001 From: ousugo Date: Wed, 19 Feb 2025 18:18:17 +0800 Subject: [PATCH] feat: Add copy functionality to message reasoning content --- .../pages/home/Messages/MessageThought.tsx | 55 ++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/src/renderer/src/pages/home/Messages/MessageThought.tsx b/src/renderer/src/pages/home/Messages/MessageThought.tsx index 52258a54a6..38b7295788 100644 --- a/src/renderer/src/pages/home/Messages/MessageThought.tsx +++ b/src/renderer/src/pages/home/Messages/MessageThought.tsx @@ -1,6 +1,7 @@ +import { CheckOutlined } from '@ant-design/icons' import { useSettings } from '@renderer/hooks/useSettings' import { Message } from '@renderer/types' -import { Collapse } from 'antd' +import { Collapse, message as antdMessage, Tooltip } from 'antd' import { FC, useEffect, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import BarLoader from 'react-spinners/BarLoader' @@ -14,6 +15,7 @@ interface Props { const MessageThought: FC = ({ message }) => { const [activeKey, setActiveKey] = useState<'thought' | ''>('thought') + const [copied, setCopied] = useState(false) const isThinking = !message.content const { t } = useTranslation() const { messageFont, fontSize } = useSettings() @@ -31,6 +33,15 @@ const MessageThought: FC = ({ message }) => { return null } + const copyThought = () => { + if (message.reasoning_content) { + navigator.clipboard.writeText(message.reasoning_content) + antdMessage.success({ content: t('message.copied'), key: 'copy-message' }) + setCopied(true) + setTimeout(() => setCopied(false), 2000) + } + } + const thinkingTime = message.metrics?.time_thinking_millsec || 0 const thinkingTimeSeconds = (thinkingTime / 1000).toFixed(1) const isPaused = message.status === 'paused' @@ -50,6 +61,20 @@ const MessageThought: FC = ({ message }) => { {isThinking ? t('chat.thinking') : t('chat.deeply_thought', { secounds: thinkingTimeSeconds })} {isThinking && !isPaused && } + {(!isThinking || isPaused) && ( + + { + e.stopPropagation() + copyThought() + }} + aria-label={t('common.copy')}> + {!copied && } + {copied && } + + + )} ), children: ( @@ -79,4 +104,32 @@ const TinkingText = styled.span` color: var(--color-text-2); ` +const ActionButton = styled.button` + background: none; + border: none; + color: var(--color-text-2); + cursor: pointer; + padding: 4px; + display: flex; + align-items: center; + justify-content: center; + margin-left: auto; + opacity: 0.6; + transition: all 0.3s; + + &:hover { + opacity: 1; + color: var(--color-text); + } + + &:focus-visible { + outline: 2px solid var(--color-primary); + outline-offset: 2px; + } + + .iconfont { + font-size: 14px; + } +` + export default MessageThought