From 14c9cb60014906241aea50469e772c46213362f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A6=96=E9=83=BD=E7=88=B1=E6=8A=A4=E5=8A=A8=E7=89=A9?= =?UTF-8?q?=E5=8D=8F=E4=BC=9A?= <87239270+1355873789@users.noreply.github.com> Date: Sat, 7 Dec 2024 12:27:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8E=86=E5=8F=B2=E6=B6=88=E6=81=AF=E6=87=92?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 性能优化 --- package.json | 2 + .../src/pages/home/Messages/Messages.tsx | 120 ++++++++++++++---- yarn.lock | 29 +++++ 3 files changed, 126 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index 1bcf4e4e..cba4dfec 100644 --- a/package.json +++ b/package.json @@ -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": { diff --git a/src/renderer/src/pages/home/Messages/Messages.tsx b/src/renderer/src/pages/home/Messages/Messages.tsx index a3ebf4fc..3bdfabb7 100644 --- a/src/renderer/src/pages/home/Messages/Messages.tsx +++ b/src/renderer/src/pages/home/Messages/Messages.tsx @@ -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` + 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)` + display: flex; + flex-direction: column-reverse; + padding: 10px 0; + padding-bottom: 20px; + overflow-x: hidden; + background-color: var(--color-background); +` + const Messages: FC = ({ assistant, topic, setActiveTopic }) => { const [messages, setMessages] = useState([]) + const [displayMessages, setDisplayMessages] = useState([]) + const [hasMore, setHasMore] = useState(true) + const [isLoadingMore, setIsLoadingMore] = useState(false) + const containerRef = useRef(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 = ({ assistant, topic, setActiveTopic }) => { setActiveTopic(newTopic) autoRenameTopic() - // 由于复制了消息,消息中附带的文件的总数变了,需要更新 + // 由于复制了消���,消息中附带的文件的总数变了,需要更新 const filesArr = branchMessages.map((m) => m.files) const files = flatten(filesArr).filter(Boolean) files.map(async (f) => { @@ -197,7 +239,31 @@ const Messages: FC = ({ 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 ( = ({ assistant, topic, setActiveTopic }) => { ref={containerRef} right={topicPosition === 'left'}> - {memoizedMessages.map((message, index) => ( - - ))} + + + + + + {displayMessages.map((message, index) => ( + + ))} + + ) } -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 diff --git a/yarn.lock b/yarn.lock index 499c94c2..50c38fa2 100644 --- a/yarn.lock +++ b/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"