xref: /MusicFree/src/pages/searchPage/components/resultPanel/resultSubPanel.tsx (revision 8c55a6aa7a01f120247fcb5fabac8ec87ebb57cd)
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        // todo: 是否声明不可搜索
50        scene[r.key] = getResultComponent(tab, r.key, r.title);
51    });
52    return SceneMap(scene);
53}
54
55function ResultSubPanel(props: IResultSubPanelProps) {
56    const [index, setIndex] = useState(0);
57
58    const routes = PluginManager.getSearchablePlugins().map(_ => ({
59        key: _.hash,
60        title: _.name,
61    }));
62
63    return (
64        <TabView
65            lazy
66            navigationState={{
67                index,
68                routes,
69            }}
70            renderTabBar={_ => (
71                <TabBar
72                    {..._}
73                    scrollEnabled
74                    style={{
75                        backgroundColor: 'transparent',
76                        shadowColor: 'transparent',
77                        borderColor: 'transparent',
78                    }}
79                    tabStyle={{
80                        width: rpx(200),
81                    }}
82                    renderIndicator={() => null}
83                    pressColor="transparent"
84                    renderLabel={({route, focused, color}) => (
85                        <Text
86                            numberOfLines={1}
87                            style={{
88                                fontWeight: focused
89                                    ? fontWeightConst.bolder
90                                    : fontWeightConst.bold,
91                                color,
92                            }}>
93                            {route.title ?? '(未命名)'}
94                        </Text>
95                    )}
96                />
97            )}
98            renderScene={useCallback(getSubRouterScene(props.tab, routes), [
99                props.tab,
100            ])}
101            onIndexChange={setIndex}
102            initialLayout={{width: rpx(750)}}
103        />
104    );
105}
106
107// 不然会一直重新渲染
108export default memo(ResultSubPanel);
109