Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -6776,6 +6776,7 @@ const CONST = {
SEARCH_CONTEXT_GENERAL: 'general',
SEARCH_CONTEXT_SEARCH: 'search',
SEARCH_CONTEXT_MEMBER_INVITE: 'memberInvite',
SEARCH_CONTEXT_SHARE_LOG: 'shareLog',
SEARCH_CONTEXT_SHARE_DESTINATION: 'shareDestination',
},
EXPENSE: {
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 @@ import useOnyx from './useOnyx';

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_DESTINATION'
'SEARCH_CONTEXT_GENERAL' | 'SEARCH_CONTEXT_SEARCH' | 'SEARCH_CONTEXT_MEMBER_INVITE' | 'SEARCH_CONTEXT_SHARE_LOG' | 'SEARCH_CONTEXT_SHARE_DESTINATION'
>];
type SearchSelectorSelectionMode = (typeof CONST.SEARCH_SELECTOR)[keyof Pick<typeof CONST.SEARCH_SELECTOR, 'SELECTION_MODE_SINGLE' | 'SELECTION_MODE_MULTI'>];

Expand Down Expand Up @@ -206,6 +206,25 @@ function useSearchSelectorBase({
includeUserToInvite,
excludeLogins,
});
case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_SHARE_LOG:
return getValidOptions(
optionsWithContacts,
draftComments,
{
betas,
includeMultipleParticipantReports: true,
includeP2P: true,
forcePolicyNamePreview: true,
includeOwnedWorkspaceChats: true,
includeSelfDM: true,
includeThreads: true,
includeReadOnly: false,
searchString: computedSearchTerm,
maxElements: maxResults,
includeUserToInvite,
},
countryCode,
);
case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_SHARE_DESTINATION:
return getValidOptions(optionsWithContacts, draftComments, {
betas,
Expand Down
30 changes: 0 additions & 30 deletions src/libs/OptionsListUtils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@
*/
let currentUserLogin: string | undefined;
let currentUserAccountID: number | undefined;
Onyx.connect({

Check warning on line 190 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 @@ -196,19 +196,19 @@
});

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

Check warning on line 199 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 205 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 211 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 @@ -220,14 +220,14 @@
});

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

Check warning on line 223 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 230 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 @@ -236,7 +236,7 @@
});

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

Check warning on line 239 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 @@ -248,7 +248,7 @@
const allSortedReportActions: Record<string, ReportAction[]> = {};
let allReportActions: OnyxCollection<ReportActions>;
const lastVisibleReportActions: ReportActions = {};
Onyx.connect({

Check warning on line 251 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 @@ -310,13 +310,13 @@
});

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

Check warning on line 313 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),
});

let nvpDismissedProductTraining: OnyxEntry<DismissedProductTraining>;
Onyx.connect({

Check warning on line 319 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_DISMISSED_PRODUCT_TRAINING,
callback: (value) => (nvpDismissedProductTraining = value),
});
Expand Down Expand Up @@ -2089,35 +2089,6 @@
return optionList;
}

function getShareLogOptions(
options: OptionList,
draftComments: OnyxCollection<string>,
betas: Beta[] = [],
searchString = '',
maxElements?: number,
includeUserToInvite = false,
countryCode: number = CONST.DEFAULT_COUNTRY_CODE,
): Options {
return getValidOptions(
options,
draftComments,
{
betas,
includeMultipleParticipantReports: true,
includeP2P: true,
forcePolicyNamePreview: true,
includeOwnedWorkspaceChats: true,
includeSelfDM: true,
includeThreads: true,
includeReadOnly: false,
searchString,
maxElements,
includeUserToInvite,
},
countryCode,
);
}

