Skip to content
Merged
29 changes: 13 additions & 16 deletions src/libs/actions/OnyxDerived/configs/reportAttributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {PersonalDetailsList, Policy, ReportAttributesDerivedValue} from '@src/types/onyx';

let isFullyComputed = false;
let previousDisplayNames: Record<string, string | undefined> = {};
let previousPersonalDetails: OnyxEntry<PersonalDetailsList> | undefined;
let previousPolicies: OnyxCollection<Policy>;
Expand Down Expand Up @@ -58,7 +57,6 @@ const checkDisplayNamesChanged = (personalDetails: OnyxEntry<PersonalDetailsList
/**
* This derived value is used to get the report attributes for the report.
*/

export default createOnyxDerivedValueConfig({
key: ONYXKEYS.DERIVED.REPORT_ATTRIBUTES,
dependencies: [
Expand Down Expand Up @@ -91,22 +89,25 @@ export default createOnyxDerivedValueConfig({
previousPersonalDetails = undefined;
}

// if any of those keys changed, reset the isFullyComputed flag to recompute all reports
// we need to recompute all report attributes on locale change because the report names are locale dependent
if (hasKeyTriggeredCompute(ONYXKEYS.NVP_PREFERRED_LOCALE, sourceValues) || displayNamesChanged) {
isFullyComputed = false;
}
// A full recompute is needed when locale changes (report names are locale-dependent) or display names change.
// We compare preferredLocale against currentValue?.locale so that the first locale load on startup
// (where both equal the same persisted value) does not trigger an unnecessary full recompute.
let needsFullRecompute = (hasKeyTriggeredCompute(ONYXKEYS.NVP_PREFERRED_LOCALE, sourceValues) && preferredLocale !== currentValue?.locale) || displayNamesChanged;

// if policies are loaded first time, we need to recompute all report attributes to get correct action badge in LHN, such as Approve because it depends on policy's type (see canApproveIOU function)
if (hasKeyTriggeredCompute(ONYXKEYS.COLLECTION.POLICY, sourceValues)) {
if (isFullyComputed && Object.keys(previousPolicies ?? {}).length === 0 && Object.keys(policies ?? {}).length > 0) {
isFullyComputed = false;
if (Object.keys(previousPolicies ?? {}).length === 0 && Object.keys(policies ?? {}).length > 0) {
needsFullRecompute = true;
}
previousPolicies = policies;
}

// Use incremental updates when currentValue is already populated and no full recompute is required.
// If currentValue has no reports (fresh install or cleared storage), fall back to a full scan.
const useIncrementalUpdates = !!currentValue?.reports && Object.keys(currentValue.reports).length > 0 && !needsFullRecompute;

// if we already computed the report attributes and there is no new reports data, return the current value
if ((isFullyComputed && !sourceValues) || !reports) {
if ((useIncrementalUpdates && !sourceValues) || !reports) {
return currentValue ?? {reports: {}, locale: null};
}

Expand Down Expand Up @@ -141,7 +142,7 @@ export default createOnyxDerivedValueConfig({
...Array.from(reportUpdatesRelatedToReportActions),
];

if (isFullyComputed) {
if (useIncrementalUpdates) {
// if there are report-related updates, iterate over the updates
if (updates.length > 0 || !!transactionsUpdates || !!transactionViolationsUpdates) {
if (updates.length > 0) {
Expand Down Expand Up @@ -187,6 +188,7 @@ export default createOnyxDerivedValueConfig({
return currentValue ?? {reports: {}, locale: null};
}
}

const reportAttributes = dataToIterate.reduce<ReportAttributesDerivedValue['reports']>((acc, key) => {
// source value sends partial data, so we need an entire report object to do computations
const report = reports[key];
Expand Down Expand Up @@ -281,11 +283,6 @@ export default createOnyxDerivedValueConfig({
reportAttributes[chatReportID].actionBadge = CONST.REPORT.ACTION_BADGE.FIX;
}

// mark the report attributes as fully computed after first iteration to avoid unnecessary recomputation on all objects
if (!Object.keys(reportUpdates).length && Object.keys(reports ?? {}).length > 0 && !isFullyComputed) {
isFullyComputed = true;
}

return {
reports: reportAttributes,
locale: preferredLocale ?? null,
Expand Down
Loading