xref: /MusicFree/src/pages/searchPage/components/resultPanel/resultSubPanel.tsx (revision 428a07232c590a64f321e5de380e0b764e4a2b5e)
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';
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                  const pluginSearchResultRef = useRef(pluginSearchResult);
29
30                  useEffect(() => {
31                      pluginSearchResultRef.current = pluginSearchResult;
32                  }, [pluginSearchResult]);
33
34                  return (
35                      <ResultWrapper
36                          tab={tab}
37                          searchResult={pluginSearchResult}
38                          pluginHash={pluginHash}
39                          pluginName={pluginName}
40                          pluginSearchResultRef={pluginSearchResultRef}
41                      />
42                  );
43              },
44              () => true,
45          )
46        : () => <DefaultResults />;
47}
48
49/** 结果scene */
50function getSubRouterScene(
51    tab: ICommon.SupportMediaType,
52    routes: Array<{key: string; title: string}>,
53) {
54    const scene: Record<string, React.FC> = {};
55    routes.forEach(r => {
56        // todo: 是否声明不可搜索
57        scene[r.key] = getResultComponent(tab, r.key, r.title);
58    });
59    return SceneMap(scene);
60}
61
62function ResultSubPanel(props: IResultSubPanelProps) {
63    const [index, setIndex] = useState(0);
64
65    const routes = PluginManager.getSortedSearchablePlugins(props.tab).map(
66        _ => ({
67            key: _.hash,
68            title: _.name,
69        }),
70    );
71    const renderScene = useMemo(
72        () => getSubRouterScene(props.tab, routes),
73        [props.tab],
74    );
75
76    return (
77        <TabView
78            lazy
79            navigationState={{
80                index,
81                routes,
82            }}
83            renderTabBar={_ => (
84                <TabBar
85                    {..._}
86                    scrollEnabled
87                    style={{
88                        backgroundColor: 'transparent',
89                        shadowColor: 'transparent',
90                        borderColor: 'transparent',
91                    }}
92                    tabStyle={{
93                        width: rpx(200),
94                    }}
95                    renderIndicator={() => null}
96                    pressColor="transparent"
97                    renderLabel={({route, focused, color}) => (
98                        <Text
99                            numberOfLines={1}
100                            style={{
101                                fontWeight: focused
102                                    ? fontWeightConst.bolder
103                                    : fontWeightConst.bold,
104                                color,
105                            }}>
106                            {route.title ?? '(未命名)'}
107                        </Text>
108                    )}
109                />
110            )}
111            renderScene={renderScene}
112            onIndexChange={setIndex}
113            initialLayout={{width: vw(100)}}
114        />
115    );
116}
117
118// 不然会一直重新渲染
119export default memo(ResultSubPanel);
120