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