From 8b9929cc7b91e87a9b74c51bd9b87e217c4b2690 Mon Sep 17 00:00:00 2001 From: Hobee Liu <56749226+HoBeedzc@users.noreply.github.com> Date: Tue, 1 Apr 2025 16:17:57 +0800 Subject: [PATCH] feat: add chat navigation bar close (#4019) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(聊天导航): 新增关闭、置顶和置底按钮并更新图标 在聊天导航组件中新增了关闭、置顶和置底按钮,并更新了相关图标以提升用户体验。同时,添加了点击关闭按钮时隐藏导航的功能。 * feat(消息导航): 添加手动关闭状态以避免误触 在 ChatNavigation 组件中添加 `manuallyClosedUntil` 状态,用于在用户手动关闭导航后,1分钟内不响应鼠标靠近事件。这可以防止用户在操作时误触导航栏,提升用户体验。 * refactor(ChatNavigation): 重命名函数并添加滚动处理逻辑 重命名 handleChatNavigationClick 为 handleCloseChatNavigation 以提高代码可读性,并添加 handleScrollToTop 和 handleScrollToBottom 函数以处理滚动逻辑 * fix: 修复滚动到顶部时位置不正确的问题 将 `scrollToTop` 函数中的 `top` 值从 `0` 改为 `-container.scrollHeight`,以确保滚动到顶部时位置正确 * docs(i18n): 添加新的翻译字符串以支持更多操作 在多个语言文件中添加了“回到顶部”、“回到底部”和“关闭”的翻译字符串,以支持更多用户界面操作。 * refactor: 移除未使用的变量以简化代码 ``` 解释: - **类型**: `refactor`,因为这是代码重构,移除了未使用的变量,没有改变功能行为。 - **描述**: 移除了未使用的变量以简化代码,符合简洁和可维护性的原则。 --- src/renderer/src/i18n/locales/en-us.json | 5 +- src/renderer/src/i18n/locales/ja-jp.json | 5 +- src/renderer/src/i18n/locales/ru-ru.json | 5 +- src/renderer/src/i18n/locales/zh-cn.json | 5 +- src/renderer/src/i18n/locales/zh-tw.json | 5 +- src/renderer/src/i18n/translate/el-gr.json | 5 +- src/renderer/src/i18n/translate/es-es.json | 5 +- src/renderer/src/i18n/translate/fr-fr.json | 5 +- src/renderer/src/i18n/translate/pt-pt.json | 5 +- .../pages/home/Messages/ChatNavigation.tsx | 82 +++++++++++++++++-- 10 files changed, 112 insertions(+), 15 deletions(-) diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index ade0e11b..31bd6b63 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -150,7 +150,10 @@ "history": "Chat History", "last": "Already at the last message", "next": "Next Message", - "prev": "Previous Message" + "prev": "Previous Message", + "top": "Back to top", + "bottom": "Back to bottom", + "close": "Close" }, "resend": "Resend", "save": "Save", diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index a1e68634..50764e48 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -150,7 +150,10 @@ "history": "チャット履歴", "last": "最後のメッセージです", "next": "次のメッセージ", - "prev": "前のメッセージ" + "prev": "前のメッセージ", + "top": "トップに戻る", + "bottom": "下部に戻る", + "close": "閉じる" }, "resend": "再送信", "save": "保存", diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index 6cc7553c..15b0d4a5 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -150,7 +150,10 @@ "history": "История чата", "last": "Уже последнее сообщение", "next": "Следующее сообщение", - "prev": "Предыдущее сообщение" + "prev": "Предыдущее сообщение", + "top": "Вернуться наверх", + "bottom": "Вернуться вниз", + "close": "Закрыть" }, "resend": "Переотправить", "save": "Сохранить", diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index 71e8dfe0..b5d0931f 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -150,7 +150,10 @@ "history": "聊天历史", "last": "已经是最后一条消息", "next": "下一条消息", - "prev": "上一条消息" + "prev": "上一条消息", + "top": "回到顶部", + "bottom": "回到底部", + "close": "关闭" }, "resend": "重新发送", "save": "保存", diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index bf2c2c67..41076e0a 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -150,7 +150,10 @@ "history": "聊天歷史", "last": "已經是最後一條訊息", "next": "下一條訊息", - "prev": "上一條訊息" + "prev": "上一條訊息", + "top": "回到頂部", + "bottom": "回到底部", + "close": "關閉" }, "resend": "重新傳送", "save": "儲存", diff --git a/src/renderer/src/i18n/translate/el-gr.json b/src/renderer/src/i18n/translate/el-gr.json index 6b46257f..8fbe8799 100644 --- a/src/renderer/src/i18n/translate/el-gr.json +++ b/src/renderer/src/i18n/translate/el-gr.json @@ -130,7 +130,10 @@ "first": "Ήδη το πρώτο μήνυμα", "last": "Ήδη το τελευταίο μήνυμα", "next": "Επόμενο μήνυμα", - "prev": "Προηγούμενο μήνυμα" + "prev": "Προηγούμενο μήνυμα", + "top": "Επιστροφή στην κορυφή", + "bottom": "Επιστροφή στο κάτω μέρος", + "close": "Κλείσιμο" }, "resend": "Ξαναστείλε", "save": "Αποθήκευση", diff --git a/src/renderer/src/i18n/translate/es-es.json b/src/renderer/src/i18n/translate/es-es.json index f9751305..1dc6bdcd 100644 --- a/src/renderer/src/i18n/translate/es-es.json +++ b/src/renderer/src/i18n/translate/es-es.json @@ -130,7 +130,10 @@ "first": "Ya es el primer mensaje", "last": "Ya es el último mensaje", "next": "Siguiente mensaje", - "prev": "Mensaje anterior" + "prev": "Mensaje anterior", + "top": "Volver arriba", + "bottom": "Volver abajo", + "close": "Cerrar" }, "resend": "Reenviar", "save": "Guardar", diff --git a/src/renderer/src/i18n/translate/fr-fr.json b/src/renderer/src/i18n/translate/fr-fr.json index 9a1c9600..1128c72c 100644 --- a/src/renderer/src/i18n/translate/fr-fr.json +++ b/src/renderer/src/i18n/translate/fr-fr.json @@ -130,7 +130,10 @@ "first": "Déjà premier message", "last": "Déjà dernier message", "next": "Prochain message", - "prev": "Précédent message" + "prev": "Précédent message", + "top": "Retour en haut", + "bottom": "Retour en bas", + "close": "Fermer" }, "resend": "Réenvoyer", "save": "Enregistrer", diff --git a/src/renderer/src/i18n/translate/pt-pt.json b/src/renderer/src/i18n/translate/pt-pt.json index 9dc210f9..005423fe 100644 --- a/src/renderer/src/i18n/translate/pt-pt.json +++ b/src/renderer/src/i18n/translate/pt-pt.json @@ -130,7 +130,10 @@ "first": "Esta é a primeira mensagem", "last": "Esta é a última mensagem", "next": "Próxima mensagem", - "prev": "Mensagem anterior" + "prev": "Mensagem anterior", + "top": "Voltar ao topo", + "bottom": "Voltar ao fundo", + "close": "Fechar" }, "resend": "Reenviar", "save": "Salvar", diff --git a/src/renderer/src/pages/home/Messages/ChatNavigation.tsx b/src/renderer/src/pages/home/Messages/ChatNavigation.tsx index 68f07402..14ec82c8 100644 --- a/src/renderer/src/pages/home/Messages/ChatNavigation.tsx +++ b/src/renderer/src/pages/home/Messages/ChatNavigation.tsx @@ -1,4 +1,11 @@ -import { DownOutlined, HistoryOutlined, UpOutlined } from '@ant-design/icons' +import { + ArrowDownOutlined, + ArrowUpOutlined, + CloseOutlined, + HistoryOutlined, + VerticalAlignBottomOutlined, + VerticalAlignTopOutlined +} from '@ant-design/icons' import { useSettings } from '@renderer/hooks/useSettings' import { RootState } from '@renderer/store' import { selectCurrentTopicId } from '@renderer/store/messages' @@ -20,6 +27,7 @@ const ChatNavigation: FC = ({ containerId }) => { const [isNearButtons, setIsNearButtons] = useState(false) const [hideTimer, setHideTimer] = useState(null) const [showChatHistory, setShowChatHistory] = useState(false) + const [manuallyClosedUntil, setManuallyClosedUntil] = useState(null) const currentTopicId = useSelector((state: RootState) => selectCurrentTopicId(state)) const lastMoveTime = useRef(0) const { topicPosition, showTopics } = useSettings() @@ -44,6 +52,10 @@ const ChatNavigation: FC = ({ containerId }) => { // Handle mouse entering button area const handleMouseEnter = useCallback(() => { + if (manuallyClosedUntil && Date.now() < manuallyClosedUntil) { + return + } + setIsNearButtons(true) setIsVisible(true) @@ -52,7 +64,7 @@ const ChatNavigation: FC = ({ containerId }) => { clearTimeout(hideTimer) setHideTimer(null) } - }, [hideTimer]) + }, [hideTimer, manuallyClosedUntil]) // Handle mouse leaving button area const handleMouseLeave = useCallback(() => { @@ -97,7 +109,7 @@ const ChatNavigation: FC = ({ containerId }) => { const scrollToTop = () => { const container = document.getElementById(containerId) - container && container.scrollTo({ top: 0, behavior: 'smooth' }) + container && container.scrollTo({ top: -container.scrollHeight, behavior: 'smooth' }) } const scrollToBottom = () => { @@ -148,6 +160,23 @@ const ChatNavigation: FC = ({ containerId }) => { return -1 } + // 修改 handleCloseChatNavigation 函数 + const handleCloseChatNavigation = () => { + setIsVisible(false) + // 设置手动关闭状态,1分钟内不响应鼠标靠近事件 + setManuallyClosedUntil(Date.now() + 60000) // 60000毫秒 = 1分钟 + } + + const handleScrollToTop = () => { + resetHideTimer() + scrollToTop() + } + + const handleScrollToBottom = () => { + resetHideTimer() + scrollToBottom() + } + const handleNextMessage = () => { resetHideTimer() const userMessages = findUserMessages() @@ -216,6 +245,11 @@ const ChatNavigation: FC = ({ containerId }) => { // Throttled mouse move handler to improve performance const handleMouseMove = (e: MouseEvent) => { + // 如果在手动关闭期间,不响应鼠标移动事件 + if (manuallyClosedUntil && Date.now() < manuallyClosedUntil) { + return + } + // Throttle mouse move to every 50ms for performance const now = Date.now() if (now - lastMoveTime.current < 50) return @@ -262,16 +296,43 @@ const ChatNavigation: FC = ({ containerId }) => { clearTimeout(hideTimer) } } - }, [containerId, hideTimer, resetHideTimer, isNearButtons, handleMouseEnter, handleMouseLeave, showRightTopics]) + }, [ + containerId, + hideTimer, + resetHideTimer, + isNearButtons, + handleMouseEnter, + handleMouseLeave, + showRightTopics, + manuallyClosedUntil + ]) return ( <> + + } + onClick={handleCloseChatNavigation} + aria-label={t('chat.navigation.close')} + /> + + + + } + onClick={handleScrollToTop} + aria-label={t('chat.navigation.top')} + /> + + } + icon={} onClick={handlePrevMessage} aria-label={t('chat.navigation.prev')} /> @@ -280,12 +341,21 @@ const ChatNavigation: FC = ({ containerId }) => { } + icon={} onClick={handleNextMessage} aria-label={t('chat.navigation.next')} /> + + } + onClick={handleScrollToBottom} + aria-label={t('chat.navigation.bottom')} + /> + +