Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1648,6 +1648,7 @@ const CONST = {
LOCATION_UPDATE_INTERVAL: 5000,
PLAY_SOUND_MESSAGE_DEBOUNCE_TIME: 500,
SKELETON_ANIMATION_SPEED: 3,
SEARCH_OPTIONS_COMPARISON: 'search_options_comparison',
},
PRIORITY_MODE: {
GSD: 'gsd',
Expand Down
55 changes: 52 additions & 3 deletions src/hooks/useFastSearchFromOptions.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import deburr from 'lodash/deburr';
import {useCallback, useEffect, useState} from 'react';
import {useCallback, useEffect, useRef, useState} from 'react';
import Timing from '@libs/actions/Timing';
import FastSearch from '@libs/FastSearch';
import type {Options as OptionsListType, ReportAndPersonalDetailOptions} from '@libs/OptionsListUtils';
import {filterUserToInvite, isSearchStringMatch} from '@libs/OptionsListUtils';
import Performance from '@libs/Performance';
import type {OptionData} from '@libs/ReportUtils';
import StringUtils from '@libs/StringUtils';
import CONST from '@src/CONST';

type AllOrSelectiveOptions = ReportAndPersonalDetailOptions | OptionsListType;

Expand Down Expand Up @@ -36,8 +39,17 @@ function useFastSearchFromOptions(
{includeUserToInvite}: Options = {includeUserToInvite: false},
): (searchInput: string) => AllOrSelectiveOptions {
const [fastSearch, setFastSearch] = useState<ReturnType<typeof FastSearch.createFastSearch<OptionData>> | null>(null);
const prevOptionsRef = useRef<typeof options | null>(null);
const prevFastSearchRef = useRef<ReturnType<typeof FastSearch.createFastSearch<OptionData>> | null>(null);

useEffect(() => {
const prevOptions = prevOptionsRef.current;

if (prevOptions && shallowCompareOptions(prevOptions, options)) {
return;
}
prevOptionsRef.current = options;
prevFastSearchRef.current?.dispose();
const newFastSearch = FastSearch.createFastSearch([
{
data: options.personalDetails,
Expand Down Expand Up @@ -67,10 +79,11 @@ function useFastSearchFromOptions(
},
]);
setFastSearch(newFastSearch);

return () => newFastSearch.dispose();
prevFastSearchRef.current = newFastSearch;
}, [options]);

useEffect(() => () => prevFastSearchRef.current?.dispose(), []);

const findInSearchTree = useCallback(
(searchInput: string): AllOrSelectiveOptions => {
if (!fastSearch) {
Expand Down Expand Up @@ -122,4 +135,40 @@ function useFastSearchFromOptions(
return findInSearchTree;
}

/**
* Compares two ReportAndPersonalDetailOptions objects shallowly.
* @returns true if the options are shallowly equal, false otherwise.
*/
function shallowCompareOptions(prev: ReportAndPersonalDetailOptions, next: ReportAndPersonalDetailOptions): boolean {
if (!prev || !next) {
return false;
}

// Compare lengths first
if (prev.personalDetails.length !== next.personalDetails.length || prev.recentReports.length !== next.recentReports.length) {
return false;
}
Timing.start(CONST.TIMING.SEARCH_OPTIONS_COMPARISON);
Performance.markStart(CONST.TIMING.SEARCH_OPTIONS_COMPARISON);

for (let i = 0; i < prev.personalDetails.length; i++) {
if (prev.personalDetails.at(i)?.keyForList !== next.personalDetails.at(i)?.keyForList) {
Timing.end(CONST.TIMING.SEARCH_OPTIONS_COMPARISON);
Performance.markEnd(CONST.TIMING.SEARCH_OPTIONS_COMPARISON);
return false;
}
}

for (let i = 0; i < prev.recentReports.length; i++) {
if (prev.recentReports.at(i)?.keyForList !== next.recentReports.at(i)?.keyForList) {
Timing.end(CONST.TIMING.SEARCH_OPTIONS_COMPARISON);
Performance.markEnd(CONST.TIMING.SEARCH_OPTIONS_COMPARISON);
return false;
}
}
Timing.end(CONST.TIMING.SEARCH_OPTIONS_COMPARISON);
Performance.markEnd(CONST.TIMING.SEARCH_OPTIONS_COMPARISON);
return true;
}

export default useFastSearchFromOptions;