1import React, {memo, useCallback, useState} from 'react'; 2import {Text} from 'react-native'; 3import rpx 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'; 12 13interface IResultSubPanelProps { 14 tab: ICommon.SupportMediaType; 15} 16 17// 展示结果的视图 18function getResultComponent( 19 tab: ICommon.SupportMediaType, 20 pluginHash: string, 21 pluginName: string, 22) { 23 return tab in renderMap 24 ? memo( 25 () => { 26 const searchResults = useAtomValue(searchResultsAtom); 27 const pluginSearchResult = searchResults[tab][pluginHash]; 28 return ( 29 <ResultWrapper 30 tab={tab} 31 searchResult={pluginSearchResult} 32 pluginHash={pluginHash} 33 pluginName={pluginName} 34 /> 35 ); 36 }, 37 () => true, 38 ) 39 : () => <DefaultResults />; 40} 41 42/** 结果scene */ 43function getSubRouterScene( 44 tab: ICommon.SupportMediaType, 45 routes: Array<{key: string; title: string}>, 46) { 47 const scene: Record<string, React.FC> = {}; 48 routes.forEach(r => { 49 scene[r.key] = getResultComponent(tab, r.key, r.title); 50 }); 51 return SceneMap(scene); 52} 53 54function ResultSubPanel(props: IResultSubPanelProps) { 55 const [index, setIndex] = useState(0); 56 // todo 是否聚合结果,如果是的话 57 const routes = PluginManager.getValidPlugins().map(_ => ({ 58 key: _.hash, 59 title: _.name, 60 })); 61 62 return ( 63 <TabView 64 lazy 65 navigationState={{ 66 index, 67 routes, 68 }} 69 renderTabBar={_ => ( 70 <TabBar 71 {..._} 72 scrollEnabled 73 style={{ 74 backgroundColor: 'transparent', 75 shadowColor: 'transparent', 76 borderColor: 'transparent', 77 }} 78 tabStyle={{ 79 width: rpx(200), 80 }} 81 renderIndicator={() => null} 82 pressColor="transparent" 83 renderLabel={({route, focused, color}) => ( 84 <Text 85 numberOfLines={1} 86 style={{ 87 fontWeight: focused 88 ? fontWeightConst.bolder 89 : fontWeightConst.bold, 90 color, 91 }}> 92 {route.title ?? '(未命名)'} 93 </Text> 94 )} 95 /> 96 )} 97 renderScene={useCallback(getSubRouterScene(props.tab, routes), [ 98 props.tab, 99 ])} 100 onIndexChange={setIndex} 101 initialLayout={{width: rpx(750)}} 102 /> 103 ); 104} 105 106// 不然会一直重新渲染 107export default memo(ResultSubPanel); 108