Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
6d01fce
refactor MoneyRequestAttendeeSelector to use useSearchSelector hook
NJ-2020 Oct 4, 2025
2abe97a
Merge branch 'Expensify:main' into refactor/71064
NJ-2020 Oct 4, 2025
e959d64
remove unnecessary console log statements
NJ-2020 Oct 4, 2025
c161e2b
fix some issues, remove unnecessary code
NJ-2020 Oct 5, 2025
2ba6e93
clean up
NJ-2020 Oct 6, 2025
cd9d50f
Merge remote-tracking branch 'origin' into refactor/71064
NJ-2020 Oct 14, 2025
f0fcc5f
fix: update SEARCH_SELECTOR list
NJ-2020 Oct 14, 2025
6fb17a4
fix eslint error
NJ-2020 Oct 14, 2025
8e3254e
Merge branch 'Expensify:main' into refactor/71064
NJ-2020 Oct 15, 2025
796b291
fix some issues & improvements
NJ-2020 Oct 15, 2025
e401910
fix max recent contact lists & eslint error
NJ-2020 Oct 15, 2025
e4cc1bd
fix recent attendee lists, some issues
NJ-2020 Oct 15, 2025
2383981
fix eslint check
NJ-2020 Oct 15, 2025
d102352
Merge remote-tracking branch 'origin' into refactor/71064
NJ-2020 Oct 18, 2025
9e69257
fix recent contacts is not filtered when typing
NJ-2020 Oct 18, 2025
afcdaf5
fix eslint error
NJ-2020 Oct 18, 2025
5fd21dc
improvements
NJ-2020 Oct 18, 2025
16223b3
Merge remote-tracking branch 'origin' into refactor/71064
NJ-2020 Oct 24, 2025
565e437
fix attendee display name
NJ-2020 Oct 24, 2025
2eaa41d
fix avatar url
NJ-2020 Oct 24, 2025
4d8910d
Merge remote-tracking branch 'origin' into refactor/71064
NJ-2020 Oct 24, 2025
bb44d36
fix conflicts
NJ-2020 Oct 31, 2025
da59a5a
Merge branch 'main' into refactor/71064
NJ-2020 Nov 1, 2025
58935fa
Merge branch 'Expensify:main' into refactor/71064
NJ-2020 Nov 2, 2025
42347a8
Merge branch 'Expensify:main' into refactor/71064
NJ-2020 Nov 5, 2025
1d7c9c6
fix: duplicate identifier
NJ-2020 Nov 5, 2025
cd2afef
fix typecheck
NJ-2020 Nov 5, 2025
aa55f08
Merge remote-tracking branch 'origin' into refactor/71064
NJ-2020 Nov 8, 2025
3d2c548
fix error
NJ-2020 Nov 8, 2025
b5262b8
fix recentAttendees list length
NJ-2020 Nov 8, 2025
0746e12
Merge branch 'Expensify:main' into refactor/71064
NJ-2020 Nov 13, 2025
09c5039
Merge branch 'Expensify:main' into refactor/71064
NJ-2020 Nov 14, 2025
04bcd76
Merge branch 'Expensify:main' into refactor/71064
NJ-2020 Nov 18, 2025
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/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6860,6 +6860,7 @@ const CONST = {
SEARCH_CONTEXT_MEMBER_INVITE: 'memberInvite',
SEARCH_CONTEXT_SHARE_LOG: 'shareLog',
SEARCH_CONTEXT_SHARE_DESTINATION: 'shareDestination',
SEARCH_CONTEXT_ATTENDEES: 'attendees',
},
EXPENSE: {
TYPE: {
Expand Down
21 changes: 20 additions & 1 deletion src/hooks/useSearchSelector.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

type SearchSelectorContext = (typeof CONST.SEARCH_SELECTOR)[keyof Pick<
typeof CONST.SEARCH_SELECTOR,
'SEARCH_CONTEXT_GENERAL' | 'SEARCH_CONTEXT_SEARCH' | 'SEARCH_CONTEXT_MEMBER_INVITE' | 'SEARCH_CONTEXT_SHARE_LOG' | 'SEARCH_CONTEXT_SHARE_DESTINATION'
'SEARCH_CONTEXT_GENERAL' | 'SEARCH_CONTEXT_SEARCH' | 'SEARCH_CONTEXT_MEMBER_INVITE' | 'SEARCH_CONTEXT_SHARE_LOG' | 'SEARCH_CONTEXT_SHARE_DESTINATION' | 'SEARCH_CONTEXT_ATTENDEES'
>];
type SearchSelectorSelectionMode = (typeof CONST.SEARCH_SELECTOR)[keyof Pick<typeof CONST.SEARCH_SELECTOR, 'SELECTION_MODE_SINGLE' | 'SELECTION_MODE_MULTI'>];

Expand All @@ -38,6 +38,9 @@
/** Whether to include recent reports (for getMemberInviteOptions) */
includeRecentReports?: boolean;

/** Whether to include current user */
includeCurrentUser?: boolean;

/** Enable phone contacts integration */
enablePhoneContacts?: boolean;

Expand Down Expand Up @@ -136,6 +139,7 @@
initialSelected,
shouldInitialize = true,
contactOptions,
includeCurrentUser = false,
}: UseSearchSelectorConfig): UseSearchSelectorReturn {
const {options: defaultOptions, areOptionsInitialized} = useOptionsList({
shouldInitialize,
Expand Down Expand Up @@ -246,10 +250,25 @@
maxElements: maxResults,
includeUserToInvite,
});
case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_ATTENDEES:
return getValidOptions(optionsWithContacts, draftComments, nvpDismissedProductTraining, {
...getValidOptionsConfig,
betas: betas ?? [],
includeP2P: true,
includeSelectedOptions: false,
excludeLogins,
loginsToExclude: excludeLogins,
includeRecentReports,
maxElements: maxResults,
maxRecentReportElements: maxRecentReportsToShow,
searchString: computedSearchTerm,
includeUserToInvite,
includeCurrentUser,
});
default:
return getEmptyOptions();
}
}, [

Check warning on line 271 in src/hooks/useSearchSelector.base.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

React Hook useMemo has a missing dependency: 'includeCurrentUser'. Either include it or remove the dependency array

Check warning on line 271 in src/hooks/useSearchSelector.base.ts

View workflow job for this annotation

GitHub Actions / ESLint check

React Hook useMemo has a missing dependency: 'includeCurrentUser'. Either include it or remove the dependency array
areOptionsInitialized,
searchContext,
optionsWithContacts,
Expand Down
70 changes: 10 additions & 60 deletions src/libs/OptionsListUtils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import * as Sentry from '@sentry/react-native';
import {Str} from 'expensify-common';
import deburr from 'lodash/deburr';
import keyBy from 'lodash/keyBy';
import lodashOrderBy from 'lodash/orderBy';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
Expand Down Expand Up @@ -140,7 +139,6 @@
import {generateAccountID} from '@libs/UserUtils';
import Timing from '@userActions/Timing';
import CONST from '@src/CONST';
import type {IOUAction} from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {
Beta,
Expand Down Expand Up @@ -190,7 +188,7 @@
*/
let currentUserLogin: string | undefined;
let currentUserAccountID: number | undefined;
Onyx.connect({

Check warning on line 191 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.SESSION,
callback: (value) => {
currentUserLogin = value?.email;
Expand All @@ -199,19 +197,19 @@
});

let loginList: OnyxEntry<Login>;
Onyx.connect({

Check warning on line 200 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.LOGIN_LIST,
callback: (value) => (loginList = isEmptyObject(value) ? {} : value),
});

let allPersonalDetails: OnyxEntry<PersonalDetailsList>;
Onyx.connect({

Check warning on line 206 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
callback: (value) => (allPersonalDetails = isEmptyObject(value) ? {} : value),
});

const policies: OnyxCollection<Policy> = {};
Onyx.connect({

Check warning on line 212 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.POLICY,
callback: (policy, key) => {
if (!policy || !key || !policy.name) {
Expand All @@ -223,14 +221,14 @@
});

let allPolicies: OnyxCollection<Policy> = {};
Onyx.connect({

Check warning on line 224 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.POLICY,
waitForCollectionCallback: true,
callback: (val) => (allPolicies = val),
});

let allReports: OnyxCollection<Report>;
Onyx.connect({

Check warning on line 231 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -239,7 +237,7 @@
});

let allReportNameValuePairs: OnyxCollection<ReportNameValuePairs>;
Onyx.connect({

Check warning on line 240 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -251,7 +249,7 @@
const allSortedReportActions: Record<string, ReportAction[]> = {};
let allReportActions: OnyxCollection<ReportActions>;
const lastVisibleReportActions: ReportActions = {};
Onyx.connect({

Check warning on line 252 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
waitForCollectionCallback: true,
callback: (actions) => {
Expand Down Expand Up @@ -313,7 +311,7 @@
});

let activePolicyID: OnyxEntry<string>;
Onyx.connect({

Check warning on line 314 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.NVP_ACTIVE_POLICY_ID,
callback: (value) => (activePolicyID = value),
});
Expand Down Expand Up @@ -1985,9 +1983,9 @@
let workspaceChats: Array<SearchOption<Report>> = [];
let selfDMChat: SearchOptionData | undefined;

const searchTerms = processSearchString(searchString);
if (includeRecentReports) {
// if maxElements is passed, filter the recent reports by searchString and return only most recent reports (@see recentReportsComparator)
const searchTerms = processSearchString(searchString);

const isWorkspaceChat = (report: SearchOption<Report>) => shouldSeparateWorkspaceChat && report.isPolicyExpenseChat && !report.private_isArchived;
const isSelfDMChat = (report: SearchOption<Report>) => shouldSeparateSelfDMChat && report.isSelfDM && !report.private_isArchived;
Expand Down Expand Up @@ -2068,7 +2066,11 @@

return false;
});
recentReportOptions = recentAttendees as Array<SearchOption<Report>>;
recentReportOptions = filterReports(recentAttendees as SearchOptionData[], searchTerms) as Array<SearchOption<Report>>;

if (maxRecentReportElements) {
recentReportOptions = recentReportOptions.slice(0, maxRecentReportElements);
}
}

// Get valid personal details and check if we can find the current user:
Expand All @@ -2086,7 +2088,6 @@
};
}

const searchTerms = processSearchString(searchString);
const filteringFunction = (personalDetail: OptionData) => {
if (
!personalDetail?.login ||
Expand Down Expand Up @@ -2245,40 +2246,7 @@
};
}

type GetAttendeeOptionsParams = {
reports: Array<SearchOption<Report>>;
personalDetails: Array<SearchOption<PersonalDetails>>;
betas: OnyxEntry<Beta[]>;
attendees: Attendee[];
recentAttendees: Attendee[];
draftComments: OnyxCollection<string>;
nvpDismissedProductTraining: OnyxEntry<DismissedProductTraining>;
includeOwnedWorkspaceChats: boolean;
includeP2P: boolean;
includeInvoiceRooms: boolean;
action: IOUAction | undefined;
countryCode: number;
};

function getAttendeeOptions({
reports,
personalDetails,
betas,
attendees,
recentAttendees,
draftComments,
nvpDismissedProductTraining,
includeOwnedWorkspaceChats = false,
includeP2P = true,
includeInvoiceRooms = false,
action = undefined,
countryCode = CONST.DEFAULT_COUNTRY_CODE,
}: GetAttendeeOptionsParams) {
const personalDetailList = keyBy(
personalDetails.map(({item}) => item),
'accountID',
);

function getFilteredRecentAttendees(personalDetails: OnyxEntry<PersonalDetailsList>, attendees: Attendee[], recentAttendees: Attendee[]): Option[] {
const recentAttendeeHasCurrentUser = recentAttendees.find((attendee) => attendee.email === currentUserLogin || attendee.login === currentUserLogin);
if (!recentAttendeeHasCurrentUser && currentUserLogin) {
const details = getPersonalDetailByEmail(currentUserLogin);
Expand All @@ -2300,27 +2268,9 @@
login: attendee.email ?? attendee.displayName,
...getPersonalDetailByEmail(attendee.email),
}))
.map((attendee) => getParticipantsOption(attendee, personalDetailList as never));
.map((attendee) => getParticipantsOption(attendee, personalDetails));

return getValidOptions(
{reports, personalDetails},
draftComments,
nvpDismissedProductTraining,
{
betas,
selectedOptions: attendees.map((attendee) => ({...attendee, login: attendee.email})),
excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT,
includeOwnedWorkspaceChats,
includeRecentReports: false,
includeP2P,
includeSelectedOptions: false,
includeSelfDM: false,
includeInvoiceRooms,
action,
recentAttendees: filteredRecentAttendees,
},
countryCode,
);
return filteredRecentAttendees;
}

/**
Expand Down Expand Up @@ -2851,7 +2801,7 @@
formatMemberForList,
formatSectionsFromSearchTerm,
getAlternateText,
getAttendeeOptions,
getFilteredRecentAttendees,
getCurrentUserSearchTerms,
getEmptyOptions,
getFirstKeyForList,
Expand Down
Loading
Loading