xref: /MusicFree/src/pages/artistDetail/components/resultList.tsx (revision 5d19d26c98d1c233995663070b95e5f28b5b9e1c)
1import React, {useEffect, useRef, useState} from 'react';
2import rpx from '@/utils/rpx';
3import {FlatList} from 'react-native-gesture-handler';
4import {useAtom} from 'jotai';
5import {IQueryResult, scrollToTopAtom} from '../store/atoms';
6import {RequestStateCode} from '@/constants/commonConst';
7import useQueryArtist from '../hooks/useQuery';
8import {useRoute} from '@react-navigation/native';
9import Empty from '@/components/base/empty';
10import ListLoading from '@/components/base/listLoading';
11import ListReachEnd from '@/components/base/listReachEnd';
12
13const ITEM_HEIGHT = rpx(120);
14
15interface IResultListProps<T = IArtist.ArtistMediaType> {
16    tab: T;
17    data: IQueryResult<T>;
18    renderItem: (...args: any) => any;
19}
20export default function ResultList(props: IResultListProps) {
21    const {data, renderItem, tab} = props;
22    const [scrollToTopState, setScrollToTopState] = useAtom(scrollToTopAtom);
23    const lastScrollY = useRef<number>(0);
24    const route = useRoute<any>();
25    const pluginHash: string = route.params.pluginHash;
26    const artistItem: IArtist.IArtistItem = route.params.artistItem;
27    const [queryState, setQueryState] = useState<RequestStateCode>(
28        data?.state ?? RequestStateCode.IDLE,
29    );
30
31    const queryArtist = useQueryArtist(pluginHash);
32
33    useEffect(() => {
34        queryState === RequestStateCode.IDLE && queryArtist(artistItem, 1, tab);
35    }, []);
36
37    useEffect(() => {
38        setQueryState(data?.state ?? RequestStateCode.IDLE);
39    }, [data]);
40
41    return (
42        <FlatList
43            onScroll={e => {
44                const currentY = e.nativeEvent.contentOffset.y;
45                if (
46                    !scrollToTopState &&
47                    currentY < ITEM_HEIGHT * 8 - rpx(350)
48                ) {
49                    currentY < lastScrollY.current && setScrollToTopState(true);
50                } else {
51                    if (scrollToTopState && currentY > ITEM_HEIGHT * 8) {
52                        currentY > lastScrollY.current &&
53                            setScrollToTopState(false);
54                    }
55                }
56                lastScrollY.current = currentY;
57            }}
58            ListEmptyComponent={<Empty />}
59            ListFooterComponent={
60                queryState === RequestStateCode.PENDING ? (
61                    <ListLoading />
62                ) : queryState === RequestStateCode.FINISHED &&
63                  data.data?.length !== 0 ? (
64                    <ListReachEnd />
65                ) : (
66                    <></>
67                )
68            }
69            onEndReached={() => {
70                (queryState === RequestStateCode.IDLE ||
71                    queryState === RequestStateCode.PARTLY_DONE) &&
72                    queryArtist(artistItem, undefined, tab);
73            }}
74            getItemLayout={(_, index) => ({
75                length: ITEM_HEIGHT,
76                offset: ITEM_HEIGHT * index,
77                index,
78            })}
79            overScrollMode="always"
80            data={data.data ?? []}
81            renderItem={renderItem}
82        />
83    );
84}
85