1import React, {memo, useEffect, useMemo, useRef, useState} from 'react'; 2import {Text} from 'react-native'; 3import rpx, {vw} from '@/utils/rpx'; 4import {SceneMap, TabBar, TabView} from 'react-native-tab-view'; 5import DefaultResults from './results/defaultResults'; 6import {renderMap} from './results'; 7import ResultWrapper from './resultWrapper'; 8import {fontWeightConst} from '@/constants/uiConst'; 9import {useAtomValue} from 'jotai'; 10import {searchResultsAtom} from '../../store/atoms'; 11import PluginManager from '@/core/pluginManager'; 12import useColors from '@/hooks/useColors'; 13 14interface IResultSubPanelProps { 15 tab: ICommon.SupportMediaType; 16} 17 18// 展示结果的视图 19function getResultComponent( 20 tab: ICommon.SupportMediaType, 21 pluginHash: string, 22 pluginName: string, 23) { 24 return tab in renderMap 25 ? memo( 26 () => { 27 const searchResults = useAtomValue(searchResultsAtom); 28 const pluginSearchResult = searchResults[tab][pluginHash]; 29 const pluginSearchResultRef = useRef(pluginSearchResult); 30 31 useEffect(() => { 32 pluginSearchResultRef.current = pluginSearchResult; 33 }, [pluginSearchResult]); 34 35 return ( 36 <ResultWrapper 37 tab={tab} 38 searchResult={pluginSearchResult} 39 pluginHash={pluginHash} 40 pluginName={pluginName} 41 pluginSearchResultRef={pluginSearchResultRef} 42 /> 43 ); 44 }, 45 () => true, 46 ) 47 : () => <DefaultResults />; 48} 49 50/** 结果scene */ 51function getSubRouterScene( 52 tab: ICommon.SupportMediaType, 53 routes: Array<{key: string; title: string}>, 54) { 55 const scene: Record<string, React.FC> = {}; 56 routes.forEach(r => { 57 // todo: 是否声明不可搜索 58 scene[r.key] = getResultComponent(tab, r.key, r.title); 59 }); 60 return SceneMap(scene); 61} 62 63function ResultSubPanel(props: IResultSubPanelProps) { 64 const [index, setIndex] = useState(0); 65 const colors = useColors(); 66 67 const routes = PluginManager.getSortedSearchablePlugins(props.tab).map( 68 _ => ({ 69 key: _.hash, 70 title: _.name, 71 }), 72 ); 73 const renderScene = useMemo( 74 () => getSubRouterScene(props.tab, routes), 75 [props.tab], 76 ); 77 78 return ( 79 <TabView 80 lazy 81 navigationState={{ 82 index, 83 routes, 84 }} 85 renderTabBar={_ => ( 86 <TabBar 87 {..._} 88 scrollEnabled 89 style={{ 90 backgroundColor: 'transparent', 91 shadowColor: 'transparent', 92 borderColor: 'transparent', 93 }} 94 inactiveColor={colors.text} 95 activeColor={colors.primary} 96 tabStyle={{ 97 width: 'auto', 98 }} 99 renderIndicator={() => null} 100 pressColor="transparent" 101 renderLabel={({route, focused, color}) => ( 102 <Text 103 numberOfLines={1} 104 style={{ 105 width: rpx(140), 106 fontWeight: focused 107 ? fontWeightConst.bolder 108 : fontWeightConst.medium, 109 color, 110 textAlign: 'center', 111 }}> 112 {route.title ?? '(未命名)'} 113 </Text> 114 )} 115 /> 116 )} 117 renderScene={renderScene} 118 onIndexChange={setIndex} 119 initialLayout={{width: vw(100)}} 120 /> 121 ); 122} 123 124// 不然会一直重新渲染 125export default memo(ResultSubPanel); 126