Skip to content
Draft
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
138 changes: 134 additions & 4 deletions src/libs/OptionsListUtils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@
isTaskAction,
isThreadParentMessage,
isUnapprovedAction,
isWhisperAction,
shouldReportActionBeVisible,
withDEWRoutedActionsArray,
} from '@libs/ReportActionsUtils';
import {computeReportName} from '@libs/ReportNameUtils';
Expand Down Expand Up @@ -197,13 +199,13 @@
*/

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

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

View workflow job for this annotation

GitHub Actions / ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function

Check warning on line 202 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 208 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 @@ -215,14 +217,14 @@
});

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

Check warning on line 220 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 227 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 @@ -231,7 +233,77 @@
});

let allReportNameValuePairsOnyxConnect: OnyxCollection<ReportNameValuePairs>;

const lastReportActions: ReportActions = {};
const allSortedReportActions: Record<string, ReportAction[]> = {};
let allReportActions: OnyxCollection<ReportActions>;
const lastVisibleReportActions: ReportActions = {};
const filteredReportActionsCache: Record<string, ReportAction[]> = {};
const lastMessageTextCache: Record<string, string> = {};

/**
* Invalidates and recomputes cache entries for a specific report.
* This is called when report actions, metadata, or archived status changes.
*
* @param reportID - The ID of the report to invalidate cache for
*/
function invalidateCacheForReport(reportID: string) {
if (!reportID) {
return;
}

delete lastMessageTextCache[reportID];
delete filteredReportActionsCache[reportID];

if (allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`]) {
const reportActionsArray = Object.values(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`] ?? {});
const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`];
const transactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`]);

let sortedReportActions = getSortedReportActions(withDEWRoutedActionsArray(reportActionsArray), true);
if (transactionThreadReportID) {
const transactionThreadReportActionsArray = Object.values(allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID}`] ?? {});
sortedReportActions = getCombinedReportActions(sortedReportActions, transactionThreadReportID, transactionThreadReportActionsArray, reportID);
}
allSortedReportActions[reportID] = sortedReportActions;

const reportNameValuePairs = allReportNameValuePairsOnyxConnect?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`];
const isReportArchived = !!reportNameValuePairs?.private_isArchived;
const isWriteActionAllowed = canUserPerformWriteAction(report, isReportArchived);

const reportActionsForDisplay = sortedReportActions.filter(
(reportAction) =>
(!(isWhisperAction(reportAction) && !isReportPreviewAction(reportAction) && !isMoneyRequestAction(reportAction)) || isActionableMentionWhisper(reportAction)) &&
shouldReportActionBeVisible(reportAction, reportAction.reportActionID, isWriteActionAllowed) &&
reportAction.actionName !== CONST.REPORT.ACTIONS.TYPE.CREATED &&
reportAction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
);
filteredReportActionsCache[reportID] = reportActionsForDisplay;

const reportActionForDisplay = reportActionsForDisplay.at(0);
if (!reportActionForDisplay) {
delete lastVisibleReportActions[reportID];
return;
}
lastVisibleReportActions[reportID] = reportActionForDisplay;

const lastActorAccountID = report?.lastActorAccountID;
let lastActorDetails: Partial<PersonalDetails> | null = lastActorAccountID && allPersonalDetails?.[lastActorAccountID] ? allPersonalDetails[lastActorAccountID] : null;

if (!lastActorDetails && reportActionForDisplay) {
const lastActorDisplayName = reportActionForDisplay.person?.[0]?.text;
lastActorDetails = lastActorDisplayName
? {
displayName: lastActorDisplayName,
accountID: lastActorAccountID,
}
: null;
}
}
}

Onyx.connect({

Check warning on line 306 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 @@ -239,10 +311,44 @@
},
});

const lastReportActions: ReportActions = {};
const allSortedReportActions: Record<string, ReportAction[]> = {};
let allReportActions: OnyxCollection<ReportActions>;
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.COLLECTION.REPORT_NAME_VALUE_PAIRS,
callback: (value, key) => {
if (!key) {
return;
}
const reportID = key.split('_').at(1);
if (reportID) {
invalidateCacheForReport(reportID);
}
},
});

// Stored for collection callback ordering; may be read by other code in this module
// eslint-disable-next-line @typescript-eslint/no-unused-vars
let allReportMetadata: OnyxCollection<ReportMetadata>;
Onyx.connect({

Check warning on line 330 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_METADATA,
waitForCollectionCallback: true,
callback: (value) => {
allReportMetadata = value;
},
});

