Skip to content

Commit

Permalink
Merge pull request Expensify#40764 from callstack-internal/perf/room-…
Browse files Browse the repository at this point in the history
…invite-list-filtering

perf: Room Invite options filtering
  • Loading branch information
roryabraham authored Jul 26, 2024
2 parents 6d2cf34 + 94fb636 commit 0559307
Showing 1 changed file with 33 additions and 16 deletions.
49 changes: 33 additions & 16 deletions src/pages/RoomInvitePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ function RoomInvitePage({
const {translate} = useLocalize();
const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState('');
const [selectedOptions, setSelectedOptions] = useState<ReportUtils.OptionData[]>([]);
const [invitePersonalDetails, setInvitePersonalDetails] = useState<ReportUtils.OptionData[]>([]);
const [userToInvite, setUserToInvite] = useState<ReportUtils.OptionData | null>(null);
const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false});
const {options, areOptionsInitialized} = useOptionsList();

Expand All @@ -75,9 +73,12 @@ function RoomInvitePage({
);
}, [report.participants]);

useEffect(() => {
const inviteOptions = OptionsListUtils.getMemberInviteOptions(options.personalDetails, betas ?? [], debouncedSearchTerm, excludedUsers);
const defaultOptions = useMemo(() => {
if (!areOptionsInitialized) {
return {recentReports: [], personalDetails: [], userToInvite: null, currentUserOption: null, categoryOptions: [], tagOptions: [], taxRatesOptions: []};
}

const inviteOptions = OptionsListUtils.getMemberInviteOptions(options.personalDetails, betas ?? [], '', excludedUsers);
// Update selectedOptions with the latest personalDetails information
const detailsMap: Record<string, OptionsListUtils.MemberForList> = {};
inviteOptions.personalDetails.forEach((detail) => {
Expand All @@ -91,15 +92,31 @@ function RoomInvitePage({
newSelectedOptions.push(option.login && option.login in detailsMap ? {...detailsMap[option.login], isSelected: true} : option);
});

setUserToInvite(inviteOptions.userToInvite);
setInvitePersonalDetails(inviteOptions.personalDetails);
setSelectedOptions(newSelectedOptions);
// eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps -- we don't want to recalculate when selectedOptions change
}, [betas, debouncedSearchTerm, excludedUsers, options.personalDetails]);
return {
userToInvite: inviteOptions.userToInvite,
personalDetails: inviteOptions.personalDetails,
selectedOptions: newSelectedOptions,
recentReports: [],
currentUserOption: null,
categoryOptions: [],
tagOptions: [],
taxRatesOptions: [],
};
}, [areOptionsInitialized, betas, excludedUsers, options.personalDetails, selectedOptions]);

const inviteOptions = useMemo(() => {
if (debouncedSearchTerm.trim() === '') {
return defaultOptions;
}
const filteredOptions = OptionsListUtils.filterOptions(defaultOptions, debouncedSearchTerm, {excludeLogins: excludedUsers});

return filteredOptions;
}, [debouncedSearchTerm, defaultOptions, excludedUsers]);

const sections = useMemo(() => {
const sectionsArr: Sections = [];

const {personalDetails, userToInvite} = inviteOptions;
if (!areOptionsInitialized) {
return [];
}
Expand All @@ -109,7 +126,7 @@ function RoomInvitePage({
if (debouncedSearchTerm !== '') {
filterSelectedOptions = selectedOptions.filter((option) => {
const accountID = option?.accountID;
const isOptionInPersonalDetails = invitePersonalDetails.some((personalDetail) => accountID && personalDetail?.accountID === accountID);
const isOptionInPersonalDetails = personalDetails ? personalDetails.some((personalDetail) => accountID && personalDetail?.accountID === accountID) : false;
const parsedPhoneNumber = PhoneNumber.parsePhoneNumber(LoginUtils.appendCountryCode(Str.removeSMSDomain(debouncedSearchTerm)));
const searchValue = parsedPhoneNumber.possible && parsedPhoneNumber.number ? parsedPhoneNumber.number.e164 : debouncedSearchTerm.toLowerCase();
const isPartOfSearchTerm = (option.text?.toLowerCase() ?? '').includes(searchValue) || (option.login?.toLowerCase() ?? '').includes(searchValue);
Expand All @@ -125,7 +142,7 @@ function RoomInvitePage({

// Filtering out selected users from the search results
const selectedLogins = selectedOptions.map(({login}) => login);
const personalDetailsWithoutSelected = invitePersonalDetails.filter(({login}) => !selectedLogins.includes(login));
const personalDetailsWithoutSelected = personalDetails ? personalDetails.filter(({login}) => !selectedLogins.includes(login)) : [];
const personalDetailsFormatted = personalDetailsWithoutSelected.map((personalDetail) => OptionsListUtils.formatMemberForList(personalDetail));
const hasUnselectedUserToInvite = userToInvite && !selectedLogins.includes(userToInvite.login);

Expand All @@ -142,7 +159,7 @@ function RoomInvitePage({
}

return sectionsArr;
}, [areOptionsInitialized, selectedOptions, debouncedSearchTerm, invitePersonalDetails, userToInvite, translate]);
}, [inviteOptions, areOptionsInitialized, selectedOptions, debouncedSearchTerm, translate]);

const toggleOption = useCallback(
(option: OptionsListUtils.MemberForList) => {
Expand Down Expand Up @@ -205,11 +222,11 @@ function RoomInvitePage({
const headerMessage = useMemo(() => {
const searchValue = debouncedSearchTerm.trim().toLowerCase();
const expensifyEmails = CONST.EXPENSIFY_EMAILS as string[];
if (!userToInvite && expensifyEmails.includes(searchValue)) {
if (!inviteOptions.userToInvite && expensifyEmails.includes(searchValue)) {
return translate('messages.errorMessageInvalidEmail');
}
if (
!userToInvite &&
!inviteOptions.userToInvite &&
excludedUsers.includes(
PhoneNumber.parsePhoneNumber(LoginUtils.appendCountryCode(searchValue)).possible
? PhoneNumber.addSMSDomainIfPhoneNumber(LoginUtils.appendCountryCode(searchValue))
Expand All @@ -218,8 +235,8 @@ function RoomInvitePage({
) {
return translate('messages.userIsAlreadyMember', {login: searchValue, name: reportName});
}
return OptionsListUtils.getHeaderMessage(invitePersonalDetails.length !== 0, !!userToInvite, searchValue);
}, [debouncedSearchTerm, userToInvite, excludedUsers, invitePersonalDetails, translate, reportName]);
return OptionsListUtils.getHeaderMessage((inviteOptions.personalDetails ?? []).length !== 0, !!inviteOptions.userToInvite, debouncedSearchTerm);
}, [debouncedSearchTerm, inviteOptions.userToInvite, inviteOptions.personalDetails, excludedUsers, translate, reportName]);

useEffect(() => {
ReportActions.searchInServer(debouncedSearchTerm);
Expand Down

0 comments on commit 0559307

Please sign in to comment.