feat(search): add keyword highlighting to PostCard and improve QRCodeScanner
Add HighlightText component for search result highlighting in PostCard. Refactor QRCodeScanner to use async permission methods with better error handling. Improve SearchScreen with stable function refs and pass highlightKeyword to PostCard. Modernize MessageListScreen search UI with SearchBar and TabBar components. Add emoji virtualization to EmojiPanel and auto-focus input after inserting emoji. BREAKING CHANGE: EmojiPanel onFocusInput prop added for focus management
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
* 支持响应式布局,宽屏下显示更大的搜索结果区域
|
||||
*/
|
||||
|
||||
import React, { useState, useCallback, useEffect, useMemo } from 'react';
|
||||
import React, { useState, useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import {
|
||||
View,
|
||||
FlatList,
|
||||
@@ -80,7 +80,8 @@ export const SearchScreen: React.FC<SearchScreenProps> = ({ onBack }) => {
|
||||
// 保存当前搜索关键词,用于Tab切换时重新搜索
|
||||
const [currentKeyword, setCurrentKeyword] = useState('');
|
||||
|
||||
// 使用游标分页进行帖子搜索
|
||||
const searchExtraParams = useMemo(() => ({ query: currentKeyword }), [currentKeyword]);
|
||||
|
||||
const {
|
||||
list: searchResults,
|
||||
isLoading,
|
||||
@@ -100,20 +101,25 @@ export const SearchScreen: React.FC<SearchScreenProps> = ({ onBack }) => {
|
||||
});
|
||||
return response;
|
||||
},
|
||||
{ pageSize: DEFAULT_PAGE_SIZE },
|
||||
{ query: '' }
|
||||
{ pageSize: DEFAULT_PAGE_SIZE, autoLoad: false },
|
||||
searchExtraParams
|
||||
);
|
||||
|
||||
// 用户搜索结果(保持原有分页方式)
|
||||
const [userResults, setUserResults] = useState<User[]>([]);
|
||||
const [userLoading, setUserLoading] = useState(false);
|
||||
|
||||
const refreshRef = useRef(refresh);
|
||||
refreshRef.current = refresh;
|
||||
const resetRef = useRef(reset);
|
||||
resetRef.current = reset;
|
||||
|
||||
// 当搜索词变化时重置
|
||||
useEffect(() => {
|
||||
if (currentKeyword) {
|
||||
refresh();
|
||||
refreshRef.current();
|
||||
} else {
|
||||
reset();
|
||||
resetRef.current();
|
||||
}
|
||||
}, [currentKeyword]);
|
||||
|
||||
@@ -132,11 +138,7 @@ export const SearchScreen: React.FC<SearchScreenProps> = ({ onBack }) => {
|
||||
try {
|
||||
const searchType = getSearchType();
|
||||
|
||||
if (searchType === 'posts') {
|
||||
// 帖子搜索由 useCursorPagination 处理,这里只需触发刷新
|
||||
refresh();
|
||||
} else if (searchType === 'users') {
|
||||
// 用户搜索保持原有方式
|
||||
if (searchType === 'users') {
|
||||
setUserLoading(true);
|
||||
const usersResponse = await authService.searchUsers(trimmedKeyword, 1, 20);
|
||||
setUserResults(usersResponse.list || []);
|
||||
@@ -259,6 +261,7 @@ export const SearchScreen: React.FC<SearchScreenProps> = ({ onBack }) => {
|
||||
onAction={(action) => handlePostAction(post, action)}
|
||||
variant="list"
|
||||
features={isMobile ? 'compact' : 'full'}
|
||||
highlightKeyword={currentKeyword}
|
||||
/>
|
||||
))}
|
||||
</ResponsiveGrid>
|
||||
@@ -281,6 +284,7 @@ export const SearchScreen: React.FC<SearchScreenProps> = ({ onBack }) => {
|
||||
onAction={(action) => handlePostAction(item, action)}
|
||||
variant="list"
|
||||
features="compact"
|
||||
highlightKeyword={currentKeyword}
|
||||
/>
|
||||
)}
|
||||
keyExtractor={item => item.id}
|
||||
|
||||
Reference in New Issue
Block a user