Wunderbar: change throttle to debounce + add min chars

## Issue
6314: prevent lighthouse spam from wunderbar

## Changes
- Wunderbar: change throttle to debounce + add min chars.
- useLighthouse: added option to not throttle.
This commit is contained in:
infinite-persistence 2021-06-23 11:40:13 +08:00 committed by Thomas Zarebczan
parent 2ba3f05725
commit 36ac9e038d
2 changed files with 23 additions and 10 deletions

View file

@ -16,7 +16,6 @@ import WunderbarTopSuggestion from 'component/wunderbarTopSuggestion';
import WunderbarSuggestion from 'component/wunderbarSuggestion'; import WunderbarSuggestion from 'component/wunderbarSuggestion';
import { useHistory } from 'react-router'; import { useHistory } from 'react-router';
import { formatLbryUrlForWeb } from 'util/url'; import { formatLbryUrlForWeb } from 'util/url';
import useThrottle from 'effects/use-throttle';
import Yrbl from 'component/yrbl'; import Yrbl from 'component/yrbl';
import { SEARCH_OPTIONS } from 'constants/search'; import { SEARCH_OPTIONS } from 'constants/search';
@ -31,6 +30,9 @@ const TAG_SEARCH_PREFIX = 'tag:';
const L_KEY_CODE = 76; const L_KEY_CODE = 76;
const ESC_KEY_CODE = 27; const ESC_KEY_CODE = 27;
const WUNDERBAR_INPUT_DEBOUNCE_MS = 500;
const LIGHTHOUSE_MIN_CHARACTERS = 3;
type Props = { type Props = {
searchQuery: ?string, searchQuery: ?string,
onSearch: (string) => void, onSearch: (string) => void,
@ -69,14 +71,14 @@ export default function WunderBarSuggestions(props: Props) {
const urlParams = new URLSearchParams(search); const urlParams = new URLSearchParams(search);
const queryFromUrl = urlParams.get('q') || ''; const queryFromUrl = urlParams.get('q') || '';
const [term, setTerm] = React.useState(queryFromUrl); const [term, setTerm] = React.useState(queryFromUrl);
const throttledTerm = useThrottle(term, 500) || ''; const [debouncedTerm, setDebouncedTerm] = React.useState('');
const searchSize = isMobile ? 20 : 5; const searchSize = isMobile ? 20 : 5;
const additionalOptions = channelsOnly const additionalOptions = channelsOnly
? { isBackgroundSearch: false, [SEARCH_OPTIONS.CLAIM_TYPE]: SEARCH_OPTIONS.INCLUDE_CHANNELS } ? { isBackgroundSearch: false, [SEARCH_OPTIONS.CLAIM_TYPE]: SEARCH_OPTIONS.INCLUDE_CHANNELS }
: {}; : {};
const { results, loading } = useLighthouse(throttledTerm, showMature, searchSize, additionalOptions); const { results, loading } = useLighthouse(debouncedTerm, showMature, searchSize, additionalOptions, 0);
const noResults = throttledTerm && !loading && results && results.length === 0; const noResults = debouncedTerm && !loading && results && results.length === 0;
const nameFromQuery = throttledTerm.trim().replace(/\s+/g, '').replace(/:/g, '#'); const nameFromQuery = debouncedTerm.trim().replace(/\s+/g, '').replace(/:/g, '#');
const uriFromQuery = `lbry://${nameFromQuery}`; const uriFromQuery = `lbry://${nameFromQuery}`;
let uriFromQueryIsValid = false; let uriFromQueryIsValid = false;
let channelUrlForTopTest; let channelUrlForTopTest;
@ -156,6 +158,16 @@ export default function WunderBarSuggestions(props: Props) {
} }
} }
React.useEffect(() => {
const timer = setTimeout(() => {
if (debouncedTerm !== term) {
setDebouncedTerm(term.length < LIGHTHOUSE_MIN_CHARACTERS ? '' : term);
}
}, WUNDERBAR_INPUT_DEBOUNCE_MS);
return () => clearTimeout(timer);
}, [term, debouncedTerm]);
React.useEffect(() => { React.useEffect(() => {
function handleHomeEndCaretPos(elem, shiftKey, isHome) { function handleHomeEndCaretPos(elem, shiftKey, isHome) {
if (elem) { if (elem) {
@ -294,7 +306,7 @@ export default function WunderBarSuggestions(props: Props) {
{uriFromQueryIsValid && !noTopSuggestion ? <WunderbarTopSuggestion query={nameFromQuery} /> : null} {uriFromQueryIsValid && !noTopSuggestion ? <WunderbarTopSuggestion query={nameFromQuery} /> : null}
<div className="wunderbar__label">{__('Search Results')}</div> <div className="wunderbar__label">{__('Search Results')}</div>
{results.slice(0, isMobile ? 20 : 5).map((uri) => ( {results.slice(0, term.length < LIGHTHOUSE_MIN_CHARACTERS ? 0 : isMobile ? 20 : 5).map((uri) => (
<WunderbarSuggestion key={uri} uri={uri} /> <WunderbarSuggestion key={uri} uri={uri} />
))} ))}

View file

@ -7,14 +7,15 @@ import useThrottle from './use-throttle';
export default function useLighthouse( export default function useLighthouse(
query: string, query: string,
showMature?: boolean, showMature: boolean,
size?: number = 5, size: number = 5,
additionalOptions: any = {} additionalOptions: any = {},
throttleMs: number = 500
) { ) {
const [results, setResults] = React.useState(); const [results, setResults] = React.useState();
const [loading, setLoading] = React.useState(); const [loading, setLoading] = React.useState();
const queryString = query ? getSearchQueryString(query, { nsfw: showMature, size, ...additionalOptions }) : ''; const queryString = query ? getSearchQueryString(query, { nsfw: showMature, size, ...additionalOptions }) : '';
const throttledQuery = useThrottle(queryString, 500); const throttledQuery = useThrottle(queryString, throttleMs);
React.useEffect(() => { React.useEffect(() => {
if (throttledQuery) { if (throttledQuery) {