/**
* Build the IOUConfirmation options for showing the payee personalDetail
*/
Expand Down Expand Up @@ -2763,7 +2734,6 @@
getReportOption,
getSearchOptions,
getSearchValueForPhoneOrEmail,
getShareLogOptions,
getUserToInviteContactOption,
getUserToInviteOption,
getValidOptions,
Expand Down
105 changes: 42 additions & 63 deletions src/pages/settings/AboutPage/ShareLogList/BaseShareLogList.tsx
Original file line number Diff line number Diff line change
@@ -1,100 +1,79 @@
import React, {useEffect, useMemo} from 'react';
import type {SectionListData} from 'react-native';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import {useBetas} from '@components/OnyxListItemProvider';
import {useOptionsList} from '@components/OptionListContextProvider';
import ScreenWrapper from '@components/ScreenWrapper';
import SelectionList from '@components/SelectionListWithSections';
import type {Section} from '@components/SelectionListWithSections/types';
import UserListItem from '@components/SelectionListWithSections/UserListItem';
import useDebouncedState from '@hooks/useDebouncedState';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useOnyx from '@hooks/useOnyx';
import useSearchSelector from '@hooks/useSearchSelector';
import {searchInServer} from '@libs/actions/Report';
import {appendTimeToFileName} from '@libs/fileDownload/FileUtils';
import Navigation from '@libs/Navigation/Navigation';
import {filterAndOrderOptions, getHeaderMessage, getShareLogOptions} from '@libs/OptionsListUtils';
import {getHeaderMessage} from '@libs/OptionsListUtils';
import type {OptionData} from '@libs/ReportUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {Report} from '@src/types/onyx';
import type {BaseShareLogListProps} from './types';

type Sections = Array<SectionListData<OptionData, Section<OptionData>>>;

function BaseShareLogList({onAttachLogToReport}: BaseShareLogListProps) {
const [searchValue, debouncedSearchValue, setSearchValue] = useDebouncedState('');
const {isOffline} = useNetwork();
const {translate} = useLocalize();
const betas = useBetas();
const [countryCode = CONST.DEFAULT_COUNTRY_CODE] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false});
const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false, canBeMissing: true});
const {options, areOptionsInitialized} = useOptionsList();
const [draftComments] = useOnyx(ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT, {canBeMissing: true});
const [countryCode = CONST.DEFAULT_COUNTRY_CODE] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false});

const defaultOptions = useMemo(() => {
const {searchTerm, debouncedSearchTerm, setSearchTerm, availableOptions, areOptionsInitialized} = useSearchSelector({
selectionMode: CONST.SEARCH_SELECTOR.SELECTION_MODE_SINGLE,
searchContext: CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_SHARE_LOG,
includeUserToInvite: false,
});
const sections = useMemo(() => {
if (!areOptionsInitialized) {
return {
recentReports: [],
personalDetails: [],
userToInvite: null,
currentUserOption: null,
headerMessage: '',
};
return CONST.EMPTY_ARRAY;
}
const shareLogOptions = getShareLogOptions(options, draftComments, betas ?? []);

const header = getHeaderMessage((shareLogOptions.recentReports.length || 0) + (shareLogOptions.personalDetails.length || 0) !== 0, !!shareLogOptions.userToInvite, '', countryCode);

return {
...shareLogOptions,
headerMessage: header,
};
}, [areOptionsInitialized, options, draftComments, betas, countryCode]);

const searchOptions = useMemo(() => {
if (debouncedSearchValue.trim() === '') {
return defaultOptions;
}

const filteredOptions = filterAndOrderOptions(defaultOptions, debouncedSearchValue, countryCode, {
preferChatRoomsOverThreads: true,
sortByReportTypeInSearch: true,
});

const headerMessage = getHeaderMessage(
(filteredOptions.recentReports?.length || 0) + (filteredOptions.personalDetails?.length || 0) !== 0,
!!filteredOptions.userToInvite,
debouncedSearchValue.trim(),
countryCode,
false,
);

return {...filteredOptions, headerMessage};
}, [debouncedSearchValue, defaultOptions, countryCode]);

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

sectionsList.push({
title: translate('common.recents'),
data: searchOptions.recentReports,
shouldShow: searchOptions.recentReports?.length > 0,
data: availableOptions.recentReports,
shouldShow: availableOptions.recentReports.length > 0,
});

sectionsList.push({
title: translate('common.contacts'),
data: searchOptions.personalDetails,
shouldShow: searchOptions.personalDetails?.length > 0,
data: availableOptions.personalDetails,
shouldShow: availableOptions.personalDetails.length > 0,
});

if (searchOptions.userToInvite) {
if (availableOptions.userToInvite) {
sectionsList.push({
data: [searchOptions.userToInvite],
title: undefined,
data: [availableOptions.userToInvite],
shouldShow: true,
});
}

return sectionsList;
}, [searchOptions?.personalDetails, searchOptions?.recentReports, searchOptions?.userToInvite, translate]);
}, [areOptionsInitialized, translate, availableOptions.recentReports, availableOptions.personalDetails, availableOptions.userToInvite]);

