feat(Messages): Implement topic branching and file reference tracking

- Add support for creating new topics from message branches
- Implement file reference count update when branching messages
- Enhance EventEmitter to handle NEW_BRANCH event
- Integrate database operations for topic and file management
This commit is contained in:
kangfenmao 2025-03-11 15:08:40 +08:00
parent 6bcc21c578
commit 92ed848d4e

View File

@ -1,5 +1,6 @@
import Scrollbar from '@renderer/components/Scrollbar' import Scrollbar from '@renderer/components/Scrollbar'
import { LOAD_MORE_COUNT } from '@renderer/config/constant' import { LOAD_MORE_COUNT } from '@renderer/config/constant'
import db from '@renderer/databases'
import { useAssistant } from '@renderer/hooks/useAssistant' import { useAssistant } from '@renderer/hooks/useAssistant'
import { useMessageOperations } from '@renderer/hooks/useMessageOperations' import { useMessageOperations } from '@renderer/hooks/useMessageOperations'
import { useSettings } from '@renderer/hooks/useSettings' import { useSettings } from '@renderer/hooks/useSettings'
@ -18,7 +19,7 @@ import {
removeSpecialCharactersForFileName, removeSpecialCharactersForFileName,
runAsyncFunction runAsyncFunction
} from '@renderer/utils' } from '@renderer/utils'
import { isEmpty, last } from 'lodash' import { flatten, isEmpty, last, take } from 'lodash'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import InfiniteScroll from 'react-infinite-scroll-component' import InfiniteScroll from 'react-infinite-scroll-component'
@ -39,13 +40,13 @@ interface MessagesProps {
const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic }) => { const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic }) => {
const { t } = useTranslation() const { t } = useTranslation()
const { showTopics, topicPosition, showAssistants, enableTopicNaming } = useSettings() const { showTopics, topicPosition, showAssistants, enableTopicNaming } = useSettings()
const { updateTopic } = useAssistant(assistant.id) const { updateTopic, addTopic } = useAssistant(assistant.id)
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
const containerRef = useRef<HTMLDivElement>(null) const containerRef = useRef<HTMLDivElement>(null)
const [displayMessages, setDisplayMessages] = useState<Message[]>([]) const [displayMessages, setDisplayMessages] = useState<Message[]>([])
const [hasMore, setHasMore] = useState(false) const [hasMore, setHasMore] = useState(false)
const [isLoadingMore, setIsLoadingMore] = useState(false) const [isLoadingMore, setIsLoadingMore] = useState(false)
const { messages, loading, displayCount, updateMessages, clearTopicMessages } = useMessageOperations(topic) const { messages, displayCount, updateMessages, clearTopicMessages, deleteMessage } = useMessageOperations(topic)
useEffect(() => { useEffect(() => {
const reversedMessages = [...messages].reverse() const reversedMessages = [...messages].reverse()
@ -132,9 +133,9 @@ const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic })
}), }),
EventEmitter.on(EVENT_NAMES.NEW_CONTEXT, async () => { EventEmitter.on(EVENT_NAMES.NEW_CONTEXT, async () => {
const lastMessage = last(messages) const lastMessage = last(messages)
if (lastMessage?.type === 'clear') { if (lastMessage?.type === 'clear') {
// TODO deleteMessage(lastMessage)
// handleDeleteMessage(lastMessage)
scrollToBottom() scrollToBottom()
return return
} }
@ -144,15 +145,32 @@ const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic })
const clearMessage = getUserMessage({ assistant, topic, type: 'clear' }) const clearMessage = getUserMessage({ assistant, topic, type: 'clear' })
const newMessages = [...messages, clearMessage] const newMessages = [...messages, clearMessage]
await updateMessages(newMessages) await updateMessages(newMessages)
scrollToBottom() scrollToBottom()
}),
EventEmitter.on(EVENT_NAMES.NEW_BRANCH, async (index: number) => {
const newTopic = getDefaultTopic(assistant.id)
newTopic.name = topic.name
const branchMessages = take(messages, messages.length - index)
// 将分支的消息放入数据库
await db.topics.add({ id: newTopic.id, messages: branchMessages })
addTopic(newTopic)
setActiveTopic(newTopic)
autoRenameTopic()
// 由于复制了消息,消息中附带的文件的总数变了,需要更新
const filesArr = branchMessages.map((m) => m.files)
const files = flatten(filesArr).filter(Boolean)
files.map(async (f) => {
const file = await db.files.get({ id: f?.id })
file && db.files.update(file.id, { count: file.count + 1 })
})
}) })
] ]
return () => { return () => unsubscribes.forEach((unsub) => unsub())
for (const unsub of unsubscribes) {
unsub()
}
}
}, [assistant, dispatch, scrollToBottom, topic, updateTopic]) }, [assistant, dispatch, scrollToBottom, topic, updateTopic])
useEffect(() => { useEffect(() => {