refactor(ChatNavigation): Optimize scroll navigation and performance

- Improve scroll navigation with memoized container reference
- Add scrollToTop and scrollToBottom utility methods
- Remove message notifications for navigation limits
- Use useCallback and useMemo for better performance
- Simplify message navigation logic
This commit is contained in:
kangfenmao 2025-03-11 12:29:04 +08:00
parent 2fd3ebb378
commit e61618f1b4

View File

@ -1,6 +1,6 @@
import { DownOutlined, UpOutlined } from '@ant-design/icons' import { DownOutlined, UpOutlined } from '@ant-design/icons'
import { Button, message, Tooltip } from 'antd' import { Button, Tooltip } from 'antd'
import { FC, useEffect, useState } from 'react' import { FC, useCallback, useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import styled from 'styled-components' import styled from 'styled-components'
@ -13,7 +13,9 @@ const ChatNavigation: FC<ChatNavigationProps> = ({ containerId }) => {
const [isVisible, setIsVisible] = useState(false) const [isVisible, setIsVisible] = useState(false)
const [hideTimer, setHideTimer] = useState<NodeJS.Timeout | null>(null) const [hideTimer, setHideTimer] = useState<NodeJS.Timeout | null>(null)
const resetHideTimer = () => { const container = useMemo(() => document.getElementById(containerId), [containerId])
const resetHideTimer = useCallback(() => {
if (hideTimer) { if (hideTimer) {
clearTimeout(hideTimer) clearTimeout(hideTimer)
} }
@ -22,10 +24,9 @@ const ChatNavigation: FC<ChatNavigationProps> = ({ containerId }) => {
setIsVisible(false) setIsVisible(false)
}, 1000) }, 1000)
setHideTimer(timer) setHideTimer(timer)
} }, [hideTimer])
const findUserMessages = () => { const findUserMessages = () => {
const container = document.getElementById(containerId)
if (!container) return [] if (!container) return []
const userMessages = Array.from(container.getElementsByClassName('message-user')) const userMessages = Array.from(container.getElementsByClassName('message-user'))
@ -33,7 +34,6 @@ const ChatNavigation: FC<ChatNavigationProps> = ({ containerId }) => {
} }
const findAssistantMessages = () => { const findAssistantMessages = () => {
const container = document.getElementById(containerId)
if (!container) return [] if (!container) return []
const assistantMessages = Array.from(container.getElementsByClassName('message-assistant')) const assistantMessages = Array.from(container.getElementsByClassName('message-assistant'))
@ -44,10 +44,19 @@ const ChatNavigation: FC<ChatNavigationProps> = ({ containerId }) => {
element.scrollIntoView({ behavior: 'smooth', block: 'start' }) element.scrollIntoView({ behavior: 'smooth', block: 'start' })
} }
const scrollToTop = () => {
if (!container) return
container.scrollTo({ top: 0, behavior: 'smooth' })
}
const scrollToBottom = () => {
if (!container) return
container.scrollTo({ top: container.scrollHeight, behavior: 'smooth' })
}
const getCurrentVisibleIndex = (direction: 'up' | 'down') => { const getCurrentVisibleIndex = (direction: 'up' | 'down') => {
const userMessages = findUserMessages() const userMessages = findUserMessages()
const assistantMessages = findAssistantMessages() const assistantMessages = findAssistantMessages()
const container = document.getElementById(containerId)
if (!container) return -1 if (!container) return -1
const containerRect = container.getBoundingClientRect() const containerRect = container.getBoundingClientRect()
@ -90,22 +99,24 @@ const ChatNavigation: FC<ChatNavigationProps> = ({ containerId }) => {
resetHideTimer() resetHideTimer()
const userMessages = findUserMessages() const userMessages = findUserMessages()
const assistantMessages = findAssistantMessages() const assistantMessages = findAssistantMessages()
if (userMessages.length === 0 && assistantMessages.length === 0) { if (userMessages.length === 0 && assistantMessages.length === 0) {
message.info({ content: t('chat.navigation.last'), key: 'navigation-last' }) window.message.info({ content: t('chat.navigation.last'), key: 'navigation-info' })
return return scrollToBottom()
} }
const visibleIndex = getCurrentVisibleIndex('down') const visibleIndex = getCurrentVisibleIndex('down')
if (visibleIndex === -1) { if (visibleIndex === -1) {
message.info({ content: t('chat.navigation.last'), key: 'navigation-last' }) window.message.info({ content: t('chat.navigation.last'), key: 'navigation-info' })
return return scrollToBottom()
} }
const targetIndex = visibleIndex - 1 const targetIndex = visibleIndex - 1
if (targetIndex < 0) { if (targetIndex < 0) {
message.info({ content: t('chat.navigation.last'), key: 'navigation-last' }) window.message.info({ content: t('chat.navigation.last'), key: 'navigation-info' })
return return scrollToBottom()
} }
scrollToMessage(userMessages[targetIndex]) scrollToMessage(userMessages[targetIndex])
@ -116,21 +127,22 @@ const ChatNavigation: FC<ChatNavigationProps> = ({ containerId }) => {
const userMessages = findUserMessages() const userMessages = findUserMessages()
const assistantMessages = findAssistantMessages() const assistantMessages = findAssistantMessages()
if (userMessages.length === 0 && assistantMessages.length === 0) { if (userMessages.length === 0 && assistantMessages.length === 0) {
message.info({ content: t('chat.navigation.first'), key: 'navigation-first' }) window.message.info({ content: t('chat.navigation.first'), key: 'navigation-info' })
return return scrollToTop()
} }
const visibleIndex = getCurrentVisibleIndex('up') const visibleIndex = getCurrentVisibleIndex('up')
if (visibleIndex === -1) { if (visibleIndex === -1) {
message.info({ content: t('chat.navigation.first'), key: 'navigation-first' }) window.message.info({ content: t('chat.navigation.first'), key: 'navigation-info' })
return return scrollToTop()
} }
const targetIndex = visibleIndex + 1 const targetIndex = visibleIndex + 1
if (targetIndex >= userMessages.length) { if (targetIndex >= userMessages.length) {
message.info({ content: t('chat.navigation.first'), key: 'navigation-first' }) window.message.info({ content: t('chat.navigation.first'), key: 'navigation-info' })
return return scrollToTop()
} }
scrollToMessage(userMessages[targetIndex]) scrollToMessage(userMessages[targetIndex])