const headerMessage = useMemo(() => {
if (!areOptionsInitialized) {
return '';
}

return getHeaderMessage(
(availableOptions.recentReports?.length || 0) + (availableOptions.personalDetails?.length || 0) !== 0,
!!availableOptions.userToInvite,
debouncedSearchTerm.trim(),
countryCode,
);
}, [areOptionsInitialized, availableOptions.personalDetails?.length, availableOptions.recentReports?.length, availableOptions.userToInvite, countryCode, debouncedSearchTerm]);
const attachLogToReport = (option: Report) => {
if (!option.reportID) {
return;
Expand All @@ -105,8 +84,8 @@ function BaseShareLogList({onAttachLogToReport}: BaseShareLogListProps) {
};

useEffect(() => {
searchInServer(debouncedSearchValue);
}, [debouncedSearchValue]);
searchInServer(debouncedSearchTerm);
}, [debouncedSearchTerm]);

return (
<ScreenWrapper
Expand All @@ -121,12 +100,12 @@ function BaseShareLogList({onAttachLogToReport}: BaseShareLogListProps) {
/>
<SelectionList
ListItem={UserListItem}
sections={didScreenTransitionEnd ? sections : CONST.EMPTY_ARRAY}
sections={sections}
onSelectRow={attachLogToReport}
shouldSingleExecuteRowSelect
onChangeText={setSearchValue}
textInputValue={searchValue}
headerMessage={searchOptions.headerMessage}
onChangeText={setSearchTerm}
textInputValue={searchTerm}
headerMessage={headerMessage}
textInputLabel={translate('selectionList.nameEmailOrPhoneNumber')}
textInputHint={isOffline ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''}
showLoadingPlaceholder={!didScreenTransitionEnd}
Expand Down
8 changes: 1 addition & 7 deletions tests/perf-test/OptionsListUtils.perf-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {rand} from '@ngneat/falso';
import type * as NativeNavigation from '@react-navigation/native';
import Onyx from 'react-native-onyx';
import {measureFunction} from 'reassure';
import {createOptionList, filterAndOrderOptions, getMemberInviteOptions, getSearchOptions, getShareLogOptions, getValidOptions} from '@libs/OptionsListUtils';
import {createOptionList, filterAndOrderOptions, getMemberInviteOptions, getSearchOptions, getValidOptions} from '@libs/OptionsListUtils';
import type {OptionData} from '@libs/ReportUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
Expand Down Expand Up @@ -110,12 +110,6 @@ describe('OptionsListUtils', () => {
await measureFunction(() => getSearchOptions({options, betas: mockedBetas, draftComments: {}}));
});

/* Testing getShareLogOptions */
test('[OptionsListUtils] getShareLogOptions', async () => {
await waitForBatchedUpdates();
await measureFunction(() => getShareLogOptions(options, {}, mockedBetas));
});

/* Testing getFilteredOptions */
test('[OptionsListUtils] getFilteredOptions with search value', async () => {
await waitForBatchedUpdates();
Expand Down
13 changes: 0 additions & 13 deletions tests/unit/OptionsListUtilsTest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import {
getMemberInviteOptions,
getSearchOptions,
getSearchValueForPhoneOrEmail,
getShareLogOptions,
getValidOptions,
optionsOrderBy,
orderOptions,
Expand Down Expand Up @@ -1275,18 +1274,6 @@ describe('OptionsListUtils', () => {
});
});

describe('getShareLogOptions()', () => {
it('should not include read-only report', () => {
// Given a list of 11 report options with reportID of 10 is archived
// When we call getShareLogOptions
const results = getShareLogOptions(OPTIONS, {}, []);

// Then the report with reportID of 10 should not be included on the list
expect(results.recentReports.length).toBe(10);
expect(results.recentReports.find((report) => report.reportID === '10')).toBeUndefined();
});
});

describe('getMemberInviteOptions()', () => {
it('should sort personal details alphabetically', () => {
// Given a set of personalDetails
Expand Down
Loading