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: Room Invite options filtering #40764

Merged
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
Loading