xref: /MusicFree/src/pages/searchPage/components/resultPanel/resultWrapper.tsx (revision 268ffae051f9727ffd7aa44d5171e698a9dc4fd2)
1import React, {memo, useEffect, useState} from 'react';
2import {useAtomValue} from 'jotai';
3import {ISearchResult, queryAtom} from '../../store/atoms';
4import {renderMap} from './results';
5import useSearch from '../../hooks/useSearch';
6import Loading from '@/components/base/loading';
7import {RequestStateCode} from '@/constants/commonConst';
8import ListLoading from '@/components/base/listLoading';
9import Empty from '@/components/base/empty';
10import ListReachEnd from '@/components/base/listReachEnd';
11import useOrientation from '@/hooks/useOrientation';
12import {FlashList} from '@shopify/flash-list';
13import rpx from '@/utils/rpx';
14import {StyleSheet, View} from 'react-native';
15
16interface IResultWrapperProps<
17    T extends ICommon.SupportMediaType = ICommon.SupportMediaType,
18> {
19    tab: T;
20    pluginHash: string;
21    pluginName: string;
22    searchResult: ISearchResult<T>;
23    pluginSearchResultRef: React.MutableRefObject<ISearchResult<T>>;
24}
25function ResultWrapper(props: IResultWrapperProps) {
26    const {tab, pluginHash, searchResult, pluginSearchResultRef} = props;
27    const search = useSearch();
28    const [searchState, setSearchState] = useState<RequestStateCode>(
29        searchResult?.state ?? RequestStateCode.IDLE,
30    );
31    const orientation = useOrientation();
32    const query = useAtomValue(queryAtom);
33
34    const ResultComponent = renderMap[tab]!;
35    const data: any = searchResult?.data ?? [];
36
37    useEffect(() => {
38        if (searchState === RequestStateCode.IDLE) {
39            search(query, 1, tab, pluginHash);
40        }
41    }, []);
42
43    useEffect(() => {
44        setSearchState(searchResult?.state ?? RequestStateCode.IDLE);
45    }, [searchResult]);
46
47    const renderItem = ({item, index}: any) => (
48        <ResultComponent
49            item={item}
50            index={index}
51            pluginHash={pluginHash}
52            pluginSearchResultRef={pluginSearchResultRef}
53        />
54    );
55
56    return searchState === RequestStateCode.PENDING_FIRST_PAGE ? (
57        <Loading />
58    ) : (
59        <FlashList
60            extraData={searchState}
61            ListEmptyComponent={() => <Empty />}
62            ListFooterComponent={() => (
63                <View style={style.wrapper}>
64                    {searchState === RequestStateCode.PENDING_REST_PAGE ? (
65                        <ListLoading />
66                    ) : searchState === RequestStateCode.FINISHED ? (
67                        <ListReachEnd />
68                    ) : (
69                        <></>
70                    )}
71                </View>
72            )}
73            data={data}
74            refreshing={false}
75            onRefresh={() => {
76                search(query, 1, tab, pluginHash);
77            }}
78            onEndReached={() => {
79                (searchState === RequestStateCode.PARTLY_DONE ||
80                    searchState === RequestStateCode.IDLE) &&
81                    search(undefined, undefined, tab, pluginHash);
82            }}
83            estimatedItemSize={tab === 'sheet' ? rpx(306) : rpx(120)}
84            numColumns={
85                tab === 'sheet' ? (orientation === 'vertical' ? 3 : 4) : 1
86            }
87            renderItem={renderItem}
88        />
89    );
90}
91
92export default memo(ResultWrapper);
93const style = StyleSheet.create({
94    wrapper: {
95        width: '100%',
96        height: rpx(140),
97        justifyContent: 'center',
98        alignItems: 'center',
99    },
100});
101