From 0e55971e1d0a0344faf7d665479d80a63676d5fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Le=C5=9Bniewski?= Date: Tue, 3 Mar 2026 14:16:31 +0100 Subject: [PATCH 1/9] refactor: subscribe to POLICY_TAGS in reportAttributes and pass policyTags to computeReportName Wire POLICY_TAGS into the reportAttributes OnyxDerived config so per-report policy tags are available at derivation time and forwarded to computeReportName. Co-Authored-By: Claude Sonnet 4.6 --- .../OnyxDerived/configs/reportAttributes.ts | 19 +++++++++++++++-- tests/unit/OnyxDerivedTest.tsx | 21 +++++++++++-------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/libs/actions/OnyxDerived/configs/reportAttributes.ts b/src/libs/actions/OnyxDerived/configs/reportAttributes.ts index 7be982ceb0080..ac3a09db9a76c 100644 --- a/src/libs/actions/OnyxDerived/configs/reportAttributes.ts +++ b/src/libs/actions/OnyxDerived/configs/reportAttributes.ts @@ -70,9 +70,13 @@ export default createOnyxDerivedValueConfig({ ONYXKEYS.PERSONAL_DETAILS_LIST, ONYXKEYS.SESSION, ONYXKEYS.COLLECTION.POLICY, + ONYXKEYS.COLLECTION.POLICY_TAGS, ONYXKEYS.COLLECTION.REPORT_METADATA, ], - compute: ([reports, preferredLocale, transactionViolations, reportActions, reportNameValuePairs, transactions, personalDetails, session, policies], {currentValue, sourceValues}) => { + compute: ( + [reports, preferredLocale, transactionViolations, reportActions, reportNameValuePairs, transactions, personalDetails, session, policies, policyTags], + {currentValue, sourceValues}, + ) => { // Check if display names changed when personal details are updated let displayNamesChanged = false; if (hasKeyTriggeredCompute(ONYXKEYS.PERSONAL_DETAILS_LIST, sourceValues)) { @@ -211,7 +215,18 @@ export default createOnyxDerivedValueConfig({ acc[report.reportID] = { reportName: report - ? computeReportName(report, reports, policies, transactions, reportNameValuePairs, personalDetails, reportActions, session?.accountID ?? CONST.DEFAULT_NUMBER_ID) + ? computeReportName( + report, + reports, + policies, + transactions, + reportNameValuePairs, + personalDetails, + reportActions, + session?.accountID ?? CONST.DEFAULT_NUMBER_ID, + undefined, + policyTags, + ) : '', isEmpty: generateIsEmptyReport(report, isReportArchived), brickRoadStatus, diff --git a/tests/unit/OnyxDerivedTest.tsx b/tests/unit/OnyxDerivedTest.tsx index d753e2095788a..80e6e3b73c425 100644 --- a/tests/unit/OnyxDerivedTest.tsx +++ b/tests/unit/OnyxDerivedTest.tsx @@ -123,17 +123,20 @@ describe('OnyxDerived', () => { const transaction = createRandomTransaction(1); // When the report attributes are recomputed with both report and transaction updates - reportAttributes.compute([reports, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined], {}); - const reportAttributesComputedValue = reportAttributes.compute([reports, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined], { - sourceValues: { - [ONYXKEYS.COLLECTION.REPORT]: { - [`${ONYXKEYS.COLLECTION.REPORT}${reportID1}`]: reports[`${ONYXKEYS.COLLECTION.REPORT}${reportID1}`], - }, - [ONYXKEYS.COLLECTION.TRANSACTION]: { - [`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`]: transaction, + reportAttributes.compute([reports, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined], {}); + const reportAttributesComputedValue = reportAttributes.compute( + [reports, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined], + { + sourceValues: { + [ONYXKEYS.COLLECTION.REPORT]: { + [`${ONYXKEYS.COLLECTION.REPORT}${reportID1}`]: reports[`${ONYXKEYS.COLLECTION.REPORT}${reportID1}`], + }, + [ONYXKEYS.COLLECTION.TRANSACTION]: { + [`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`]: transaction, + }, }, }, - }).reports; + ).reports; // Then the computed report attributes should contain both reports expect(Object.keys(reportAttributesComputedValue)).toEqual([reportID1, reportID2]); From cd86c19eda2cb4038e7336332859ffd829760510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Le=C5=9Bniewski?= Date: Mon, 2 Mar 2026 19:57:54 +0100 Subject: [PATCH 2/9] refactor: pass policy tags through browser notification chain for modified expenses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wire policyTags, policy, and currentUserLogin through showReportActionNotification → showModifiedExpenseNotification → pushModifiedExpenseNotification so the notification body can use the non-Onyx.connect path (getForReportActionTemp) when policy tags are available, while falling back to the old getForReportAction otherwise. Add module-level allPolicies and allPolicyTags Onyx connections to Report/index.ts following the same pattern as the existing allReports connection. Co-Authored-By: Claude Sonnet 4.6 --- .../LocalNotification/BrowserNotifications.ts | 40 ++++++++++++++----- .../Notification/LocalNotification/index.ts | 4 +- .../Notification/LocalNotification/types.ts | 4 +- src/libs/actions/Report/index.ts | 33 ++++++++++++++- 4 files changed, 68 insertions(+), 13 deletions(-) diff --git a/src/libs/Notification/LocalNotification/BrowserNotifications.ts b/src/libs/Notification/LocalNotification/BrowserNotifications.ts index 3df24270115a4..957482497a85a 100644 --- a/src/libs/Notification/LocalNotification/BrowserNotifications.ts +++ b/src/libs/Notification/LocalNotification/BrowserNotifications.ts @@ -3,7 +3,9 @@ import {Str} from 'expensify-common'; import type {ImageSourcePropType} from 'react-native'; import EXPENSIFY_ICON_URL from '@assets/images/expensify-logo-round-clearspace.png'; import * as AppUpdate from '@libs/actions/AppUpdate'; -import {getForReportAction} from '@libs/ModifiedExpenseMessage'; +// eslint-disable-next-line @typescript-eslint/no-deprecated -- translateLocal is deprecated; BrowserNotifications is non-React code that cannot use the translate hook +import {translateLocal} from '@libs/Localize'; +import {getForReportAction, getForReportActionTemp} from '@libs/ModifiedExpenseMessage'; import {getTextFromHtml} from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; import playSound, {SOUNDS} from '@libs/Sound'; @@ -130,15 +132,35 @@ export default { push(title, body, icon, data, onClick); }, - pushModifiedExpenseNotification({report, reportAction, movedFromReport, movedToReport, onClick, usesIcon = false, currentUserLogin}: LocalNotificationModifiedExpensePushParams) { + pushModifiedExpenseNotification({ + report, + reportAction, + movedFromReport, + movedToReport, + onClick, + usesIcon = false, + policyTags, + policy, + currentUserLogin, + }: LocalNotificationModifiedExpensePushParams) { const title = reportAction.person?.map((f) => f.text).join(', ') ?? ''; - const body = getForReportAction({ - reportAction, - policyID: report.policyID, - movedFromReport, - movedToReport, - currentUserLogin, - }); + const body = policyTags + ? getForReportActionTemp({ + // eslint-disable-next-line @typescript-eslint/no-deprecated -- translateLocal is deprecated; BrowserNotifications is non-React code that cannot use the translate hook + translate: translateLocal, + reportAction, + policy, + movedFromReport, + movedToReport, + policyTags, + currentUserLogin, + }) + : getForReportAction({ + reportAction, + policyID: report.policyID, + movedFromReport, + movedToReport, + }); const icon = usesIcon ? EXPENSIFY_ICON_URL : ''; const data = { reportID: report.reportID, diff --git a/src/libs/Notification/LocalNotification/index.ts b/src/libs/Notification/LocalNotification/index.ts index 24b07db283622..0e69b1621db01 100644 --- a/src/libs/Notification/LocalNotification/index.ts +++ b/src/libs/Notification/LocalNotification/index.ts @@ -10,8 +10,8 @@ function showUpdateAvailableNotification() { BrowserNotifications.pushUpdateAvailableNotification(); } -function showModifiedExpenseNotification({report, reportAction, movedFromReport, movedToReport, currentUserLogin, onClick}: LocalNotificationModifiedExpenseParams) { - BrowserNotifications.pushModifiedExpenseNotification({report, reportAction, movedFromReport, movedToReport, onClick, usesIcon: true, currentUserLogin}); +function showModifiedExpenseNotification({report, reportAction, movedFromReport, movedToReport, onClick, policyTags, policy, currentUserLogin}: LocalNotificationModifiedExpenseParams) { + BrowserNotifications.pushModifiedExpenseNotification({report, reportAction, movedFromReport, movedToReport, onClick, usesIcon: true, policyTags, policy, currentUserLogin}); } function clearReportNotifications(reportID: string | undefined) { diff --git a/src/libs/Notification/LocalNotification/types.ts b/src/libs/Notification/LocalNotification/types.ts index 0ed62ffda9c05..73589e7553b8c 100644 --- a/src/libs/Notification/LocalNotification/types.ts +++ b/src/libs/Notification/LocalNotification/types.ts @@ -1,6 +1,6 @@ import type {OnyxEntry} from 'react-native-onyx'; import type ClearReportNotifications from '@libs/Notification/clearReportNotifications/types'; -import type {Report, ReportAction} from '@src/types/onyx'; +import type {Policy, PolicyTagLists, Report, ReportAction} from '@src/types/onyx'; type LocalNotificationClickHandler = () => void; @@ -21,6 +21,8 @@ type LocalNotificationModifiedExpenseParams = { onClick: LocalNotificationClickHandler; movedFromReport?: OnyxEntry; movedToReport?: OnyxEntry; + policyTags: OnyxEntry; + policy?: OnyxEntry; currentUserLogin: string; }; diff --git a/src/libs/actions/Report/index.ts b/src/libs/actions/Report/index.ts index 65c295ba91476..9168a279f6180 100644 --- a/src/libs/actions/Report/index.ts +++ b/src/libs/actions/Report/index.ts @@ -203,6 +203,7 @@ import type { PolicyEmployee, PolicyEmployeeList, PolicyReportField, + PolicyTagLists, RecentlyUsedReportFields, Report, ReportAction, @@ -358,6 +359,24 @@ Onyx.connect({ }, }); +let allPolicies: OnyxCollection; +Onyx.connect({ + key: ONYXKEYS.COLLECTION.POLICY, + waitForCollectionCallback: true, + callback: (value) => { + allPolicies = value; + }, +}); + +let allPolicyTags: OnyxCollection; +Onyx.connect({ + key: ONYXKEYS.COLLECTION.POLICY_TAGS, + waitForCollectionCallback: true, + callback: (value) => { + allPolicyTags = value; + }, +}); + let allPersonalDetails: OnyxEntry = {}; Onyx.connect({ key: ONYXKEYS.PERSONAL_DETAILS_LIST, @@ -3878,9 +3897,21 @@ function showReportActionNotification(reportID: string, reportAction: ReportActi const onClick = () => close(() => navigateFromNotification(reportID)); if (reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE) { + const policyID = report.policyID; + const policyTags = policyID ? allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] : undefined; + const policy = policyID ? allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`] : undefined; const movedFromReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${getMovedReportID(reportAction, CONST.REPORT.MOVE_TYPE.FROM)}`]; const movedToReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${getMovedReportID(reportAction, CONST.REPORT.MOVE_TYPE.TO)}`]; - LocalNotification.showModifiedExpenseNotification({report, reportAction, onClick, movedFromReport, movedToReport, currentUserLogin}); + LocalNotification.showModifiedExpenseNotification({ + report, + reportAction, + onClick, + movedFromReport, + movedToReport, + policyTags, + policy, + currentUserLogin, + }); } else { LocalNotification.showCommentNotification(report, reportAction, onClick); } From 3780178e189bddcf2c8609dd54d08b7fe43939bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Le=C5=9Bniewski?= Date: Wed, 11 Mar 2026 17:00:16 +0100 Subject: [PATCH 3/9] chore: move policyTags/policy subscriptions to LocalNotification Move allPolicies and allPolicyTags Onyx.connect subscriptions from Report/index.ts into LocalNotification/index.ts so that all notification-related data fetching is co-located in one module, as requested in the PR review. showModifiedExpenseNotification now resolves policyTags/policy internally from the report's policyID. Callers no longer supply them, so policyTags/policy are removed from LocalNotificationModifiedExpenseParams and kept only in LocalNotificationModifiedExpensePushParams (internal). Co-Authored-By: Claude Sonnet 4.6 --- .../Notification/LocalNotification/index.ts | 33 +++++++++++++++++-- .../Notification/LocalNotification/types.ts | 4 +-- src/libs/actions/Report/index.ts | 33 +------------------ 3 files changed, 34 insertions(+), 36 deletions(-) diff --git a/src/libs/Notification/LocalNotification/index.ts b/src/libs/Notification/LocalNotification/index.ts index 0e69b1621db01..09a6205abeb45 100644 --- a/src/libs/Notification/LocalNotification/index.ts +++ b/src/libs/Notification/LocalNotification/index.ts @@ -1,7 +1,33 @@ -import type {Report, ReportAction} from '@src/types/onyx'; +import Onyx from 'react-native-onyx'; +import type {OnyxCollection} from 'react-native-onyx'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {Policy, PolicyTagLists, Report, ReportAction} from '@src/types/onyx'; import BrowserNotifications from './BrowserNotifications'; import type {LocalNotificationClickHandler, LocalNotificationModifiedExpenseParams, LocalNotificationModule} from './types'; +// Temporary subscriptions to resolve policy and policyTags for modified-expense notifications. +// Will be removed once the Onyx.connect migration is complete and values flow from the React layer. +// See: https://github.com/Expensify/App/issues/66336 +let allPolicies: OnyxCollection; +// eslint-disable-next-line rulesdir/no-onyx-connect -- temporary subscription for modified-expense notification; see comment above +Onyx.connect({ + key: ONYXKEYS.COLLECTION.POLICY, + waitForCollectionCallback: true, + callback: (value) => { + allPolicies = value; + }, +}); + +let allPolicyTags: OnyxCollection; +// eslint-disable-next-line rulesdir/no-onyx-connect -- temporary subscription for modified-expense notification; see comment above +Onyx.connect({ + key: ONYXKEYS.COLLECTION.POLICY_TAGS, + waitForCollectionCallback: true, + callback: (value) => { + allPolicyTags = value; + }, +}); + function showCommentNotification(report: Report, reportAction: ReportAction, onClick: LocalNotificationClickHandler) { BrowserNotifications.pushReportCommentNotification(report, reportAction, onClick, true); } @@ -10,7 +36,10 @@ function showUpdateAvailableNotification() { BrowserNotifications.pushUpdateAvailableNotification(); } -function showModifiedExpenseNotification({report, reportAction, movedFromReport, movedToReport, onClick, policyTags, policy, currentUserLogin}: LocalNotificationModifiedExpenseParams) { +function showModifiedExpenseNotification({report, reportAction, movedFromReport, movedToReport, onClick, currentUserLogin}: LocalNotificationModifiedExpenseParams) { + const policyID = report.policyID; + const policyTags = policyID ? allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] : undefined; + const policy = policyID ? allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`] : undefined; BrowserNotifications.pushModifiedExpenseNotification({report, reportAction, movedFromReport, movedToReport, onClick, usesIcon: true, policyTags, policy, currentUserLogin}); } diff --git a/src/libs/Notification/LocalNotification/types.ts b/src/libs/Notification/LocalNotification/types.ts index 73589e7553b8c..bf8e22f729f03 100644 --- a/src/libs/Notification/LocalNotification/types.ts +++ b/src/libs/Notification/LocalNotification/types.ts @@ -21,13 +21,13 @@ type LocalNotificationModifiedExpenseParams = { onClick: LocalNotificationClickHandler; movedFromReport?: OnyxEntry; movedToReport?: OnyxEntry; - policyTags: OnyxEntry; - policy?: OnyxEntry; currentUserLogin: string; }; type LocalNotificationModifiedExpensePushParams = LocalNotificationModifiedExpenseParams & { usesIcon?: boolean; + policyTags: OnyxEntry; + policy?: OnyxEntry; }; export type {LocalNotificationModule, LocalNotificationClickHandler, LocalNotificationData, LocalNotificationModifiedExpenseParams, LocalNotificationModifiedExpensePushParams}; diff --git a/src/libs/actions/Report/index.ts b/src/libs/actions/Report/index.ts index 9168a279f6180..65c295ba91476 100644 --- a/src/libs/actions/Report/index.ts +++ b/src/libs/actions/Report/index.ts @@ -203,7 +203,6 @@ import type { PolicyEmployee, PolicyEmployeeList, PolicyReportField, - PolicyTagLists, RecentlyUsedReportFields, Report, ReportAction, @@ -359,24 +358,6 @@ Onyx.connect({ }, }); -let allPolicies: OnyxCollection; -Onyx.connect({ - key: ONYXKEYS.COLLECTION.POLICY, - waitForCollectionCallback: true, - callback: (value) => { - allPolicies = value; - }, -}); - -let allPolicyTags: OnyxCollection; -Onyx.connect({ - key: ONYXKEYS.COLLECTION.POLICY_TAGS, - waitForCollectionCallback: true, - callback: (value) => { - allPolicyTags = value; - }, -}); - let allPersonalDetails: OnyxEntry = {}; Onyx.connect({ key: ONYXKEYS.PERSONAL_DETAILS_LIST, @@ -3897,21 +3878,9 @@ function showReportActionNotification(reportID: string, reportAction: ReportActi const onClick = () => close(() => navigateFromNotification(reportID)); if (reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE) { - const policyID = report.policyID; - const policyTags = policyID ? allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] : undefined; - const policy = policyID ? allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`] : undefined; const movedFromReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${getMovedReportID(reportAction, CONST.REPORT.MOVE_TYPE.FROM)}`]; const movedToReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${getMovedReportID(reportAction, CONST.REPORT.MOVE_TYPE.TO)}`]; - LocalNotification.showModifiedExpenseNotification({ - report, - reportAction, - onClick, - movedFromReport, - movedToReport, - policyTags, - policy, - currentUserLogin, - }); + LocalNotification.showModifiedExpenseNotification({report, reportAction, onClick, movedFromReport, movedToReport, currentUserLogin}); } else { LocalNotification.showCommentNotification(report, reportAction, onClick); } From 409289a26baf1741c50ad6485b567b9b2e36f73c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Le=C5=9Bniewski?= Date: Wed, 11 Mar 2026 17:04:01 +0100 Subject: [PATCH 4/9] removes comment --- src/libs/Notification/LocalNotification/index.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libs/Notification/LocalNotification/index.ts b/src/libs/Notification/LocalNotification/index.ts index 09a6205abeb45..0b23ba8e3ff73 100644 --- a/src/libs/Notification/LocalNotification/index.ts +++ b/src/libs/Notification/LocalNotification/index.ts @@ -5,9 +5,6 @@ import type {Policy, PolicyTagLists, Report, ReportAction} from '@src/types/onyx import BrowserNotifications from './BrowserNotifications'; import type {LocalNotificationClickHandler, LocalNotificationModifiedExpenseParams, LocalNotificationModule} from './types'; -// Temporary subscriptions to resolve policy and policyTags for modified-expense notifications. -// Will be removed once the Onyx.connect migration is complete and values flow from the React layer. -// See: https://github.com/Expensify/App/issues/66336 let allPolicies: OnyxCollection; // eslint-disable-next-line rulesdir/no-onyx-connect -- temporary subscription for modified-expense notification; see comment above Onyx.connect({ From 8800360fbfd50d93802f4ac27ad5fd370ceb6c58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Le=C5=9Bniewski?= Date: Wed, 11 Mar 2026 17:11:01 +0100 Subject: [PATCH 5/9] updates comments --- src/libs/Notification/LocalNotification/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/Notification/LocalNotification/index.ts b/src/libs/Notification/LocalNotification/index.ts index 0b23ba8e3ff73..6d06cbacdd886 100644 --- a/src/libs/Notification/LocalNotification/index.ts +++ b/src/libs/Notification/LocalNotification/index.ts @@ -6,7 +6,7 @@ import BrowserNotifications from './BrowserNotifications'; import type {LocalNotificationClickHandler, LocalNotificationModifiedExpenseParams, LocalNotificationModule} from './types'; let allPolicies: OnyxCollection; -// eslint-disable-next-line rulesdir/no-onyx-connect -- temporary subscription for modified-expense notification; see comment above +// eslint-disable-next-line rulesdir/no-onyx-connect -- temporary subscription for modified-expense notification; see https://github.com/Expensify/App/issues/66336 Onyx.connect({ key: ONYXKEYS.COLLECTION.POLICY, waitForCollectionCallback: true, @@ -16,7 +16,7 @@ Onyx.connect({ }); let allPolicyTags: OnyxCollection; -// eslint-disable-next-line rulesdir/no-onyx-connect -- temporary subscription for modified-expense notification; see comment above +// eslint-disable-next-line rulesdir/no-onyx-connect -- temporary subscription for modified-expense notification; see https://github.com/Expensify/App/issues/66336 Onyx.connect({ key: ONYXKEYS.COLLECTION.POLICY_TAGS, waitForCollectionCallback: true, From dfc1df1a7fcdd9c14414822229049161a5a47934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Le=C5=9Bniewski?= Date: Thu, 12 Mar 2026 16:52:04 +0100 Subject: [PATCH 6/9] use Onyx.connectWithoutView for policy/policyTags subscriptions in LocalNotification Co-Authored-By: Claude Sonnet 4.6 --- src/libs/Notification/LocalNotification/index.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libs/Notification/LocalNotification/index.ts b/src/libs/Notification/LocalNotification/index.ts index b5862dead0ddc..28f22b9e2ca38 100644 --- a/src/libs/Notification/LocalNotification/index.ts +++ b/src/libs/Notification/LocalNotification/index.ts @@ -6,8 +6,9 @@ import BrowserNotifications from './BrowserNotifications'; import type {LocalNotificationClickHandler, LocalNotificationModifiedExpenseParams, LocalNotificationModule} from './types'; let allPolicies: OnyxCollection; -// eslint-disable-next-line rulesdir/no-onyx-connect -- temporary subscription for modified-expense notification; see https://github.com/Expensify/App/issues/66336 -Onyx.connect({ +// We do not depend on updates on the UI for notifications, so we can use `connectWithoutView` here. +// This is a temporary subscription until the modified-expense notification chain is fully migrated; see https://github.com/Expensify/App/issues/66336 +Onyx.connectWithoutView({ key: ONYXKEYS.COLLECTION.POLICY, waitForCollectionCallback: true, callback: (value) => { @@ -16,8 +17,9 @@ Onyx.connect({ }); let allPolicyTags: OnyxCollection; -// eslint-disable-next-line rulesdir/no-onyx-connect -- temporary subscription for modified-expense notification; see https://github.com/Expensify/App/issues/66336 -Onyx.connect({ +// We do not depend on updates on the UI for notifications, so we can use `connectWithoutView` here. +// This is a temporary subscription until the modified-expense notification chain is fully migrated; see https://github.com/Expensify/App/issues/66336 +Onyx.connectWithoutView({ key: ONYXKEYS.COLLECTION.POLICY_TAGS, waitForCollectionCallback: true, callback: (value) => { From 54686bbd3797e07b913ed89d0f28861c7f3db412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Le=C5=9Bniewski?= Date: Thu, 12 Mar 2026 17:03:20 +0100 Subject: [PATCH 7/9] simplify pushModifiedExpenseNotification to always use getForReportActionTemp Co-Authored-By: Claude Sonnet 4.6 --- .../LocalNotification/BrowserNotifications.ts | 29 +++++++------------ .../Notification/LocalNotification/index.ts | 8 ++--- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/src/libs/Notification/LocalNotification/BrowserNotifications.ts b/src/libs/Notification/LocalNotification/BrowserNotifications.ts index b2952a629cfd7..9dbd6982ea9eb 100644 --- a/src/libs/Notification/LocalNotification/BrowserNotifications.ts +++ b/src/libs/Notification/LocalNotification/BrowserNotifications.ts @@ -5,7 +5,7 @@ import EXPENSIFY_ICON_URL from '@assets/images/expensify-logo-round-clearspace.p import * as AppUpdate from '@libs/actions/AppUpdate'; // eslint-disable-next-line @typescript-eslint/no-deprecated -- translateLocal is deprecated; BrowserNotifications is non-React code that cannot use the translate hook import {translateLocal} from '@libs/Localize'; -import {getForReportAction, getForReportActionTemp} from '@libs/ModifiedExpenseMessage'; +import {getForReportActionTemp} from '@libs/ModifiedExpenseMessage'; import {getTextFromHtml} from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; import playSound, {SOUNDS} from '@libs/Sound'; @@ -144,23 +144,16 @@ export default { currentUserLogin, }: LocalNotificationModifiedExpensePushParams) { const title = reportAction.person?.map((f) => f.text).join(', ') ?? ''; - const body = policyTags - ? getForReportActionTemp({ - // eslint-disable-next-line @typescript-eslint/no-deprecated -- translateLocal is deprecated; BrowserNotifications is non-React code that cannot use the translate hook - translate: translateLocal, - reportAction, - policy, - movedFromReport, - movedToReport, - policyTags, - currentUserLogin, - }) - : getForReportAction({ - reportAction, - policyID: report.policyID, - movedFromReport, - movedToReport, - }); + const body = getForReportActionTemp({ + // eslint-disable-next-line @typescript-eslint/no-deprecated -- translateLocal is deprecated; BrowserNotifications is non-React code that cannot use the translate hook + translate: translateLocal, + reportAction, + policy, + movedFromReport, + movedToReport, + policyTags, + currentUserLogin, + }); const icon = usesIcon ? EXPENSIFY_ICON_URL : ''; const data = { reportID: report.reportID, diff --git a/src/libs/Notification/LocalNotification/index.ts b/src/libs/Notification/LocalNotification/index.ts index 28f22b9e2ca38..fcf855898381c 100644 --- a/src/libs/Notification/LocalNotification/index.ts +++ b/src/libs/Notification/LocalNotification/index.ts @@ -6,8 +6,8 @@ import BrowserNotifications from './BrowserNotifications'; import type {LocalNotificationClickHandler, LocalNotificationModifiedExpenseParams, LocalNotificationModule} from './types'; let allPolicies: OnyxCollection; -// We do not depend on updates on the UI for notifications, so we can use `connectWithoutView` here. -// This is a temporary subscription until the modified-expense notification chain is fully migrated; see https://github.com/Expensify/App/issues/66336 +// This is a temporary subscription until the modified-expense notification chain is fully migrated +// see https://github.com/Expensify/App/issues/66336 Onyx.connectWithoutView({ key: ONYXKEYS.COLLECTION.POLICY, waitForCollectionCallback: true, @@ -17,8 +17,8 @@ Onyx.connectWithoutView({ }); let allPolicyTags: OnyxCollection; -// We do not depend on updates on the UI for notifications, so we can use `connectWithoutView` here. -// This is a temporary subscription until the modified-expense notification chain is fully migrated; see https://github.com/Expensify/App/issues/66336 +// This is a temporary subscription until the modified-expense notification chain is fully migrated +// see https://github.com/Expensify/App/issues/66336 Onyx.connectWithoutView({ key: ONYXKEYS.COLLECTION.POLICY_TAGS, waitForCollectionCallback: true, From 9ecf4c2d4535dfbbcdc45e86e6edd975a5f880c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Le=C5=9Bniewski?= Date: Thu, 12 Mar 2026 17:09:31 +0100 Subject: [PATCH 8/9] restore connectWithoutView explanation comment in LocalNotification/index.ts Co-Authored-By: Claude Sonnet 4.6 --- src/libs/Notification/LocalNotification/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/Notification/LocalNotification/index.ts b/src/libs/Notification/LocalNotification/index.ts index fcf855898381c..28f22b9e2ca38 100644 --- a/src/libs/Notification/LocalNotification/index.ts +++ b/src/libs/Notification/LocalNotification/index.ts @@ -6,8 +6,8 @@ import BrowserNotifications from './BrowserNotifications'; import type {LocalNotificationClickHandler, LocalNotificationModifiedExpenseParams, LocalNotificationModule} from './types'; let allPolicies: OnyxCollection; -// This is a temporary subscription until the modified-expense notification chain is fully migrated -// see https://github.com/Expensify/App/issues/66336 +// We do not depend on updates on the UI for notifications, so we can use `connectWithoutView` here. +// This is a temporary subscription until the modified-expense notification chain is fully migrated; see https://github.com/Expensify/App/issues/66336 Onyx.connectWithoutView({ key: ONYXKEYS.COLLECTION.POLICY, waitForCollectionCallback: true, @@ -17,8 +17,8 @@ Onyx.connectWithoutView({ }); let allPolicyTags: OnyxCollection; -// This is a temporary subscription until the modified-expense notification chain is fully migrated -// see https://github.com/Expensify/App/issues/66336 +// We do not depend on updates on the UI for notifications, so we can use `connectWithoutView` here. +// This is a temporary subscription until the modified-expense notification chain is fully migrated; see https://github.com/Expensify/App/issues/66336 Onyx.connectWithoutView({ key: ONYXKEYS.COLLECTION.POLICY_TAGS, waitForCollectionCallback: true, From b6446ae0311b87620d6a72cc7e6878482c313038 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Le=C5=9Bniewski?= Date: Thu, 12 Mar 2026 17:12:13 +0100 Subject: [PATCH 9/9] Revert "restore connectWithoutView explanation comment in LocalNotification/index.ts" This reverts commit 4d024bc1f7c3481a7bc48fac759b0a224d124c8f. --- src/libs/Notification/LocalNotification/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/Notification/LocalNotification/index.ts b/src/libs/Notification/LocalNotification/index.ts index 28f22b9e2ca38..fcf855898381c 100644 --- a/src/libs/Notification/LocalNotification/index.ts +++ b/src/libs/Notification/LocalNotification/index.ts @@ -6,8 +6,8 @@ import BrowserNotifications from './BrowserNotifications'; import type {LocalNotificationClickHandler, LocalNotificationModifiedExpenseParams, LocalNotificationModule} from './types'; let allPolicies: OnyxCollection; -// We do not depend on updates on the UI for notifications, so we can use `connectWithoutView` here. -// This is a temporary subscription until the modified-expense notification chain is fully migrated; see https://github.com/Expensify/App/issues/66336 +// This is a temporary subscription until the modified-expense notification chain is fully migrated +// see https://github.com/Expensify/App/issues/66336 Onyx.connectWithoutView({ key: ONYXKEYS.COLLECTION.POLICY, waitForCollectionCallback: true, @@ -17,8 +17,8 @@ Onyx.connectWithoutView({ }); let allPolicyTags: OnyxCollection; -// We do not depend on updates on the UI for notifications, so we can use `connectWithoutView` here. -// This is a temporary subscription until the modified-expense notification chain is fully migrated; see https://github.com/Expensify/App/issues/66336 +// This is a temporary subscription until the modified-expense notification chain is fully migrated +// see https://github.com/Expensify/App/issues/66336 Onyx.connectWithoutView({ key: ONYXKEYS.COLLECTION.POLICY_TAGS, waitForCollectionCallback: true,