Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: Cache search options #38207

Merged
merged 57 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
840ac30
add function to create all reports and personal details options
TMisiukiewicz Mar 11, 2024
68e364c
use context to initialize all options
TMisiukiewicz Mar 11, 2024
d32dd3a
update getOptions, use options generation in search
TMisiukiewicz Mar 11, 2024
addd702
Merge branch 'main' into perf/cache-options
TMisiukiewicz Mar 12, 2024
50c823c
update usage in search page
TMisiukiewicz Mar 12, 2024
2c7d231
update options list utils
TMisiukiewicz Mar 12, 2024
b1bd11f
create reusable initializer for search pages
TMisiukiewicz Mar 12, 2024
499eb84
add options to new chat page
TMisiukiewicz Mar 12, 2024
122a6fb
update other occurencies of getoptions
TMisiukiewicz Mar 12, 2024
4c0cb3e
update initializing in search page
TMisiukiewicz Mar 13, 2024
0a7925e
update types for options
TMisiukiewicz Mar 13, 2024
2eb21a1
Merge branch 'main' into perf/cache-options
TMisiukiewicz Mar 13, 2024
47795b9
update loading in search page
TMisiukiewicz Mar 13, 2024
ffaee2a
update new chat page skeleton displaying
TMisiukiewicz Mar 13, 2024
47fc679
update caching in all selection lists
TMisiukiewicz Mar 13, 2024
623810f
update options in the background
TMisiukiewicz Mar 13, 2024
ef90c70
Merge remote-tracking branch 'upstream/main' into perf/cache-options
TMisiukiewicz Mar 14, 2024
d4621e9
update changed personal details
TMisiukiewicz Mar 14, 2024
653c9cb
fix loader on new chat page
TMisiukiewicz Mar 14, 2024
d75cc3f
filter personal details with login
TMisiukiewicz Mar 14, 2024
7ad2872
generate alternate text on the fly if needed
TMisiukiewicz Mar 14, 2024
67a0ae2
freeze the option list when search is open
TMisiukiewicz Mar 14, 2024
47c9e6b
remove unnecessary code
TMisiukiewicz Mar 15, 2024
0377ba6
remove console logs
TMisiukiewicz Mar 15, 2024
f44f1f0
Merge branch 'main' into perf/cache-options
TMisiukiewicz Mar 15, 2024
c6e9541
fix for generating alternate text
TMisiukiewicz Mar 15, 2024
e7264b5
fix jest tests
TMisiukiewicz Mar 15, 2024
aa0c81b
Merge remote-tracking branch 'upstream/main' into perf/cache-options
TMisiukiewicz Mar 18, 2024
69cd8ce
update reassure tests
TMisiukiewicz Mar 18, 2024
dcb9c38
fix prettier
TMisiukiewicz Mar 18, 2024
a694d98
Merge branch 'main' into perf/cache-options
TMisiukiewicz Mar 19, 2024
6876ae7
update reassure option list utils tests
TMisiukiewicz Mar 19, 2024
e9fae4e
remove redundant function calls
TMisiukiewicz Mar 20, 2024
02d531f
Merge branch 'main' into perf/cache-options
TMisiukiewicz Mar 20, 2024
46a4fcc
speed up setting options
TMisiukiewicz Mar 20, 2024
820c69a
Merge branch 'main' into perf/cache-options
TMisiukiewicz Mar 20, 2024
b28bd13
update money request participants selector
TMisiukiewicz Mar 20, 2024
5692a8d
lint code
TMisiukiewicz Mar 20, 2024
ca2c10a
add comments for option list context
TMisiukiewicz Mar 20, 2024
ec3547e
add test for cached options in search page
TMisiukiewicz Mar 20, 2024
eef4d62
update displaying lists
TMisiukiewicz Mar 21, 2024
e13492e
Merge branch 'main' into perf/cache-options
TMisiukiewicz Mar 21, 2024
c28b0be
Merge remote-tracking branch 'upstream/main' into perf/cache-options
TMisiukiewicz Mar 25, 2024
8e1cc45
code review updates
TMisiukiewicz Mar 25, 2024
3467a73
fix displaying personal details in current user option
TMisiukiewicz Mar 25, 2024
cdd26e8
update caching behavior in lists
TMisiukiewicz Mar 25, 2024
d5b8e36
Merge remote-tracking branch 'upstream/main' into perf/cache-options
TMisiukiewicz Mar 26, 2024
45efae2
Merge branch 'main' into perf/cache-options
TMisiukiewicz Mar 27, 2024
40dfb81
update tagpicker types
TMisiukiewicz Mar 27, 2024
f971d6a
Merge remote-tracking branch 'upstream/main' into perf/cache-options
TMisiukiewicz Mar 27, 2024
c577094
fix failing reassure tests
TMisiukiewicz Mar 27, 2024
5507fc8
Merge branch 'main' into perf/cache-options
TMisiukiewicz Mar 29, 2024
304544f
lint code
TMisiukiewicz Mar 29, 2024
4865582
fix typecheck
TMisiukiewicz Mar 29, 2024
d98ee6c
Merge remote-tracking branch 'upstream/main' into perf/cache-options
TMisiukiewicz Apr 2, 2024
07d1b74
update function naming
TMisiukiewicz Apr 3, 2024
50ed5e4
Merge remote-tracking branch 'upstream/main' into perf/cache-options
TMisiukiewicz Apr 3, 2024
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
2 changes: 2 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import HTMLEngineProvider from './components/HTMLEngineProvider';
import InitialURLContextProvider from './components/InitialURLContextProvider';
import {LocaleContextProvider} from './components/LocaleContextProvider';
import OnyxProvider from './components/OnyxProvider';
import OptionsListContextProvider from './components/OptionListContextProvider';
import PopoverContextProvider from './components/PopoverProvider';
import SafeArea from './components/SafeArea';
import ScrollOffsetContextProvider from './components/ScrollOffsetContextProvider';
Expand Down Expand Up @@ -82,6 +83,7 @@ function App({url}: AppProps) {
FullScreenContextProvider,
VolumeContextProvider,
VideoPopoverMenuContextProvider,
OptionsListContextProvider,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Placing this context provider here caused #39710 – we needed to move it inside AuthScreens so that it would be destroyed each time the user logs out.

]}
>
<CustomStatusBarAndBackground />
Expand Down
4 changes: 2 additions & 2 deletions src/components/CategoryPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ function CategoryPicker({selectedCategory, policyCategories, policyRecentlyUsedC
const [sections, headerMessage, shouldShowTextInput] = useMemo(() => {
const validPolicyRecentlyUsedCategories = policyRecentlyUsedCategories?.filter((p) => !isEmptyObject(p));
const {categoryOptions} = OptionsListUtils.getFilteredOptions(
{},
{},
[],
[],
[],
debouncedSearchValue,
selectedOptions,
Expand Down
142 changes: 142 additions & 0 deletions src/components/OptionListContextProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import React, {createContext, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';
import {withOnyx} from 'react-native-onyx';
import type {OnyxCollection} from 'react-native-onyx';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import type {OptionList} from '@libs/OptionsListUtils';
import * as ReportUtils from '@libs/ReportUtils';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Report} from '@src/types/onyx';
import {usePersonalDetails} from './OnyxProvider';

type OptionsListContextProps = {
/** List of options for reports and personal details */
options: OptionList;
/** Function to initialize the options */
initializeOptions: () => void;
/** Flag to check if the options are initialized */
areOptionsInitialized: boolean;
};

type OptionsListProviderOnyxProps = {
/** Collection of reports */
reports: OnyxCollection<Report>;
};

type OptionsListProviderProps = OptionsListProviderOnyxProps & {
/** Actual content wrapped by this component */
children: React.ReactNode;
};

const OptionsListContext = createContext<OptionsListContextProps>({
options: {
reports: [],
personalDetails: [],
},
initializeOptions: () => {},
areOptionsInitialized: false,
});

function OptionsListContextProvider({reports, children}: OptionsListProviderProps) {
const areOptionsInitialized = useRef(false);
const [options, setOptions] = useState<OptionList>({
reports: [],
personalDetails: [],
});
const personalDetails = usePersonalDetails();

useEffect(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coming from #40493, we missed updating the cache when a report is deleted.

// there is no need to update the options if the options are not initialized
if (!areOptionsInitialized.current) {
return;
}

const lastUpdatedReport = ReportUtils.getLastUpdatedReport();

if (!lastUpdatedReport) {
return;
}

const newOption = OptionsListUtils.createOptionFromReport(lastUpdatedReport, personalDetails);
const replaceIndex = options.reports.findIndex((option) => option.reportID === lastUpdatedReport.reportID);

if (replaceIndex === -1) {
return;
}

setOptions((prevOptions) => {
const newOptions = {...prevOptions};
newOptions.reports[replaceIndex] = newOption;
return newOptions;
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [reports]);

useEffect(() => {
// there is no need to update the options if the options are not initialized
if (!areOptionsInitialized.current) {
return;
}

// since personal details are not a collection, we need to recreate the whole list from scratch
const newPersonalDetailsOptions = OptionsListUtils.createOptionList(personalDetails).personalDetails;

setOptions((prevOptions) => {
const newOptions = {...prevOptions};
newOptions.personalDetails = newPersonalDetailsOptions;
return newOptions;
});
}, [personalDetails]);

const loadOptions = useCallback(() => {
const optionLists = OptionsListUtils.createOptionList(personalDetails, reports);
setOptions({
reports: optionLists.reports,
personalDetails: optionLists.personalDetails,
});
}, [personalDetails, reports]);

const initializeOptions = useCallback(() => {
if (areOptionsInitialized.current) {
return;
}

loadOptions();
areOptionsInitialized.current = true;
}, [loadOptions]);

return (
<OptionsListContext.Provider value={useMemo(() => ({options, initializeOptions, areOptionsInitialized: areOptionsInitialized.current}), [options, initializeOptions])}>
{children}
</OptionsListContext.Provider>
);
}

const useOptionsListContext = () => useContext(OptionsListContext);

// Hook to use the OptionsListContext with an initializer to load the options
const useOptionsList = (options?: {shouldInitialize: boolean}) => {
const {shouldInitialize = true} = options ?? {};
const {initializeOptions, options: optionsList, areOptionsInitialized} = useOptionsListContext();

useEffect(() => {
if (!shouldInitialize || areOptionsInitialized) {
return;
}

initializeOptions();
}, [shouldInitialize, initializeOptions, areOptionsInitialized]);

return {
initializeOptions,
options: optionsList,
areOptionsInitialized,
};
};

export default withOnyx<OptionsListProviderProps, OptionsListProviderOnyxProps>({
reports: {
key: ONYXKEYS.COLLECTION.REPORT,
},
})(OptionsListContextProvider);

export {useOptionsListContext, useOptionsList, OptionsListContext};
2 changes: 1 addition & 1 deletion src/components/TagPicker/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ function TagPicker({selectedTag, tagListName, policyTags, tagListIndex, policyRe
}, [selectedOptions, policyTagList, shouldShowDisabledAndSelectedOption]);

const sections = useMemo(
() => OptionsListUtils.getFilteredOptions({}, {}, [], searchValue, selectedOptions, [], false, false, false, {}, [], true, enabledTags, policyRecentlyUsedTagsList, false).tagOptions,
() => OptionsListUtils.getFilteredOptions([], [], [], searchValue, selectedOptions, [], false, false, false, {}, [], true, enabledTags, policyRecentlyUsedTagsList, false).tagOptions,
[searchValue, enabledTags, selectedOptions, policyRecentlyUsedTagsList],
);

Expand Down
Loading
Loading