lbry-desktop/ui/component/channelContent/internal/searchResults.jsx

93 lines
2.8 KiB
React
Raw Normal View History

// @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<string>) => void,
doResolveUris: (Array<string>, 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 (
<ClaimList
uris={searchResults}
loading={isSearching}
onScrollBottom={() => setPage((prev) => (noMoreResults.current ? prev : prev + 1))}
page={page}
pageSize={SEARCH_PAGE_SIZE}
tileLayout={tileLayout}
useLoadingSpinner
/>
);
}