mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-08 06:19:05 +08:00
fix: enhance message loading and search functionality in HistoryPage and SearchResults
- Integrated Redux dispatch to load topic messages when a message is clicked in HistoryPage. - Updated SearchResults to utilize message blocks for improved search results, including content extraction. - Refactored state management to accommodate new content structure in search results.
This commit is contained in:
parent
0079f4f437
commit
bd8452032e
@ -1,4 +1,6 @@
|
|||||||
import { ArrowLeftOutlined, EnterOutlined } from '@ant-design/icons'
|
import { ArrowLeftOutlined, EnterOutlined } from '@ant-design/icons'
|
||||||
|
import { useAppDispatch } from '@renderer/store'
|
||||||
|
import { loadTopicMessagesThunk } from '@renderer/store/thunk/messageThunk'
|
||||||
import { Topic } from '@renderer/types'
|
import { Topic } from '@renderer/types'
|
||||||
import type { Message } from '@renderer/types/newMessage'
|
import type { Message } from '@renderer/types/newMessage'
|
||||||
import { Input, InputRef } from 'antd'
|
import { Input, InputRef } from 'antd'
|
||||||
@ -28,6 +30,7 @@ const TopicsPage: FC = () => {
|
|||||||
const [topic, setTopic] = useState<Topic | undefined>(_topic)
|
const [topic, setTopic] = useState<Topic | undefined>(_topic)
|
||||||
const [message, setMessage] = useState<Message | undefined>(_message)
|
const [message, setMessage] = useState<Message | undefined>(_message)
|
||||||
const inputRef = useRef<InputRef>(null)
|
const inputRef = useRef<InputRef>(null)
|
||||||
|
const dispatch = useAppDispatch()
|
||||||
|
|
||||||
_search = search
|
_search = search
|
||||||
_stack = stack
|
_stack = stack
|
||||||
@ -55,6 +58,7 @@ const TopicsPage: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onMessageClick = (message: Message) => {
|
const onMessageClick = (message: Message) => {
|
||||||
|
dispatch(loadTopicMessagesThunk(message.topicId))
|
||||||
setStack(['topics', 'search', 'message'])
|
setStack(['topics', 'search', 'message'])
|
||||||
setMessage(message)
|
setMessage(message)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,11 +2,10 @@ import db from '@renderer/databases'
|
|||||||
import useScrollPosition from '@renderer/hooks/useScrollPosition'
|
import useScrollPosition from '@renderer/hooks/useScrollPosition'
|
||||||
import { getTopicById } from '@renderer/hooks/useTopic'
|
import { getTopicById } from '@renderer/hooks/useTopic'
|
||||||
import { Topic } from '@renderer/types'
|
import { Topic } from '@renderer/types'
|
||||||
import type { Message } from '@renderer/types/newMessage'
|
import { type Message, MessageBlockType } from '@renderer/types/newMessage'
|
||||||
import { getMainTextContent } from '@renderer/utils/messageUtils/find'
|
|
||||||
import { List, Typography } from 'antd'
|
import { List, Typography } from 'antd'
|
||||||
import { useLiveQuery } from 'dexie-react-hooks'
|
import { useLiveQuery } from 'dexie-react-hooks'
|
||||||
import { FC, memo, useCallback, useEffect, useMemo, useState } from 'react'
|
import { FC, memo, useCallback, useEffect, useState } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
const { Text, Title } = Typography
|
const { Text, Title } = Typography
|
||||||
@ -29,12 +28,7 @@ const SearchResults: FC<Props> = ({ keywords, onMessageClick, onTopicClick, ...p
|
|||||||
|
|
||||||
const topics = useLiveQuery(() => db.topics.toArray(), [])
|
const topics = useLiveQuery(() => db.topics.toArray(), [])
|
||||||
|
|
||||||
const messages = useMemo(
|
const [searchResults, setSearchResults] = useState<{ message: Message; topic: Topic; content: string }[]>([])
|
||||||
() => (topics || [])?.map((topic) => topic.messages.filter((message) => message.role !== 'user')).flat(),
|
|
||||||
[topics]
|
|
||||||
)
|
|
||||||
|
|
||||||
const [searchResults, setSearchResults] = useState<{ message: Message; topic: Topic }[]>([])
|
|
||||||
const [searchStats, setSearchStats] = useState({ count: 0, time: 0 })
|
const [searchStats, setSearchStats] = useState({ count: 0, time: 0 })
|
||||||
|
|
||||||
const removeMarkdown = (text: string) => {
|
const removeMarkdown = (text: string) => {
|
||||||
@ -58,17 +52,23 @@ const SearchResults: FC<Props> = ({ keywords, onMessageClick, onTopicClick, ...p
|
|||||||
}
|
}
|
||||||
|
|
||||||
const startTime = performance.now()
|
const startTime = performance.now()
|
||||||
const results: { message: Message; topic: Topic }[] = []
|
const results: { message: Message; topic: Topic; content: string }[] = []
|
||||||
const newSearchTerms = keywords
|
const newSearchTerms = keywords
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.split(' ')
|
.split(' ')
|
||||||
.filter((term) => term.length > 0)
|
.filter((term) => term.length > 0)
|
||||||
|
|
||||||
for (const message of messages) {
|
const blocksArray = await db.message_blocks.toArray()
|
||||||
const content = getMainTextContent(message)
|
const blocks = blocksArray
|
||||||
const cleanContent = removeMarkdown(content.toLowerCase())
|
.filter((block) => block.type === MessageBlockType.MAIN_TEXT)
|
||||||
if (newSearchTerms.every((term) => cleanContent.includes(term))) {
|
.filter((block) => newSearchTerms.some((term) => block.content.toLowerCase().includes(term)))
|
||||||
results.push({ message, topic: await getTopicById(message.topicId)! })
|
|
||||||
|
const messages = topics?.map((topic) => topic.messages).flat()
|
||||||
|
|
||||||
|
for (const block of blocks) {
|
||||||
|
const message = messages?.find((message) => message.id === block.messageId)
|
||||||
|
if (message) {
|
||||||
|
results.push({ message, topic: await getTopicById(message.topicId)!, content: block.content })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ const SearchResults: FC<Props> = ({ keywords, onMessageClick, onTopicClick, ...p
|
|||||||
time: (endTime - startTime) / 1000
|
time: (endTime - startTime) / 1000
|
||||||
})
|
})
|
||||||
setSearchTerms(newSearchTerms)
|
setSearchTerms(newSearchTerms)
|
||||||
}, [messages, keywords])
|
}, [keywords, topics])
|
||||||
|
|
||||||
const highlightText = (text: string) => {
|
const highlightText = (text: string) => {
|
||||||
let highlightedText = removeMarkdown(text)
|
let highlightedText = removeMarkdown(text)
|
||||||
@ -115,7 +115,7 @@ const SearchResults: FC<Props> = ({ keywords, onMessageClick, onTopicClick, ...p
|
|||||||
setTimeout(() => containerRef.current?.scrollTo({ top: 0 }), 0)
|
setTimeout(() => containerRef.current?.scrollTo({ top: 0 }), 0)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
renderItem={({ message, topic }) => (
|
renderItem={({ message, topic, content }) => (
|
||||||
<List.Item>
|
<List.Item>
|
||||||
<Title
|
<Title
|
||||||
level={5}
|
level={5}
|
||||||
@ -127,7 +127,7 @@ const SearchResults: FC<Props> = ({ keywords, onMessageClick, onTopicClick, ...p
|
|||||||
{topic.name}
|
{topic.name}
|
||||||
</Title>
|
</Title>
|
||||||
<div style={{ cursor: 'pointer' }} onClick={() => onMessageClick(message)}>
|
<div style={{ cursor: 'pointer' }} onClick={() => onMessageClick(message)}>
|
||||||
<Text>{highlightText(getMainTextContent(message))}</Text>
|
<Text>{highlightText(content)}</Text>
|
||||||
</div>
|
</div>
|
||||||
<SearchResultTime>
|
<SearchResultTime>
|
||||||
<Text type="secondary">{new Date(message.createdAt).toLocaleString()}</Text>
|
<Text type="secondary">{new Date(message.createdAt).toLocaleString()}</Text>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user