Onyx.connect({

Check warning on line 338 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_METADATA,
callback: (value, key) => {
if (!key) {
return;
}
const reportID = key.split('_').at(1);
if (reportID) {
invalidateCacheForReport(reportID);
}
},
});

Onyx.connect({

Check warning on line 351 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 All @@ -265,7 +371,7 @@
const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`];

// If the report is a one-transaction report and has , we need to return the combined reportActions so that the LHN can display modifications
// 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
const transactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, actions[reportActions[0]]);
if (transactionThreadReportID) {
Expand All @@ -280,12 +386,13 @@
} else {
lastReportActions[reportID] = firstReportAction;
}
invalidateCacheForReport(reportID);
}
},
});

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

Check warning on line 395 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 @@ -321,6 +428,27 @@
return personalDetailsForAccountIDs;
}

function getCachedReportActionsForDisplay(reportID: string): ReportAction[] {
return filteredReportActionsCache[reportID] ?? [];
}

/**
* Get cached last message text for a report, or compute and cache it if missing.
* This uses lazy computation to avoid using deprecated translateLocal in module-level Onyx.connect callbacks.
*
* @param reportID - The report ID to get cached message text for
* @param computeFn - Optional function to compute the message text if cache miss. If provided, result will be cached.
* @returns Cached message text, or undefined if cache miss and no computeFn provided
*/
function getCachedLastMessageText(reportID: string, computeFn?: () => string): string | undefined {
let cached = lastMessageTextCache[reportID];
if (!cached && computeFn) {
cached = computeFn();
lastMessageTextCache[reportID] = cached;
}
return cached;
}

/**
* Return true if personal details data is ready, i.e. report list options can be created.
*/
Expand Down Expand Up @@ -467,11 +595,11 @@
const formattedLastMessageTextWithPrefix = reportPrefix + formattedLastMessageText;

if (isExpenseThread || option.isMoneyRequestReport) {
return showChatPreviewLine && formattedLastMessageText ? formattedLastMessageTextWithPrefix : translateFn('iou.expense');

Check failure on line 598 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

`translateFn` is deprecated. This function uses imperative Onyx data access patterns, similar to `Onyx.connect`. Use `useLocalize` hook instead for reactive data access in React components

Check failure on line 598 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

`translateFn` is deprecated. This function uses imperative Onyx data access patterns, similar to `Onyx.connect`. Use `useLocalize` hook instead for reactive data access in React components
}

if (option.isThread) {
return showChatPreviewLine && formattedLastMessageText ? formattedLastMessageTextWithPrefix : translateFn('threads.thread');

Check failure on line 602 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

`translateFn` is deprecated. This function uses imperative Onyx data access patterns, similar to `Onyx.connect`. Use `useLocalize` hook instead for reactive data access in React components

Check failure on line 602 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

`translateFn` is deprecated. This function uses imperative Onyx data access patterns, similar to `Onyx.connect`. Use `useLocalize` hook instead for reactive data access in React components
}

if (option.isChatRoom && !isAdminRoom && !isAnnounceRoom) {
Expand All @@ -483,11 +611,11 @@
}

if (option.isTaskReport) {
return showChatPreviewLine && formattedLastMessageText ? formattedLastMessageTextWithPrefix : translateFn('task.task');

Check failure on line 614 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

`translateFn` is deprecated. This function uses imperative Onyx data access patterns, similar to `Onyx.connect`. Use `useLocalize` hook instead for reactive data access in React components

Check failure on line 614 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

`translateFn` is deprecated. This function uses imperative Onyx data access patterns, similar to `Onyx.connect`. Use `useLocalize` hook instead for reactive data access in React components
}

if (isGroupChat) {
return showChatPreviewLine && formattedLastMessageText ? formattedLastMessageTextWithPrefix : translateFn('common.group');

Check failure on line 618 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

`translateFn` is deprecated. This function uses imperative Onyx data access patterns, similar to `Onyx.connect`. Use `useLocalize` hook instead for reactive data access in React components

Check failure on line 618 in src/libs/OptionsListUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

`translateFn` is deprecated. This function uses imperative Onyx data access patterns, similar to `Onyx.connect`. Use `useLocalize` hook instead for reactive data access in React components
}

return showChatPreviewLine && formattedLastMessageText
Expand Down Expand Up @@ -3216,6 +3344,8 @@
getLastActorDisplayName,
getLastActorDisplayNameFromLastVisibleActions,
getLastMessageTextForReport,
getCachedReportActionsForDisplay,
getCachedLastMessageText,
getManagerMcTestParticipant,
getMemberInviteOptions,
getParticipantsOption,
Expand Down
Loading
Loading