Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
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
2 changes: 2 additions & 0 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1051,6 +1051,7 @@ const ONYXKEYS = {
PERSONAL_AND_WORKSPACE_CARD_LIST: 'personalAndWorkspaceCardList',
CARD_FEED_ERRORS: 'cardFeedErrors',
TODOS: 'todos',
SORTED_REPORT_ACTIONS: 'sortedReportActions',
},

/** Stores HybridApp specific state required to interoperate with OldDot */
Expand Down Expand Up @@ -1484,6 +1485,7 @@ type OnyxDerivedValuesMapping = {
[ONYXKEYS.DERIVED.PERSONAL_AND_WORKSPACE_CARD_LIST]: OnyxTypes.PersonalAndWorkspaceCardListDerivedValue;
[ONYXKEYS.DERIVED.CARD_FEED_ERRORS]: OnyxTypes.CardFeedErrorsDerivedValue;
[ONYXKEYS.DERIVED.TODOS]: OnyxTypes.TodosDerivedValue;
[ONYXKEYS.DERIVED.SORTED_REPORT_ACTIONS]: OnyxTypes.SortedReportActionsDerivedValue;
};

type OnyxValues = OnyxValuesMapping & OnyxCollectionValuesMapping & OnyxFormValuesMapping & OnyxFormDraftValuesMapping & OnyxDerivedValuesMapping;
Expand Down
13 changes: 10 additions & 3 deletions src/hooks/useSearchSelector.base.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {sortedActionsSelector} from '@selectors/SortedReportActions';
import {useCallback, useMemo, useState} from 'react';
import type {PermissionStatus} from 'react-native-permissions';
import {usePersonalDetails} from '@components/OnyxListItemProvider';
Expand All @@ -7,7 +8,7 @@ import {getEmptyOptions, getPersonalDetailSearchTerms, getSearchOptions, getSear
import type {OptionData} from '@libs/ReportUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {PersonalDetails} from '@src/types/onyx';
import type * as OnyxTypes from '@src/types/onyx';
import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails';
import useDebounce from './useDebounce';
import useDebouncedState from './useDebouncedState';
Expand Down Expand Up @@ -69,7 +70,7 @@ type UseSearchSelectorConfig = {
shouldInitialize?: boolean;

/** Additional contact options to merge (used by platform-specific implementations) */
contactOptions?: Array<SearchOption<PersonalDetails>>;
contactOptions?: Array<SearchOption<OnyxTypes.PersonalDetails>>;

/** Whether to filter with recent attendees */
recentAttendees?: Array<Partial<OptionData>>;
Expand All @@ -83,7 +84,7 @@ type ContactState = {
permissionStatus: PermissionStatus;

/** Contact options from device */
contactOptions: Array<SearchOption<PersonalDetails>>;
contactOptions: Array<SearchOption<OnyxTypes.PersonalDetails>>;

/** Whether to show import UI */
showImportUI: boolean;
Expand Down Expand Up @@ -193,6 +194,7 @@ function useSearchSelectorBase({
const [draftComments] = useOnyx(ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT);
const [nvpDismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING);
const [visibleReportActionsData] = useOnyx(ONYXKEYS.DERIVED.VISIBLE_REPORT_ACTIONS);
const [sortedActions] = useOnyx(ONYXKEYS.DERIVED.SORTED_REPORT_ACTIONS, {selector: sortedActionsSelector});
const currentUserPersonalDetails = useCurrentUserPersonalDetails();
const currentUserAccountID = currentUserPersonalDetails.accountID;
const currentUserEmail = currentUserPersonalDetails.email ?? '';
Expand Down Expand Up @@ -255,6 +257,7 @@ function useSearchSelectorBase({
countryCode,
reportAttributesDerived: reportAttributesDerived?.reports,
allPolicyTags,
sortedActions,
});
case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_GENERAL:
return getValidOptions(optionsWithContacts, allPolicies, draftComments, nvpDismissedProductTraining, loginList, currentUserAccountID, currentUserEmail, {
Expand All @@ -276,6 +279,7 @@ function useSearchSelectorBase({
countryCode,
reportAttributesDerived: reportAttributesDerived?.reports,
allPolicyTags,
sortedActions,
...getValidOptionsConfig,
});
case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_SHARE_DESTINATION:
Expand All @@ -300,6 +304,7 @@ function useSearchSelectorBase({
countryCode,
reportAttributesDerived: reportAttributesDerived?.reports,
allPolicyTags,
sortedActions,
});
case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_ATTENDEES:
return getValidOptions(optionsWithContacts, allPolicies, draftComments, nvpDismissedProductTraining, loginList, currentUserAccountID, currentUserEmail, {
Expand All @@ -321,6 +326,7 @@ function useSearchSelectorBase({
countryCode,
reportAttributesDerived: reportAttributesDerived?.reports,
allPolicyTags,
sortedActions,
...getValidOptionsConfig,
});
default:
Expand Down Expand Up @@ -356,6 +362,7 @@ function useSearchSelectorBase({
selectedOptions,
visibleReportActionsData,
allPolicyTags,
sortedActions,
]);

const isOptionSelected = useMemo(() => {
Expand Down
52 changes: 35 additions & 17 deletions src/libs/OptionsListUtils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@
*/

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

Check warning on line 210 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 @@ -215,38 +215,45 @@
},
});

const lastReportActions: ReportActions = {};
const allSortedReportActions: Record<string, ReportAction[]> = {};
const cachedOneTransactionThreadReportIDs: Record<string, string | undefined> = {};
let allReportActions: OnyxCollection<ReportActions>;
/** @deprecated Use sortedReportActionsData from ONYXKEYS.DERIVED.SORTED_REPORT_ACTIONS instead. Will be removed once all flows are migrated. */
const deprecatedLastReportActions: ReportActions = {};
/** @deprecated Use sortedReportActionsData from ONYXKEYS.DERIVED.SORTED_REPORT_ACTIONS instead. Will be removed once all flows are migrated. */
const deprecatedAllSortedReportActions: Record<string, ReportAction[]> = {};
/** @deprecated Use sortedReportActionsData from ONYXKEYS.DERIVED.SORTED_REPORT_ACTIONS instead. Will be removed once all flows are migrated. */
const deprecatedCachedOneTransactionThreadReportIDs: Record<string, string | undefined> = {};
/** @deprecated Use sortedReportActionsData from ONYXKEYS.DERIVED.SORTED_REPORT_ACTIONS instead. Will be removed once all flows are migrated. */
let deprecatedAllReportActions: OnyxCollection<ReportActions>;
Onyx.connect({

Check warning on line 226 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) => {
if (!actions) {
return;
}

allReportActions = actions ?? {};
// eslint-disable-next-line @typescript-eslint/no-deprecated
deprecatedAllReportActions = actions ?? {};

// Iterate over the report actions to build the sorted report actions objects
for (const reportActions of Object.entries(allReportActions)) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
for (const reportActions of Object.entries(deprecatedAllReportActions)) {
const reportID = reportActions[0].split('_').at(1);
if (!reportID) {
continue;
}

const reportActionsArray = Object.values(reportActions[1] ?? {});
let sortedReportActions = getSortedReportActions(withDEWRoutedActionsArray(reportActionsArray), true);
allSortedReportActions[reportID] = sortedReportActions;
// eslint-disable-next-line @typescript-eslint/no-deprecated
deprecatedAllSortedReportActions[reportID] = sortedReportActions;
const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`];

// If the report is a one-transaction report, we need to return the combined reportActions so that the LHN can display modifications
// to the transaction thread or the report itself.
// Cache the result for O(1) lookup in renderItem.
const transactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, actions[reportActions[0]]);
cachedOneTransactionThreadReportIDs[reportID] = transactionThreadReportID;
// eslint-disable-next-line @typescript-eslint/no-deprecated
deprecatedCachedOneTransactionThreadReportIDs[reportID] = transactionThreadReportID;

if (transactionThreadReportID) {
const transactionThreadReportActionsArray = Object.values(actions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID}`] ?? {});
Expand All @@ -255,16 +262,18 @@

const firstReportAction = sortedReportActions.at(0);
if (!firstReportAction) {
delete lastReportActions[reportID];
// eslint-disable-next-line @typescript-eslint/no-deprecated
delete deprecatedLastReportActions[reportID];
} else {
lastReportActions[reportID] = firstReportAction;
// eslint-disable-next-line @typescript-eslint/no-deprecated
deprecatedLastReportActions[reportID] = firstReportAction;
}
}
},
});

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

Check warning on line 276 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 @@ -618,7 +627,8 @@
const canUserPerformWrite = canUserPerformWriteAction(report, isReportArchived);
let lastReportAction = lastAction ?? getLastVisibleAction(reportID, canUserPerformWrite, {}, undefined, visibleReportActionsDataParam);

const transactionThreadReportID = reportID ? cachedOneTransactionThreadReportIDs[reportID] : undefined;
// eslint-disable-next-line @typescript-eslint/no-deprecated
const transactionThreadReportID = reportID ? deprecatedCachedOneTransactionThreadReportIDs[reportID] : undefined;

if (reportID && !lastAction && transactionThreadReportID) {
lastReportAction =
Expand Down Expand Up @@ -648,7 +658,8 @@
}

// some types of actions are filtered out for lastReportAction, in some cases we need to check the actual last action
const lastOriginalReportAction = reportID ? lastReportActions[reportID] : undefined;
// eslint-disable-next-line @typescript-eslint/no-deprecated
const lastOriginalReportAction = reportID ? deprecatedLastReportActions[reportID] : undefined;
let lastMessageTextFromReport = '';

if (isArchivedNonExpenseReport(report, isReportArchived)) {
Expand Down Expand Up @@ -681,7 +692,8 @@
const iouReportID = iouReport?.reportID;
const reportCache = iouReportID ? visibleReportActionsDataParam?.[iouReportID] : undefined;
const visibleReportActionsForIOUReport = reportCache && Object.keys(reportCache).length > 0 ? visibleReportActionsDataParam : undefined;
const iouReportActions = iouReportID ? allSortedReportActions[iouReportID] : undefined;
// eslint-disable-next-line @typescript-eslint/no-deprecated
const iouReportActions = iouReportID ? deprecatedAllSortedReportActions[iouReportID] : undefined;
const canPerformWrite = canUserPerformWriteAction(report, isReportArchived);
const lastIOUMoneyReportAction =
iouReportID && iouReportActions
Expand Down Expand Up @@ -2253,6 +2265,8 @@
config: GetValidReportsConfig,
visibleReportActionsData: VisibleReportActionsDerivedValue = {},
reportAttributesDerived?: ReportAttributesDerivedValue['reports'],
// eslint-disable-next-line @typescript-eslint/no-deprecated
sortedActions: Record<string, ReportAction[]> = deprecatedAllSortedReportActions,
policyTags?: OnyxCollection<PolicyTagLists>,
): Array<SearchOption<Report>> {
const {
Expand Down Expand Up @@ -2305,7 +2319,7 @@
const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report.chatReportID}`];
const oneTransactionThreadReportID =
report.type === CONST.REPORT.TYPE.IOU || report.type === CONST.REPORT.TYPE.EXPENSE || report.type === CONST.REPORT.TYPE.INVOICE
? getOneTransactionThreadReportID(report, chatReport, allSortedReportActions[report.reportID])
? getOneTransactionThreadReportID(report, chatReport, sortedActions[report.reportID])
: undefined;
const oneTransactionThreadReport = oneTransactionThreadReportID ? allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${oneTransactionThreadReportID}`] : undefined;

Expand All @@ -2315,11 +2329,11 @@
let lastIOUCreationDate;
// Add a field to sort the recent reports by the time of last IOU request for create actions
if (preferRecentExpenseReports) {
const reportPreviewAction = allSortedReportActions[option.reportID]?.find((reportAction) => isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW));
const reportPreviewAction = sortedActions[option.reportID]?.find((reportAction) => isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW));

if (reportPreviewAction) {
const iouReportID = getIOUReportIDFromReportActionPreview(reportPreviewAction);
const iouReportActions = iouReportID ? (allSortedReportActions[iouReportID] ?? []) : [];
const iouReportActions = iouReportID ? (sortedActions[iouReportID] ?? []) : [];
const lastIOUAction = iouReportActions.find((iouAction) => iouAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU);
if (lastIOUAction) {
lastIOUCreationDate = lastIOUAction.lastModified;
Expand Down Expand Up @@ -2440,6 +2454,7 @@
countryCode = CONST.DEFAULT_COUNTRY_CODE,
visibleReportActionsData = {},
reportAttributesDerived,
sortedActions,
...config
}: GetOptionsConfig = {},
): Options {
Expand Down Expand Up @@ -2545,6 +2560,7 @@
},
visibleReportActionsData,
reportAttributesDerived,
sortedActions,
allPolicyTags,
).at(0);
}
Expand All @@ -2567,6 +2583,7 @@
},
visibleReportActionsData,
reportAttributesDerived,
sortedActions,
allPolicyTags,
);

