import { useCallback, useEffect, useRef, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { Path } from '../constant'; import CloseIcon from '../icons/close.svg'; import EyeIcon from '../icons/eye.svg'; import Locale from '../locales'; import { useChatStore } from '../store'; import { IconButton } from './button'; import { ErrorBoundary } from './error'; import styles from './mask.module.scss'; interface Item { id: number; name: string; content: string; } export function SearchChatPage() { const navigate = useNavigate(); const chatStore = useChatStore(); const sessions = chatStore.sessions; const selectSession = chatStore.selectSession; const [searchResults, setSearchResults] = useState([]); const previousValueRef = useRef(''); const searchInputRef = useRef(null); const doSearch = useCallback((text: string) => { const lowerCaseText = text.toLowerCase(); const results: Item[] = []; sessions.forEach((session, index) => { const fullTextContents: string[] = []; session.messages.forEach((message) => { const content = message.content as string; if (!content.toLowerCase || content === '') { return; } const lowerCaseContent = content.toLowerCase(); // full text search let pos = lowerCaseContent.indexOf(lowerCaseText); while (pos !== -1) { const start = Math.max(0, pos - 35); const end = Math.min(content.length, pos + lowerCaseText.length + 35); fullTextContents.push(content.substring(start, end)); pos = lowerCaseContent.indexOf( lowerCaseText, pos + lowerCaseText.length, ); } }); if (fullTextContents.length > 0) { results.push({ id: index, name: session.topic, content: fullTextContents.join('... '), // concat content with... }); } }); // sort by length of matching content results.sort((a, b) => b.content.length - a.content.length); return results; }, []); useEffect(() => { const intervalId = setInterval(() => { if (searchInputRef.current) { const currentValue = searchInputRef.current.value; if (currentValue !== previousValueRef.current) { if (currentValue.length > 0) { const result = doSearch(currentValue); setSearchResults(result); } previousValueRef.current = currentValue; } } }, 1000); // Cleanup the interval on component unmount return () => clearInterval(intervalId); }, [doSearch]); return (
{/* header */}
{Locale.SearchChat.Page.Title}
{Locale.SearchChat.Page.SubTitle(searchResults.length)}
} bordered onClick={() => navigate(-1)} />
{/** 搜索输入框 */} { if (e.key === 'Enter') { e.preventDefault(); const searchText = e.currentTarget.value; if (searchText.length > 0) { const result = doSearch(searchText); setSearchResults(result); } } }} />
{searchResults.map(item => (
{ navigate(Path.Chat); selectSession(item.id); }} style={{ cursor: 'pointer' }} > {/** 搜索匹配的文本 */}
{item.name}
{item.content.slice(0, 70)}
{/** 操作按钮 */}
} text={Locale.SearchChat.Item.View} />
))}
); }