// @flow import React from 'react'; import ClaimList from 'component/claimList'; import { DEBOUNCE_WAIT_DURATION_MS, SEARCH_PAGE_SIZE } from 'constants/search'; import { lighthouse } from 'redux/actions/search'; type Props = { searchQuery: string, claimId: ?string, showMature: ?boolean, tileLayout: boolean, onResults?: (results: ?Array) => void, doResolveUris: (Array, boolean) => void, }; export function SearchResults(props: Props) { const { searchQuery, claimId, showMature, tileLayout, onResults, doResolveUris } = props; const [page, setPage] = React.useState(1); const [searchResults, setSearchResults] = React.useState(undefined); const [isSearching, setIsSearching] = React.useState(false); const noMoreResults = React.useRef(false); React.useEffect(() => { setPage(1); }, [searchQuery]); React.useEffect(() => { if (onResults) { onResults(searchResults); } }, [searchResults, onResults]); React.useEffect(() => { const timer = setTimeout(() => { if (searchQuery.trim().length < 3 || !claimId) { return setSearchResults(null); } setIsSearching(true); lighthouse .search( `from=${SEARCH_PAGE_SIZE * (page - 1)}` + `&s=${encodeURIComponent(searchQuery)}` + `&channel_id=${encodeURIComponent(claimId)}` + `&nsfw=${showMature ? 'true' : 'false'}` + `&size=${SEARCH_PAGE_SIZE}` ) .then(({ body: results }) => { const urls = results.map(({ name, claimId }) => { return `lbry://${name}#${claimId}`; }); // Batch-resolve the urls before calling 'setSearchResults', as the // latter will immediately cause the tiles to resolve, ending up // calling doResolveUri one by one before the batched one. doResolveUris(urls, true); // De-dup (LH will return some duplicates) and concat results setSearchResults((prev) => (page === 1 ? urls : Array.from(new Set((prev || []).concat(urls))))); noMoreResults.current = !urls || urls.length < SEARCH_PAGE_SIZE; }) .catch(() => { setPage(1); setSearchResults(null); noMoreResults.current = false; }) .finally(() => { setIsSearching(false); }); }, DEBOUNCE_WAIT_DURATION_MS); return () => clearTimeout(timer); }, [searchQuery, claimId, page, showMature, doResolveUris]); if (!searchResults) { return null; } return ( setPage((prev) => (noMoreResults.current ? prev : prev + 1))} page={page} pageSize={SEARCH_PAGE_SIZE} tileLayout={tileLayout} useLoadingSpinner /> ); }