Expand All @@ -2585,6 +2602,7 @@
},
visibleReportActionsData,
reportAttributesDerived,
sortedActions,
allPolicyTags,
);
} else if (recentAttendees && recentAttendees?.length > 0) {
Expand Down
3 changes: 3 additions & 0 deletions src/libs/OptionsListUtils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {
PersonalDetailsList,
PolicyTagLists,
Report,
ReportAction,
ReportActions,
ReportAttributesDerivedValue,
TransactionViolation,
Expand Down Expand Up @@ -221,6 +222,8 @@ type GetOptionsConfig = {
countryCode?: number;
visibleReportActionsData?: VisibleReportActionsDerivedValue;
reportAttributesDerived?: ReportAttributesDerivedValue['reports'];
// TODO: Remove the optional operator once all call sites pass sortedActions (https://github.com/Expensify/App/issues/66381)
sortedActions?: Record<string, ReportAction[]>;
Comment thread
truph01 marked this conversation as resolved.
} & GetValidReportsConfig;

type GetUserToInviteConfig = {
Expand Down
2 changes: 2 additions & 0 deletions src/libs/actions/OnyxDerived/ONYX_DERIVED_VALUES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import outstandingReportsByPolicyIDConfig from './configs/outstandingReportsByPo
import personalAndWorkspaceCardListConfig from './configs/personalAndWorkspaceCardList';
import reportAttributesConfig from './configs/reportAttributes';
import reportTransactionsAndViolationsConfig from './configs/reportTransactionsAndViolations';
import sortedReportActionsConfig from './configs/sortedReportActions';
import todosConfig from './configs/todos';
import visibleReportActionsConfig from './configs/visibleReportActions';
import type {OnyxDerivedValueConfig} from './types';
Expand All @@ -23,6 +24,7 @@ const ONYX_DERIVED_VALUES = {
[ONYXKEYS.DERIVED.PERSONAL_AND_WORKSPACE_CARD_LIST]: personalAndWorkspaceCardListConfig,
[ONYXKEYS.DERIVED.CARD_FEED_ERRORS]: cardFeedErrorsConfig,
[ONYXKEYS.DERIVED.TODOS]: todosConfig,
[ONYXKEYS.DERIVED.SORTED_REPORT_ACTIONS]: sortedReportActionsConfig,
} as const satisfies {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[Key in ValueOf<typeof ONYXKEYS.DERIVED>]: OnyxDerivedValueConfig<Key, any>;
Expand Down
Loading
Loading