-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Fix/move preselected items to top #80322
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
base: main
Are you sure you want to change the base?
Changes from 6 commits
722464c
79913be
82578b6
3c359bc
6a442af
05b5547
8f88a11
9d36163
673dce1
c230c97
4cb6618
f85c1cc
5d4f1e6
0db9c28
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,8 +10,8 @@ import useOnyx from '@hooks/useOnyx'; | |
| import useScreenWrapperTransitionStatus from '@hooks/useScreenWrapperTransitionStatus'; | ||
| import {canUseTouchScreen} from '@libs/DeviceCapabilities'; | ||
| import memoize from '@libs/memoize'; | ||
| import {filterAndOrderOptions, filterSelectedOptions, formatSectionsFromSearchTerm, getValidOptions} from '@libs/OptionsListUtils'; | ||
| import type {Option, Section} from '@libs/OptionsListUtils'; | ||
| import {filterAndOrderOptions, filterSelectedOptions, formatSectionsFromSearchTerm, getParticipantsOption, getPolicyExpenseReportOption, getValidOptions} from '@libs/OptionsListUtils'; | ||
| import type {Option} from '@libs/OptionsListUtils'; | ||
| import type {OptionData} from '@libs/ReportUtils'; | ||
| import {getDisplayNameForParticipant} from '@libs/ReportUtils'; | ||
| import Navigation from '@navigation/Navigation'; | ||
|
|
@@ -41,7 +41,7 @@ type SearchFiltersParticipantsSelectorProps = { | |
| }; | ||
|
|
||
| function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}: SearchFiltersParticipantsSelectorProps) { | ||
| const {translate, formatPhoneNumber} = useLocalize(); | ||
| const {translate, formatPhoneNumber, localeCompare} = useLocalize(); | ||
| const personalDetails = usePersonalDetails(); | ||
| const {didScreenTransitionEnd} = useScreenWrapperTransitionStatus(); | ||
| const {options, areOptionsInitialized} = useOptionsList({ | ||
|
|
@@ -79,13 +79,28 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}: | |
| ); | ||
| }, [areOptionsInitialized, options.reports, options.personalDetails, allPolicies, draftComments, nvpDismissedProductTraining, loginList, countryCode]); | ||
|
|
||
| const initialSelectedOptions = useMemo(() => { | ||
| if (!initialAccountIDs || initialAccountIDs.length === 0 || !personalDetails) { | ||
| return []; | ||
| } | ||
|
|
||
| const preSelectedOptions = initialAccountIDs.reduce<OptionData[]>((acc, accountID) => { | ||
| const participant = personalDetails[accountID]; | ||
| if (participant) { | ||
| acc.push(getSelectedOptionData(participant)); | ||
| } | ||
| return acc; | ||
| }, []); | ||
|
|
||
| return preSelectedOptions; | ||
| }, [initialAccountIDs, personalDetails]); | ||
|
|
||
| const unselectedOptions = useMemo(() => { | ||
| return filterSelectedOptions(defaultOptions, new Set(selectedOptions.map((option) => option.accountID))); | ||
| }, [defaultOptions, selectedOptions]); | ||
|
|
||
| const chatOptions = useMemo(() => { | ||
| const filteredOptions = filterAndOrderOptions(unselectedOptions, cleanSearchTerm, countryCode, loginList, { | ||
| selectedOptions, | ||
| excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, | ||
| maxRecentReportsToShow: CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW, | ||
| canInviteUser: false, | ||
|
|
@@ -99,10 +114,10 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}: | |
| } | ||
|
|
||
| return filteredOptions; | ||
| }, [unselectedOptions, cleanSearchTerm, countryCode, loginList, selectedOptions]); | ||
| }, [unselectedOptions, cleanSearchTerm, countryCode, loginList]); | ||
|
|
||
| const {sections, headerMessage} = useMemo(() => { | ||
| const newSections: Section[] = []; | ||
| const sectionData: OptionData[] = []; | ||
| if (!areOptionsInitialized) { | ||
| return {sections: [], headerMessage: undefined}; | ||
| } | ||
|
|
@@ -127,44 +142,62 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}: | |
| } | ||
|
|
||
| // If the current user is not selected, add them to the top of the list | ||
| if (!selectedCurrentUser && chatOptions.currentUserOption) { | ||
| if (!selectedCurrentUser && chatOptions.currentUserOption && !initialSelectedOptions.some((option) => option.accountID === chatOptions.currentUserOption?.accountID)) { | ||
| const formattedName = getDisplayNameForParticipant({ | ||
| accountID: chatOptions.currentUserOption.accountID, | ||
| shouldAddCurrentUserPostfix: true, | ||
| personalDetailsData: personalDetails, | ||
| formatPhoneNumber, | ||
| }); | ||
| chatOptions.currentUserOption.text = formattedName; | ||
|
|
||
| newSections.push({ | ||
| title: '', | ||
| data: [chatOptions.currentUserOption], | ||
| shouldShow: true, | ||
| }); | ||
| sectionData.push(chatOptions.currentUserOption); | ||
| } | ||
|
|
||
| newSections.push(formattedResults.section); | ||
| const selectedIDsSet = new Set(initialSelectedOptions.map((option) => option.accountID)); | ||
| const unselectedFormattedSectionData = formattedResults.section.data.filter((option) => !selectedIDsSet.has(option.accountID)); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❌ PERF-13 (docs)Inside the Suggested fix: Create a const initialSelectedAccountIDs = new Set(initialSelectedOptions.map((option) => option.accountID));
const unselectedRecentReports = chatOptions.recentReports.filter((report) => !initialSelectedAccountIDs.has(report.accountID));This pattern should also be applied to line 162 with Please rate this suggestion with 👍 or 👎 to help us improve! Reactions are used to monitor reviewer efficiency. |
||
| if (unselectedFormattedSectionData.length) { | ||
| sectionData.push(...(unselectedFormattedSectionData as OptionData[])); | ||
| } | ||
|
|
||
| newSections.push({ | ||
| title: '', | ||
| data: chatOptions.recentReports, | ||
| shouldShow: chatOptions.recentReports.length > 0, | ||
| }); | ||
| const unselectedRecentReports = chatOptions.recentReports.filter((report) => !initialSelectedOptions.some((selectedOption) => selectedOption.accountID === report.accountID)); | ||
| if (unselectedRecentReports) { | ||
| sectionData.push(...unselectedRecentReports); | ||
| } | ||
|
|
||
| newSections.push({ | ||
| title: '', | ||
| data: chatOptions.personalDetails, | ||
| shouldShow: chatOptions.personalDetails.length > 0, | ||
| }); | ||
| const unselectedPersonalDetails = chatOptions.personalDetails.filter((detail) => !initialSelectedOptions.some((selectedOption) => selectedOption.accountID === detail.accountID)); | ||
| if (unselectedPersonalDetails) { | ||
| sectionData.push(...unselectedPersonalDetails); | ||
| } | ||
|
|
||
| const noResultsFound = chatOptions.personalDetails.length === 0 && chatOptions.recentReports.length === 0 && !chatOptions.currentUserOption; | ||
| const message = noResultsFound ? translate('common.noResultsFound') : undefined; | ||
| let sortedSectionData = sectionData.sort((a, b) => localeCompare(a?.login?.toLowerCase() ?? '', b?.login?.toLowerCase() ?? '')); | ||
|
|
||
| if (initialSelectedOptions.length && cleanSearchTerm === '') { | ||
| sortedSectionData = [ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❌ PERF-13 (docs)Inside the Suggested fix: Create a const selectedAccountIDsSet = new Set(selectedOptions.map((option) => option.accountID));
const mappedParticipants = initialSelectedOptions.map((participant) => {
const participantData = {
...participant,
selected: selectedAccountIDsSet.has(participant.accountID),
};
// ... rest of logic
});Please rate this suggestion with 👍 or 👎 to help us improve! Reactions are used to monitor reviewer efficiency. |
||
| ...(initialSelectedOptions.map((participant) => { | ||
| const participantData = { | ||
| ...participant, | ||
| selected: selectedOptions.some((selectedOption) => selectedOption.accountID === participant.accountID), | ||
| }; | ||
| const isReportPolicyExpenseChat = participant.isPolicyExpenseChat ?? false; | ||
| return isReportPolicyExpenseChat ? getPolicyExpenseReportOption(participantData, reportAttributesDerived) : getParticipantsOption(participantData, personalDetails); | ||
| }) as OptionData[]), | ||
| ...sortedSectionData, | ||
| ]; | ||
| } | ||
|
|
||
| return { | ||
| sections: newSections, | ||
| sections: [ | ||
| { | ||
| title: '', | ||
| data: sortedSectionData, | ||
| shouldShow: sortedSectionData.length > 0, | ||
| }, | ||
| ], | ||
| headerMessage: message, | ||
| }; | ||
| }, [areOptionsInitialized, cleanSearchTerm, selectedOptions, chatOptions, personalDetails, reportAttributesDerived, translate, formatPhoneNumber]); | ||
| }, [areOptionsInitialized, cleanSearchTerm, selectedOptions, chatOptions, personalDetails, reportAttributesDerived, initialSelectedOptions, translate, formatPhoneNumber, localeCompare]); | ||
|
|
||
| const resetChanges = useCallback(() => { | ||
| setSelectedOptions([]); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❌ PERF-13 (docs)
The
.some()call inside the conditional on line 145 iterates throughinitialSelectedOptionsbut doesn't use any iterator-dependent values from the conditional context. Since this is inside a conditional (not an array method callback), this should be optimized.Suggested fix: Create a
Setof account IDs before this conditional:This
Setcan be reused for the filter operations on lines 157 and 162 as well.Please rate this suggestion with 👍 or 👎 to help us improve! Reactions are used to monitor reviewer efficiency.