历史消息懒加载
性能优化
This commit is contained in:
parent
e35d928bcd
commit
14c9cb6001
@ -38,6 +38,7 @@
|
||||
"dependencies": {
|
||||
"@electron-toolkit/preload": "^3.0.0",
|
||||
"@electron-toolkit/utils": "^3.0.0",
|
||||
"@types/react-infinite-scroll-component": "^5.0.0",
|
||||
"adm-zip": "^0.5.16",
|
||||
"docx": "^9.0.2",
|
||||
"electron-log": "^5.1.5",
|
||||
@ -48,6 +49,7 @@
|
||||
"html2canvas": "^1.4.1",
|
||||
"markdown-it": "^14.1.0",
|
||||
"officeparser": "^4.1.1",
|
||||
"react-infinite-scroll-component": "^6.1.0",
|
||||
"webdav": "4.11.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -17,8 +17,10 @@ import { estimateHistoryTokens } from '@renderer/services/TokenService'
|
||||
import { Assistant, Message, Model, Topic } from '@renderer/types'
|
||||
import { captureScrollableDiv, runAsyncFunction, uuid } from '@renderer/utils'
|
||||
import { t } from 'i18next'
|
||||
import { flatten, last, reverse, take } from 'lodash'
|
||||
import { flatten, last, take } from 'lodash'
|
||||
import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import InfiniteScroll from 'react-infinite-scroll-component'
|
||||
import BeatLoader from 'react-spinners/BeatLoader'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import Suggestions from '../components/Suggestions'
|
||||
@ -31,13 +33,53 @@ interface Props {
|
||||
setActiveTopic: (topic: Topic) => void
|
||||
}
|
||||
|
||||
interface LoaderProps {
|
||||
$loading: boolean
|
||||
}
|
||||
|
||||
const LoaderContainer = styled.div<LoaderProps>`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
background: var(--color-background);
|
||||
opacity: ${(props) => (props.$loading ? 1 : 0)};
|
||||
transition: opacity 0.3s ease;
|
||||
pointer-events: none;
|
||||
`
|
||||
|
||||
const ScrollContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
`
|
||||
|
||||
interface ContainerProps {
|
||||
right?: boolean
|
||||
}
|
||||
|
||||
const Container = styled(Scrollbar)<ContainerProps>`
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
padding: 10px 0;
|
||||
padding-bottom: 20px;
|
||||
overflow-x: hidden;
|
||||
background-color: var(--color-background);
|
||||
`
|
||||
|
||||
const Messages: FC<Props> = ({ assistant, topic, setActiveTopic }) => {
|
||||
const [messages, setMessages] = useState<Message[]>([])
|
||||
const [displayMessages, setDisplayMessages] = useState<Message[]>([])
|
||||
const [hasMore, setHasMore] = useState(true)
|
||||
const [isLoadingMore, setIsLoadingMore] = useState(false)
|
||||
|
||||
const containerRef = useRef<HTMLDivElement>(null)
|
||||
const messagesRef = useRef(messages)
|
||||
const { updateTopic, addTopic } = useAssistant(assistant.id)
|
||||
const { showTopics, topicPosition, showAssistants, enableTopicNaming } = useSettings()
|
||||
|
||||
const messagesRef = useRef(messages)
|
||||
const INITIAL_MESSAGES_COUNT = 30
|
||||
const LOAD_MORE_COUNT = 20
|
||||
|
||||
messagesRef.current = messages
|
||||
|
||||
const maxWidth = useMemo(() => {
|
||||
@ -158,7 +200,7 @@ const Messages: FC<Props> = ({ assistant, topic, setActiveTopic }) => {
|
||||
setActiveTopic(newTopic)
|
||||
autoRenameTopic()
|
||||
|
||||
// 由于复制了消息,消息中附带的文件的总数变了,需要更新
|
||||
// 由于复制了消<EFBFBD><EFBFBD><EFBFBD>,消息中附带的文件的总数变了,需要更新
|
||||
const filesArr = branchMessages.map((m) => m.files)
|
||||
const files = flatten(filesArr).filter(Boolean)
|
||||
files.map(async (f) => {
|
||||
@ -197,7 +239,31 @@ const Messages: FC<Props> = ({ assistant, topic, setActiveTopic }) => {
|
||||
})
|
||||
}, [assistant, messages])
|
||||
|
||||
const memoizedMessages = useMemo(() => reverse([...messages]), [messages])
|
||||
// 初始化显示最新的消息
|
||||
useEffect(() => {
|
||||
if (messages.length > 0) {
|
||||
const reversedMessages = [...messages].reverse()
|
||||
setDisplayMessages(reversedMessages.slice(0, INITIAL_MESSAGES_COUNT))
|
||||
setHasMore(messages.length > INITIAL_MESSAGES_COUNT)
|
||||
}
|
||||
}, [messages])
|
||||
|
||||
// 加载更多历史消息
|
||||
const loadMoreMessages = useCallback(() => {
|
||||
if (!hasMore || isLoadingMore) return
|
||||
|
||||
setIsLoadingMore(true)
|
||||
|
||||
setTimeout(() => {
|
||||
const currentLength = displayMessages.length
|
||||
const reversedMessages = [...messages].reverse()
|
||||
const moreMessages = reversedMessages.slice(currentLength, currentLength + LOAD_MORE_COUNT)
|
||||
|
||||
setDisplayMessages((prev) => [...prev, ...moreMessages])
|
||||
setHasMore(currentLength + LOAD_MORE_COUNT < messages.length)
|
||||
setIsLoadingMore(false)
|
||||
}, 300)
|
||||
}, [displayMessages, hasMore, isLoadingMore, messages])
|
||||
|
||||
return (
|
||||
<Container
|
||||
@ -207,7 +273,18 @@ const Messages: FC<Props> = ({ assistant, topic, setActiveTopic }) => {
|
||||
ref={containerRef}
|
||||
right={topicPosition === 'left'}>
|
||||
<Suggestions assistant={assistant} messages={messages} />
|
||||
{memoizedMessages.map((message, index) => (
|
||||
<InfiniteScroll
|
||||
dataLength={displayMessages.length}
|
||||
next={loadMoreMessages}
|
||||
hasMore={hasMore}
|
||||
loader={null}
|
||||
inverse={true}
|
||||
scrollableTarget="messages">
|
||||
<ScrollContainer>
|
||||
<LoaderContainer $loading={isLoadingMore}>
|
||||
<BeatLoader size={8} color="var(--color-text-2)" />
|
||||
</LoaderContainer>
|
||||
{displayMessages.map((message, index) => (
|
||||
<MessageItem
|
||||
key={message.id}
|
||||
message={message}
|
||||
@ -219,18 +296,11 @@ const Messages: FC<Props> = ({ assistant, topic, setActiveTopic }) => {
|
||||
onGetMessages={onGetMessages}
|
||||
/>
|
||||
))}
|
||||
</ScrollContainer>
|
||||
</InfiniteScroll>
|
||||
<Prompt assistant={assistant} key={assistant.prompt} />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
const Container = styled(Scrollbar)`
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
padding: 10px 0;
|
||||
padding-bottom: 20px;
|
||||
overflow-x: hidden;
|
||||
background-color: var(--color-background);
|
||||
`
|
||||
|
||||
export default Messages
|
||||
|
||||
29
yarn.lock
29
yarn.lock
@ -2093,6 +2093,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/react-infinite-scroll-component@npm:^5.0.0":
|
||||
version: 5.0.0
|
||||
resolution: "@types/react-infinite-scroll-component@npm:5.0.0"
|
||||
dependencies:
|
||||
react-infinite-scroll-component: "npm:*"
|
||||
checksum: 10c0/257e7b2fc6ebf200ada409a5c21415c1a56157807636405f3329521cf36344a81afa87f992497747534453e48145b0d4f32ccee80814548b466a0d83dfa23eec
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/react@npm:*, @types/react@npm:^18.2.48":
|
||||
version: 18.3.5
|
||||
resolution: "@types/react@npm:18.3.5"
|
||||
@ -2343,6 +2352,7 @@ __metadata:
|
||||
"@types/node": "npm:^18.19.9"
|
||||
"@types/react": "npm:^18.2.48"
|
||||
"@types/react-dom": "npm:^18.2.18"
|
||||
"@types/react-infinite-scroll-component": "npm:^5.0.0"
|
||||
"@types/tinycolor2": "npm:^1"
|
||||
"@vitejs/plugin-react": "npm:^4.2.1"
|
||||
adm-zip: "npm:^0.5.16"
|
||||
@ -2384,6 +2394,7 @@ __metadata:
|
||||
react-dom: "npm:^18.2.0"
|
||||
react-hotkeys-hook: "npm:^4.6.1"
|
||||
react-i18next: "npm:^14.1.2"
|
||||
react-infinite-scroll-component: "npm:^6.1.0"
|
||||
react-markdown: "npm:^9.0.1"
|
||||
react-redux: "npm:^9.1.2"
|
||||
react-router: "npm:6"
|
||||
@ -9965,6 +9976,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-infinite-scroll-component@npm:*, react-infinite-scroll-component@npm:^6.1.0":
|
||||
version: 6.1.0
|
||||
resolution: "react-infinite-scroll-component@npm:6.1.0"
|
||||
dependencies:
|
||||
throttle-debounce: "npm:^2.1.0"
|
||||
peerDependencies:
|
||||
react: ">=16.0.0"
|
||||
checksum: 10c0/8de02f178ae861880dddbd0c882dc70b55e21737b87fe428140d81a2c5d13c5eeba8a4fc260b1e86e4c556fdea333d6babaed55a9e5987a42b181b2d92f69cd8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-is@npm:^16.13.1, react-is@npm:^16.7.0":
|
||||
version: 16.13.1
|
||||
resolution: "react-is@npm:16.13.1"
|
||||
@ -11546,6 +11568,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"throttle-debounce@npm:^2.1.0":
|
||||
version: 2.3.0
|
||||
resolution: "throttle-debounce@npm:2.3.0"
|
||||
checksum: 10c0/41648e4cf46f935818af32ecac34f9876c618f24e300551cbe3a0ca2c5828cb8d2f9b73e6e1e2f8c64237f70fbc8c541f9b5c9114da70b33b1ed10ba4cc6b15f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"throttle-debounce@npm:^5.0.0, throttle-debounce@npm:^5.0.2":
|
||||
version: 5.0.2
|
||||
resolution: "throttle-debounce@npm:5.0.2"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user