diff --git a/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx index a1536c8270504..1a5a9049a2a55 100644 --- a/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx @@ -49,7 +49,7 @@ import {getTotalAmountForIOUReportPreviewButton} from '@libs/MoneyRequestReportU import Navigation from '@libs/Navigation/Navigation'; import {getConnectedIntegration, hasDynamicExternalWorkflow} from '@libs/PolicyUtils'; import {hasPendingDEWSubmit} from '@libs/ReportActionsUtils'; -import {getInvoicePayerName} from '@libs/ReportNameUtils'; +import {getInvoicePayerName, getReportName} from '@libs/ReportNameUtils'; import getReportPreviewAction from '@libs/ReportPreviewActionUtils'; import { areAllRequestsBeingSmartScanned as areAllRequestsBeingSmartScannedReportUtils, @@ -59,7 +59,6 @@ import { getMoneyRequestSpendBreakdown, getNonHeldAndFullAmount, getPolicyName, - getReportName, getReportStatusColorStyle, getReportStatusTranslation, getTransactionsWithReceipts, @@ -927,9 +926,7 @@ function MoneyRequestReportPreviewContent({ style={[styles.headerText]} testID="MoneyRequestReportPreview-reportName" > - {/* This will be fixed as follow up https://github.com/Expensify/App/pull/75357 */} - {/* eslint-disable-next-line @typescript-eslint/no-deprecated */} - {getReportName({report: iouReport, reportAttributes}) || action.childReportName} + {getReportName(iouReport, reportAttributes) || action.childReportName} diff --git a/src/components/Search/SearchAutocompleteList.tsx b/src/components/Search/SearchAutocompleteList.tsx index bb0d731f2b8e6..7f058301f3f62 100644 --- a/src/components/Search/SearchAutocompleteList.tsx +++ b/src/components/Search/SearchAutocompleteList.tsx @@ -18,6 +18,7 @@ import useFeedKeysWithAssignedCards from '@hooks/useFeedKeysWithAssignedCards'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; +import useReportAttributes from '@hooks/useReportAttributes'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; import FS from '@libs/Fullstory'; @@ -150,6 +151,7 @@ function SearchAutocompleteList({ const [betas] = useOnyx(ONYXKEYS.BETAS); const feedKeysWithCards = useFeedKeysWithAssignedCards(); + const reportAttributes = useReportAttributes(); const [draftComments] = useOnyx(ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT); const [nvpDismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING); const [recentSearches, recentSearchesMetadata] = useOnyx(ONYXKEYS.RECENT_SEARCHES); @@ -160,7 +162,6 @@ function SearchAutocompleteList({ const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const currentUserEmail = currentUserPersonalDetails.email ?? ''; const currentUserAccountID = currentUserPersonalDetails.accountID; - const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); const expensifyIcons = useMemoizedLazyExpensifyIcons(['History', 'MagnifyingGlass']); const taxRates = getAllTaxRates(policies); @@ -311,7 +312,7 @@ function SearchAutocompleteList({ autoCompleteWithSpace: false, translate, feedKeysWithCards, - conciergeReportID, + reportAttributes, }) : query, singleIcon: expensifyIcons.History, diff --git a/src/components/Search/SearchPageHeader/SearchPageHeaderInput.tsx b/src/components/Search/SearchPageHeader/SearchPageHeaderInput.tsx index f29fdb9a41c86..09fad2c2c76c8 100644 --- a/src/components/Search/SearchPageHeader/SearchPageHeaderInput.tsx +++ b/src/components/Search/SearchPageHeader/SearchPageHeaderInput.tsx @@ -25,6 +25,7 @@ import useFeedKeysWithAssignedCards from '@hooks/useFeedKeysWithAssignedCards'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; +import useReportAttributes from '@hooks/useReportAttributes'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -64,13 +65,13 @@ function SearchPageHeaderInput({queryJSON, searchRouterListVisible, hideSearchRo const personalDetails = usePersonalDetails(); const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT); const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY); + const reportAttributes = useReportAttributes(); const taxRates = useMemo(() => getAllTaxRates(policies), [policies]); const [personalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.PERSONAL_AND_WORKSPACE_CARD_LIST); const [allFeeds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER); const feedKeysWithCards = useFeedKeysWithAssignedCards(); const {inputQuery: originalInputQuery} = queryJSON; const [currentUserAccountID = -1] = useOnyx(ONYXKEYS.SESSION, {selector: accountIDSelector}); - const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED); const [betas] = useOnyx(ONYXKEYS.BETAS); const [isSelfTourViewed] = useOnyx(ONYXKEYS.NVP_ONBOARDING, {selector: hasSeenTourSelector}); @@ -86,7 +87,7 @@ function SearchPageHeaderInput({queryJSON, searchRouterListVisible, hideSearchRo autoCompleteWithSpace: true, translate, feedKeysWithCards, - conciergeReportID, + reportAttributes, }); const [searchContext] = useOnyx(ONYXKEYS.SEARCH_CONTEXT); @@ -144,10 +145,10 @@ function SearchPageHeaderInput({queryJSON, searchRouterListVisible, hideSearchRo policies, currentUserAccountID, translate, - conciergeReportID, + reportAttributes, ); setAutocompleteSubstitutions(substitutionsMap); - }, [allFeeds, personalAndWorkspaceCards, originalInputQuery, personalDetails, reports, taxRates, policies, currentUserAccountID, translate, conciergeReportID]); + }, [allFeeds, personalAndWorkspaceCards, originalInputQuery, personalDetails, reports, taxRates, policies, currentUserAccountID, translate, reportAttributes]); useEffect(() => { if (searchRouterListVisible) { diff --git a/src/components/Search/SearchRouter/buildSubstitutionsMap.ts b/src/components/Search/SearchRouter/buildSubstitutionsMap.ts index 8198bdee1a3bb..47a72df7c347a 100644 --- a/src/components/Search/SearchRouter/buildSubstitutionsMap.ts +++ b/src/components/Search/SearchRouter/buildSubstitutionsMap.ts @@ -4,7 +4,7 @@ import type {SearchAutocompleteQueryRange, SearchFilterKey} from '@components/Se import {parse} from '@libs/SearchParser/autocompleteParser'; import {getFilterDisplayValue} from '@libs/SearchQueryUtils'; import CONST from '@src/CONST'; -import type {CardFeeds, CardList, PersonalDetailsList, Policy, Report} from '@src/types/onyx'; +import type {CardFeeds, CardList, PersonalDetailsList, Policy, Report, ReportAttributesDerivedValue} from '@src/types/onyx'; import type {SubstitutionMap} from './getQueryWithSubstitutions'; const getSubstitutionsKey = (filterKey: SearchFilterKey, value: string) => `${filterKey}:${value}`; @@ -35,7 +35,7 @@ function buildSubstitutionsMap( policies: OnyxCollection, currentUserAccountID: number, translate: LocalizedTranslate, - conciergeReportID: string | undefined, + reportAttributes?: ReportAttributesDerivedValue['reports'], ): SubstitutionMap { const parsedQuery = parse(query) as {ranges: SearchAutocompleteQueryRange[]}; @@ -84,7 +84,7 @@ function buildSubstitutionsMap( policies, currentUserAccountID, translate, - conciergeReportID, + reportAttributes, }); // If displayValue === filterValue, then it means there is nothing to substitute, so we don't add any key to map diff --git a/src/hooks/useSearchTypeMenu.tsx b/src/hooks/useSearchTypeMenu.tsx index c64955cf36f50..661031911b3e1 100644 --- a/src/hooks/useSearchTypeMenu.tsx +++ b/src/hooks/useSearchTypeMenu.tsx @@ -23,6 +23,7 @@ import useFeedKeysWithAssignedCards from './useFeedKeysWithAssignedCards'; import {useMemoizedLazyExpensifyIcons} from './useLazyAsset'; import useLocalize from './useLocalize'; import useOnyx from './useOnyx'; +import useReportAttributes from './useReportAttributes'; import useSearchTypeMenuSections from './useSearchTypeMenuSections'; import useSingleExecution from './useSingleExecution'; import useTheme from './useTheme'; @@ -45,7 +46,6 @@ export default function useSearchTypeMenu(queryJSON: SearchQueryJSON) { const taxRates = getAllTaxRates(allPolicies); const [personalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.PERSONAL_AND_WORKSPACE_CARD_LIST); const [savedSearches] = useOnyx(ONYXKEYS.SAVED_SEARCHES); - const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); const [currentUserAccountID = -1] = useOnyx(ONYXKEYS.SESSION, {selector: accountIDSelector}); const [reportCounts = CONST.EMPTY_TODOS_REPORT_COUNTS] = useOnyx(ONYXKEYS.DERIVED.TODOS, {selector: todosReportCountsSelector}); const expensifyIcons = useMemoizedLazyExpensifyIcons([ @@ -70,6 +70,7 @@ export default function useSearchTypeMenu(queryJSON: SearchQueryJSON) { const [allFeeds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER); const feedKeysWithCards = useFeedKeysWithAssignedCards(); + const reportAttributes = useReportAttributes(); const flattenedMenuItems = useMemo(() => typeMenuSections.flatMap((section) => section.menuItems), [typeMenuSections]); // this is a performance fix, rendering popover menu takes a lot of time and we don't need this component initially, that's why we postpone rendering it until everything else is rendered @@ -116,7 +117,7 @@ export default function useSearchTypeMenu(queryJSON: SearchQueryJSON) { autoCompleteWithSpace: false, translate, feedKeysWithCards, - conciergeReportID, + reportAttributes, }); } @@ -166,11 +167,11 @@ export default function useSearchTypeMenu(queryJSON: SearchQueryJSON) { taxRates, personalAndWorkspaceCards, allFeeds, - feedKeysWithCards, allPolicies, currentUserAccountID, translate, - conciergeReportID, + feedKeysWithCards, + reportAttributes, ]); const activeItemIndex = useMemo(() => { diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts index 36c4f13803f78..63a7c061aa7db 100644 --- a/src/libs/ModifiedExpenseMessage.ts +++ b/src/libs/ModifiedExpenseMessage.ts @@ -4,7 +4,7 @@ import type {Entries, ValueOf} from 'type-fest'; import type {LocalizedTranslate} from '@components/LocaleContextProvider'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; -import type {Policy, PolicyTagLists, Report, ReportAction} from '@src/types/onyx'; +import type {Policy, PolicyTagLists, Report, ReportAction, ReportAttributesDerivedValue} from '@src/types/onyx'; import type {PersonalRulesModifiedFields, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage'; import ObjectUtils from '@src/types/utils/ObjectUtils'; import {getDecodedCategoryName, isCategoryMissing} from './CategoryUtils'; @@ -21,9 +21,9 @@ import {getOriginalMessage, isModifiedExpenseAction} from './ReportActionsUtils' // The functions imported here are pure utility functions that don't create initialization-time dependencies. // ReportNameUtils imports helper functions from ReportUtils, and ReportUtils imports name generation functions from ReportNameUtils. // eslint-disable-next-line import/no-cycle -import {buildReportNameFromParticipantNames, getPolicyExpenseChatName} from './ReportNameUtils'; +import {buildReportNameFromParticipantNames, getPolicyExpenseChatName, getReportName} from './ReportNameUtils'; // eslint-disable-next-line import/no-cycle -import {getPolicyName, getReportName, getRootParentReport, isPolicyExpenseChat, isSelfDM} from './ReportUtils'; +import {getPolicyName, getRootParentReport, isPolicyExpenseChat, isSelfDM} from './ReportUtils'; import {getFormattedAttendees, getTagArrayFromName} from './TransactionUtils'; import {isInvalidMerchantValue} from './ValidationUtils'; @@ -165,16 +165,14 @@ function getMovedFromOrToReportMessage( movedFromReport: OnyxEntry | undefined, movedToReport: OnyxEntry | undefined, currentUserLogin: string, - // TODO: This will be required eventually. Refactor issue: https://github.com/Expensify/App/issues/66411 - conciergeReportID?: string, + reportAttributes?: ReportAttributesDerivedValue['reports'], ): string | undefined { if (movedToReport) { return getForExpenseMovedFromSelfDM(translate, movedToReport, currentUserLogin); } if (movedFromReport) { - // eslint-disable-next-line @typescript-eslint/no-deprecated - const originReportName = getReportName({report: movedFromReport, conciergeReportID}); + const originReportName = getReportName(movedFromReport, reportAttributes); return translate('iou.movedFromReport', originReportName ?? ''); } } @@ -253,7 +251,7 @@ function getForReportAction({ movedToReport, policyTags, currentUserLogin, - conciergeReportID, + reportAttributes, }: { translate: LocalizedTranslate; reportAction: OnyxEntry; @@ -265,14 +263,13 @@ function getForReportAction({ // See https://github.com/Expensify/App/pull/75562 policyTags?: OnyxEntry; currentUserLogin: string; - // TODO: This will be required eventually. Refactor issue: https://github.com/Expensify/App/issues/66411 - conciergeReportID?: string; + reportAttributes?: ReportAttributesDerivedValue['reports']; }): string { if (!isModifiedExpenseAction(reportAction)) { return ''; } - const movedFromOrToReportMessage = getMovedFromOrToReportMessage(translate, movedFromReport, movedToReport, currentUserLogin, conciergeReportID); + const movedFromOrToReportMessage = getMovedFromOrToReportMessage(translate, movedFromReport, movedToReport, currentUserLogin, reportAttributes); if (movedFromOrToReportMessage) { return movedFromOrToReportMessage; } diff --git a/src/libs/Navigation/AppNavigator/AuthScreensInitHandler.tsx b/src/libs/Navigation/AppNavigator/AuthScreensInitHandler.tsx index cf70df6c456c6..765c9f1ad66ed 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreensInitHandler.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreensInitHandler.tsx @@ -3,6 +3,7 @@ import {useEffect, useRef} from 'react'; import {useInitialURLActions, useInitialURLState} from '@components/InitialURLContextProvider'; import useHasActiveAdminPolicies from '@hooks/useHasActiveAdminPolicies'; import useOnyx from '@hooks/useOnyx'; +import useReportAttributes from '@hooks/useReportAttributes'; import {init, isClientTheLeader} from '@libs/ActiveClientManager'; import Log from '@libs/Log'; import getCurrentUrl from '@libs/Navigation/currentUrl'; @@ -23,15 +24,15 @@ import CONFIG from '@src/CONFIG'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; +import type {ReportAttributesDerivedValue} from '@src/types/onyx'; -function initializePusher(conciergeReportID: string | undefined, currentUserAccountID?: number) { +function initializePusher(currentUserAccountID?: number, getReportAttributes?: () => ReportAttributesDerivedValue['reports'] | undefined) { return Pusher.init({ appKey: CONFIG.PUSHER.APP_KEY, cluster: CONFIG.PUSHER.CLUSTER, authEndpoint: `${CONFIG.EXPENSIFY.DEFAULT_API_ROOT}api/AuthenticatePusher?`, }).then(() => { - User.subscribeToUserEvents(currentUserAccountID ?? CONST.DEFAULT_NUMBER_ID, conciergeReportID); + User.subscribeToUserEvents(currentUserAccountID ?? CONST.DEFAULT_NUMBER_ID, getReportAttributes); }); } @@ -60,13 +61,17 @@ function AuthScreensInitHandler() { const [lastUpdateIDAppliedToClient] = useOnyx(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT); const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP); - const [conciergeReportID, conciergeReportIDMetadata] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); const lastUpdateIDAppliedToClientRef = useRef(lastUpdateIDAppliedToClient); const isLoadingAppRef = useRef(isLoadingApp); lastUpdateIDAppliedToClientRef.current = lastUpdateIDAppliedToClient; isLoadingAppRef.current = isLoadingApp; + const reportAttributes = useReportAttributes(); + // We use a ref so the Pusher callback (registered once on mount) always reads the latest value without re-subscribing. + const reportAttributesRef = useRef(reportAttributes); + reportAttributesRef.current = reportAttributes; + const handleNetworkReconnect = () => { if (isLoadingAppRef.current) { App.openApp(); @@ -80,12 +85,9 @@ function AuthScreensInitHandler() { if (!Navigation.isActiveRoute(ROUTES.SIGN_IN_MODAL)) { return; } - if (isLoadingOnyxValue(conciergeReportIDMetadata)) { - return; - } // This means sign in in RHP was successful, so we can subscribe to user events - initializePusher(conciergeReportID, session?.accountID); - }, [session?.accountID, conciergeReportID, conciergeReportIDMetadata]); + initializePusher(session?.accountID, () => reportAttributesRef.current); + }, [session?.accountID]); useEffect(() => { const isLoggingInAsNewUser = !!session?.email && SessionUtils.isLoggingInAsNewUser(currentUrl, session.email); @@ -107,7 +109,8 @@ function AuthScreensInitHandler() { parentSpan: getSpan(CONST.TELEMETRY.SPAN_BOOTSPLASH.ROOT), }); PusherConnectionManager.init(); - initializePusher(conciergeReportID, session?.accountID).finally(() => { + + initializePusher(session?.accountID, () => reportAttributesRef.current).finally(() => { endSpan(CONST.TELEMETRY.SPAN_NAVIGATION.PUSHER_INIT); }); diff --git a/src/libs/Notification/LocalNotification/BrowserNotifications.ts b/src/libs/Notification/LocalNotification/BrowserNotifications.ts index dc2fe2ffe3315..35d6780a522b7 100644 --- a/src/libs/Notification/LocalNotification/BrowserNotifications.ts +++ b/src/libs/Notification/LocalNotification/BrowserNotifications.ts @@ -7,9 +7,10 @@ import * as AppUpdate from '@libs/actions/AppUpdate'; import {translateLocal} from '@libs/Localize'; import {getForReportAction} from '@libs/ModifiedExpenseMessage'; import {getTextFromHtml} from '@libs/ReportActionsUtils'; +import {getReportName} from '@libs/ReportNameUtils'; import * as ReportUtils from '@libs/ReportUtils'; import playSound, {SOUNDS} from '@libs/Sound'; -import type {Report, ReportAction} from '@src/types/onyx'; +import type {Report, ReportAction, ReportAttributesDerivedValue} from '@src/types/onyx'; import SafeString from '@src/utils/SafeString'; import type {LocalNotificationClickHandler, LocalNotificationData, LocalNotificationModifiedExpensePushParams} from './types'; @@ -96,7 +97,13 @@ export default { * * @param usesIcon true if notification uses right circular icon */ - pushReportCommentNotification(report: Report, reportAction: ReportAction, onClick: LocalNotificationClickHandler, conciergeReportID: string | undefined, usesIcon = false) { + pushReportCommentNotification( + report: Report, + reportAction: ReportAction, + onClick: LocalNotificationClickHandler, + usesIcon = false, + reportAttributes?: ReportAttributesDerivedValue['reports'], + ) { let title; let body; const icon = usesIcon ? EXPENSIFY_ICON_URL : ''; @@ -115,9 +122,7 @@ export default { } if (isRoomOrGroupChat) { - // Will be fixed in https://github.com/Expensify/App/issues/76852 - // eslint-disable-next-line @typescript-eslint/no-deprecated - const roomName = ReportUtils.getReportName({report, conciergeReportID}); + const roomName = getReportName(report, reportAttributes); title = roomName; body = `${plainTextPerson}: ${plainTextMessage}`; } else { @@ -142,7 +147,7 @@ export default { policyTags, policy, currentUserLogin, - conciergeReportID, + reportAttributes, }: LocalNotificationModifiedExpensePushParams) { const title = reportAction.person?.map((f) => f.text).join(', ') ?? ''; const bodyWithHTML = getForReportAction({ @@ -154,7 +159,7 @@ export default { movedToReport, policyTags, currentUserLogin, - conciergeReportID, + reportAttributes, }); // Strip HTML tags for plain text notification body const body = getTextFromHtml(bodyWithHTML); diff --git a/src/libs/Notification/LocalNotification/index.ts b/src/libs/Notification/LocalNotification/index.ts index a398ad1238bcd..ad915ebecce6c 100644 --- a/src/libs/Notification/LocalNotification/index.ts +++ b/src/libs/Notification/LocalNotification/index.ts @@ -1,7 +1,7 @@ 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 type {Policy, PolicyTagLists, Report, ReportAction, ReportAttributesDerivedValue} from '@src/types/onyx'; import BrowserNotifications from './BrowserNotifications'; import type {LocalNotificationClickHandler, LocalNotificationModifiedExpenseParams, LocalNotificationModule} from './types'; @@ -27,15 +27,15 @@ Onyx.connectWithoutView({ }, }); -function showCommentNotification(report: Report, reportAction: ReportAction, onClick: LocalNotificationClickHandler, conciergeReportID: string | undefined) { - BrowserNotifications.pushReportCommentNotification(report, reportAction, onClick, conciergeReportID, true); +function showCommentNotification(report: Report, reportAction: ReportAction, onClick: LocalNotificationClickHandler, reportAttributes?: ReportAttributesDerivedValue['reports']) { + BrowserNotifications.pushReportCommentNotification(report, reportAction, onClick, true, reportAttributes); } function showUpdateAvailableNotification() { BrowserNotifications.pushUpdateAvailableNotification(); } -function showModifiedExpenseNotification({report, reportAction, movedFromReport, movedToReport, onClick, currentUserLogin, conciergeReportID}: LocalNotificationModifiedExpenseParams) { +function showModifiedExpenseNotification({report, reportAction, movedFromReport, movedToReport, onClick, currentUserLogin, reportAttributes}: LocalNotificationModifiedExpenseParams) { const policyID = report.policyID; const policyTags = policyID ? allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] : undefined; const policy = policyID ? allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`] : undefined; @@ -49,7 +49,7 @@ function showModifiedExpenseNotification({report, reportAction, movedFromReport, policyTags, policy, currentUserLogin, - conciergeReportID, + reportAttributes, }); } diff --git a/src/libs/Notification/LocalNotification/types.ts b/src/libs/Notification/LocalNotification/types.ts index dd701cb5ae45c..321550b06a88e 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 {Policy, PolicyTagLists, Report, ReportAction} from '@src/types/onyx'; +import type {Policy, PolicyTagLists, Report, ReportAction, ReportAttributesDerivedValue} from '@src/types/onyx'; type LocalNotificationClickHandler = () => void; @@ -9,7 +9,7 @@ type LocalNotificationData = { }; type LocalNotificationModule = { - showCommentNotification: (report: Report, reportAction: ReportAction, onClick: LocalNotificationClickHandler, conciergeReportID: string | undefined) => void; + showCommentNotification: (report: Report, reportAction: ReportAction, onClick: LocalNotificationClickHandler, reportAttributes?: ReportAttributesDerivedValue['reports']) => void; showUpdateAvailableNotification: () => void; showModifiedExpenseNotification: (params: LocalNotificationModifiedExpenseParams) => void; clearReportNotifications: ClearReportNotifications; @@ -22,7 +22,7 @@ type LocalNotificationModifiedExpenseParams = { movedFromReport?: OnyxEntry; movedToReport?: OnyxEntry; currentUserLogin: string; - conciergeReportID: string | undefined; + reportAttributes?: ReportAttributesDerivedValue['reports']; }; type LocalNotificationModifiedExpensePushParams = LocalNotificationModifiedExpenseParams & { diff --git a/src/libs/SearchQueryUtils.ts b/src/libs/SearchQueryUtils.ts index be605786ad38e..c1e0351ec76f0 100644 --- a/src/libs/SearchQueryUtils.ts +++ b/src/libs/SearchQueryUtils.ts @@ -44,7 +44,7 @@ import navigationRef from './Navigation/navigationRef'; import type {SearchFullscreenNavigatorParamList} from './Navigation/types'; import {getDisplayNameOrDefault, getPersonalDetailByEmail} from './PersonalDetailsUtils'; import {getCleanedTagName} from './PolicyUtils'; -import {getReportName} from './ReportUtils'; +import {getReportName} from './ReportNameUtils'; import {parse as parseSearchQuery} from './SearchParser/searchParser'; import StringUtils from './StringUtils'; import {hashText} from './UserUtils'; @@ -1108,7 +1108,7 @@ type GetFilterDisplayValueParams = { policies: OnyxCollection; currentUserAccountID: number; translate: LocalizedTranslate; - conciergeReportID: string | undefined; + reportAttributes?: OnyxTypes.ReportAttributesDerivedValue['reports']; feedKeysWithCards?: FeedKeysWithAssignedCards; }; @@ -1125,7 +1125,7 @@ function getFilterDisplayValue({ policies, currentUserAccountID, translate, - conciergeReportID, + reportAttributes, feedKeysWithCards, }: GetFilterDisplayValueParams) { if ( @@ -1146,8 +1146,7 @@ function getFilterDisplayValue({ return getCardDescription(cardList?.[cardID], translate) || filterValue; } if (filterName === CONST.SEARCH.SYNTAX_FILTER_KEYS.IN) { - // eslint-disable-next-line @typescript-eslint/no-deprecated - return getReportName({report: reports?.[`${ONYXKEYS.COLLECTION.REPORT}${filterValue}`], conciergeReportID}) || filterValue; + return getReportName(reports?.[`${ONYXKEYS.COLLECTION.REPORT}${filterValue}`], reportAttributes) || filterValue; } if (filterName === CONST.SEARCH.SYNTAX_FILTER_KEYS.AMOUNT || filterName === CONST.SEARCH.SYNTAX_FILTER_KEYS.TOTAL || filterName === CONST.SEARCH.SYNTAX_FILTER_KEYS.PURCHASE_AMOUNT) { const frontendAmount = convertToFrontendAmountAsInteger(Number(filterValue)); @@ -1187,7 +1186,7 @@ function getDisplayQueryFiltersForKey( policies: OnyxCollection, currentUserAccountID: number, translate: LocalizedTranslate, - conciergeReportID: string | undefined, + reportAttributes?: OnyxTypes.ReportAttributesDerivedValue['reports'], feedKeysWithCards?: FeedKeysWithAssignedCards, ) { if (key === CONST.SEARCH.SYNTAX_FILTER_KEYS.TAX_RATE) { @@ -1253,7 +1252,7 @@ function getDisplayQueryFiltersForKey( policies, currentUserAccountID, translate, - conciergeReportID, + reportAttributes, feedKeysWithCards, }), })); @@ -1333,7 +1332,7 @@ function buildUserReadableQueryString({ autoCompleteWithSpace = false, translate, feedKeysWithCards, - conciergeReportID, + reportAttributes, }: { queryJSON: SearchQueryJSON; PersonalDetails: OnyxTypes.PersonalDetailsList | undefined; @@ -1346,7 +1345,7 @@ function buildUserReadableQueryString({ autoCompleteWithSpace: boolean; translate: LocalizedTranslate; feedKeysWithCards?: FeedKeysWithAssignedCards; - conciergeReportID: string | undefined; + reportAttributes?: OnyxTypes.ReportAttributesDerivedValue['reports']; }) { const {type, status, groupBy, columns, policyID, rawFilterList, flatFilters: filters = [], limit} = queryJSON; @@ -1390,7 +1389,7 @@ function buildUserReadableQueryString({ policies, currentUserAccountID, translate, - conciergeReportID, + reportAttributes, feedKeysWithCards, ); @@ -1440,7 +1439,7 @@ function buildUserReadableQueryString({ policies, currentUserAccountID, translate, - conciergeReportID, + reportAttributes, feedKeysWithCards, ); diff --git a/src/libs/actions/Report/index.ts b/src/libs/actions/Report/index.ts index 2666ccd2b3739..9e9bfe0c08ea6 100644 --- a/src/libs/actions/Report/index.ts +++ b/src/libs/actions/Report/index.ts @@ -209,6 +209,7 @@ import type { Report, ReportAction, ReportActionReactions, + ReportAttributesDerivedValue, ReportNextStepDeprecated, ReportUserIsTyping, ReportViolations, @@ -4093,7 +4094,13 @@ function shouldShowReportActionNotification(reportID: string, currentUserAccount return true; } -function showReportActionNotification(reportID: string, reportAction: ReportAction, currentUserAccountID: number, currentUserLogin: string, conciergeReportID: string | undefined) { +function showReportActionNotification( + reportID: string, + reportAction: ReportAction, + currentUserAccountID: number, + currentUserLogin: string, + reportAttributes?: ReportAttributesDerivedValue['reports'], +) { if (!shouldShowReportActionNotification(reportID, currentUserAccountID, reportAction)) { return; } @@ -4112,9 +4119,9 @@ function showReportActionNotification(reportID: string, reportAction: ReportActi if (reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE) { 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, conciergeReportID}); + LocalNotification.showModifiedExpenseNotification({report, reportAction, onClick, movedFromReport, movedToReport, currentUserLogin, reportAttributes}); } else { - LocalNotification.showCommentNotification(report, reportAction, onClick, conciergeReportID); + LocalNotification.showCommentNotification(report, reportAction, onClick, reportAttributes); } notifyNewAction(reportID, undefined, reportAction.actorAccountID === currentUserAccountID); diff --git a/src/libs/actions/Task.ts b/src/libs/actions/Task.ts index 28901436b3d0e..bb6ff2313b4d5 100644 --- a/src/libs/actions/Task.ts +++ b/src/libs/actions/Task.ts @@ -14,6 +14,7 @@ import NetworkConnection from '@libs/NetworkConnection'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; +import {getReportName} from '@libs/ReportNameUtils'; import * as ReportUtils from '@libs/ReportUtils'; import {buildOptimisticSnapshotData} from '@libs/SearchQueryUtils'; import playSound, {SOUNDS} from '@libs/Sound'; @@ -1073,7 +1074,7 @@ function getShareDestination( reports: OnyxCollection, personalDetails: OnyxEntry, localeCompare: LocaleContextProps['localeCompare'], - conciergeReportID: string | undefined, + reportAttributes?: OnyxTypes.ReportAttributesDerivedValue['reports'], ): ShareDestination { const report = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]; @@ -1101,9 +1102,7 @@ function getShareDestination( } return { icons: ReportUtils.getIcons(report, LocalePhoneNumber.formatPhoneNumber, personalDetails, Expensicons.FallbackAvatar), - // Will be fixed in https://github.com/Expensify/App/issues/76852 - // eslint-disable-next-line @typescript-eslint/no-deprecated - displayName: ReportUtils.getReportName({report, conciergeReportID}), + displayName: getReportName(report, reportAttributes), subtitle, displayNamesWithTooltips, shouldUseFullTitleToDisplay: ReportUtils.shouldUseFullTitleToDisplay(report), diff --git a/src/libs/actions/User.ts b/src/libs/actions/User.ts index 3bd9d0163795b..5775ba05bbedf 100644 --- a/src/libs/actions/User.ts +++ b/src/libs/actions/User.ts @@ -49,7 +49,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {ExpenseRuleForm, MerchantRuleForm} from '@src/types/form'; -import type {AppReview, BlockedFromConcierge, CustomStatusDraft, ExpenseRule, Policy} from '@src/types/onyx'; +import type {AppReview, BlockedFromConcierge, CustomStatusDraft, ExpenseRule, Policy, ReportAttributesDerivedValue} from '@src/types/onyx'; import type Login from '@src/types/onyx/Login'; import type {Errors} from '@src/types/onyx/OnyxCommon'; import type {AnyOnyxServerUpdate, OnyxServerUpdate, OnyxUpdateEvent} from '@src/types/onyx/OnyxUpdatesFromServer'; @@ -614,7 +614,11 @@ function isBlockedFromConcierge(blockedFromConciergeNVP: OnyxEntry(onyxUpdates: Array>, currentUserAccountIDParam: number, conciergeReportID: string | undefined) { +function triggerNotifications( + onyxUpdates: Array>, + currentUserAccountIDParam: number, + reportAttributes?: ReportAttributesDerivedValue['reports'], +) { for (const update of onyxUpdates) { if (!update.shouldNotify && !update.shouldShowPushNotification) { continue; @@ -626,7 +630,7 @@ function triggerNotifications(onyxUpdates: Array ReportAttributesDerivedValue['reports'] | undefined) { // If we don't have the user's accountID yet (because the app isn't fully setup yet) we can't subscribe so return early if (!currentUserAccountIDParam) { return; @@ -908,7 +912,7 @@ function subscribeToUserEvents(currentUserAccountIDParam: number, conciergeRepor } const onyxUpdatePromise = Onyx.update(pushJSON).then(() => { - triggerNotifications(pushJSON, currentUserAccountIDParam, conciergeReportID); + triggerNotifications(pushJSON, currentUserAccountIDParam, getReportAttributes?.()); }); // Return a promise when Onyx is done updating so that the OnyxUpdatesManager can properly apply all diff --git a/src/pages/Search/SavedSearchList.tsx b/src/pages/Search/SavedSearchList.tsx index b2776e0906902..9be2d7997ecfc 100644 --- a/src/pages/Search/SavedSearchList.tsx +++ b/src/pages/Search/SavedSearchList.tsx @@ -10,6 +10,7 @@ import useFeedKeysWithAssignedCards from '@hooks/useFeedKeysWithAssignedCards'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; +import useReportAttributes from '@hooks/useReportAttributes'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; import {setSearchContext} from '@libs/actions/Search'; @@ -45,7 +46,7 @@ function SavedSearchList({hash}: SavedSearchListProps) { const [allFeeds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER); const feedKeysWithCards = useFeedKeysWithAssignedCards(); const [currentUserAccountID = -1] = useOnyx(ONYXKEYS.SESSION, {selector: accountIDSelector}); - const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); + const reportAttributes = useReportAttributes(); const {showDeleteModal} = useDeleteSavedSearch(); const { @@ -77,7 +78,7 @@ function SavedSearchList({hash}: SavedSearchListProps) { autoCompleteWithSpace: false, translate, feedKeysWithCards, - conciergeReportID, + reportAttributes, }); } diff --git a/src/pages/tasks/NewTaskPage.tsx b/src/pages/tasks/NewTaskPage.tsx index 265b7f607bd7d..3a880fb6b9888 100644 --- a/src/pages/tasks/NewTaskPage.tsx +++ b/src/pages/tasks/NewTaskPage.tsx @@ -13,6 +13,7 @@ import useAncestors from '@hooks/useAncestors'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; +import useReportAttributes from '@hooks/useReportAttributes'; import useSafeAreaPaddings from '@hooks/useSafeAreaPaddings'; import useThemeStyles from '@hooks/useThemeStyles'; import blurActiveElement from '@libs/Accessibility/blurActiveElement'; @@ -35,7 +36,7 @@ function NewTaskPage({route}: NewTaskPageProps) { const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT); const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST); const [quickAction] = useOnyx(ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE); - const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); + const reportAttributes = useReportAttributes(); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const styles = useThemeStyles(); const {translate, formatPhoneNumber, localeCompare} = useLocalize(); @@ -46,7 +47,7 @@ function NewTaskPage({route}: NewTaskPageProps) { localeCompare, formatPhoneNumber, ); - const shareDestination = task?.shareDestination ? getShareDestination(task.shareDestination, reports, personalDetails, localeCompare, conciergeReportID) : undefined; + const shareDestination = task?.shareDestination ? getShareDestination(task.shareDestination, reports, personalDetails, localeCompare, reportAttributes) : undefined; const parentReport = task?.shareDestination ? reports?.[`${ONYXKEYS.COLLECTION.REPORT}${task.shareDestination}`] : undefined; const ancestors = useAncestors(parentReport); const taskKey = `${task?.assignee}|${task?.assigneeAccountID}|${task?.description}|${task?.parentReportID}|${task?.shareDestination}|${task?.title}`; diff --git a/tests/actions/ReportTest.ts b/tests/actions/ReportTest.ts index 6fb84b2d77e80..2793dae83b75e 100644 --- a/tests/actions/ReportTest.ts +++ b/tests/actions/ReportTest.ts @@ -873,158 +873,6 @@ describe('actions/Report', () => { }); }); - it('should pass conciergeReportID through to showReportActionNotification when provided', () => { - const TEST_USER_ACCOUNT_ID = 1; - const TEST_USER_LOGIN = 'test@user.com'; - const REPORT_ID = '1'; - const CONCIERGE_REPORT_ID = '42'; - const REPORT_ACTION = { - actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, - }; - - return TestHelper.signInWithTestUser(TEST_USER_ACCOUNT_ID) - .then(waitForBatchedUpdates) - .then(() => { - User.subscribeToUserEvents(TEST_USER_ACCOUNT_ID, CONCIERGE_REPORT_ID); - return waitForBatchedUpdates(); - }) - .then(() => { - PusherHelper.emitOnyxUpdate([ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${REPORT_ID}`, - value: { - 1: REPORT_ACTION, - }, - shouldNotify: true, - }, - ]); - return SequentialQueue.getCurrentRequest().then(waitForBatchedUpdates); - }) - .then(() => { - expect(Report.showReportActionNotification).toBeCalledWith(REPORT_ID, REPORT_ACTION, TEST_USER_ACCOUNT_ID, TEST_USER_LOGIN, CONCIERGE_REPORT_ID); - }); - }); - - it('should pass conciergeReportID through when using shouldShowPushNotification flag', () => { - const TEST_USER_ACCOUNT_ID = 1; - const TEST_USER_LOGIN = 'test@user.com'; - const REPORT_ID = '1'; - const CONCIERGE_REPORT_ID = '99'; - const REPORT_ACTION = { - actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, - }; - - return TestHelper.signInWithTestUser(TEST_USER_ACCOUNT_ID) - .then(waitForBatchedUpdates) - .then(() => { - User.subscribeToUserEvents(TEST_USER_ACCOUNT_ID, CONCIERGE_REPORT_ID); - return waitForBatchedUpdates(); - }) - .then(() => { - PusherHelper.emitOnyxUpdate([ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${REPORT_ID}`, - value: { - 1: REPORT_ACTION, - }, - shouldShowPushNotification: true, - }, - ]); - return SequentialQueue.getCurrentRequest().then(waitForBatchedUpdates); - }) - .then(() => { - expect(Report.showReportActionNotification).toBeCalledWith(REPORT_ID, REPORT_ACTION, TEST_USER_ACCOUNT_ID, TEST_USER_LOGIN, CONCIERGE_REPORT_ID); - }); - }); - - it('should pass conciergeReportID for multiple report actions across different reports', () => { - const TEST_USER_ACCOUNT_ID = 1; - const TEST_USER_LOGIN = 'test@user.com'; - const REPORT_ID_1 = '1'; - const REPORT_ID_2 = '2'; - const CONCIERGE_REPORT_ID = '55'; - const REPORT_ACTION_1 = { - actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, - }; - const REPORT_ACTION_2 = { - actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, - }; - - return TestHelper.signInWithTestUser(TEST_USER_ACCOUNT_ID) - .then(waitForBatchedUpdates) - .then(() => { - User.subscribeToUserEvents(TEST_USER_ACCOUNT_ID, CONCIERGE_REPORT_ID); - return waitForBatchedUpdates(); - }) - .then(() => { - PusherHelper.emitOnyxUpdate([ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${REPORT_ID_1}`, - value: { - 1: REPORT_ACTION_1, - }, - shouldNotify: true, - }, - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${REPORT_ID_2}`, - value: { - 2: REPORT_ACTION_2, - }, - shouldNotify: true, - }, - ]); - return SequentialQueue.getCurrentRequest().then(waitForBatchedUpdates); - }) - .then(() => { - expect(Report.showReportActionNotification).toHaveBeenCalledTimes(2); - expect(Report.showReportActionNotification).toHaveBeenCalledWith(REPORT_ID_1, REPORT_ACTION_1, TEST_USER_ACCOUNT_ID, TEST_USER_LOGIN, CONCIERGE_REPORT_ID); - expect(Report.showReportActionNotification).toHaveBeenCalledWith(REPORT_ID_2, REPORT_ACTION_2, TEST_USER_ACCOUNT_ID, TEST_USER_LOGIN, CONCIERGE_REPORT_ID); - }); - }); - - it('should pass conciergeReportID for multiple actions within a single report update', () => { - const TEST_USER_ACCOUNT_ID = 1; - const TEST_USER_LOGIN = 'test@user.com'; - const REPORT_ID = '1'; - const CONCIERGE_REPORT_ID = '77'; - const REPORT_ACTION_1 = { - actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, - }; - const REPORT_ACTION_2 = { - actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, - }; - - return TestHelper.signInWithTestUser(TEST_USER_ACCOUNT_ID) - .then(waitForBatchedUpdates) - .then(() => { - User.subscribeToUserEvents(TEST_USER_ACCOUNT_ID, CONCIERGE_REPORT_ID); - return waitForBatchedUpdates(); - }) - .then(() => { - PusherHelper.emitOnyxUpdate([ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${REPORT_ID}`, - value: { - 1: REPORT_ACTION_1, - 2: REPORT_ACTION_2, - }, - shouldNotify: true, - }, - ]); - return SequentialQueue.getCurrentRequest().then(waitForBatchedUpdates); - }) - .then(() => { - expect(Report.showReportActionNotification).toHaveBeenCalledTimes(2); - expect(Report.showReportActionNotification).toHaveBeenCalledWith(REPORT_ID, REPORT_ACTION_1, TEST_USER_ACCOUNT_ID, TEST_USER_LOGIN, CONCIERGE_REPORT_ID); - expect(Report.showReportActionNotification).toHaveBeenCalledWith(REPORT_ID, REPORT_ACTION_2, TEST_USER_ACCOUNT_ID, TEST_USER_LOGIN, CONCIERGE_REPORT_ID); - }); - }); - it('should properly toggle reactions on a message', () => { global.fetch = TestHelper.getGlobalFetchMock(); diff --git a/tests/ui/AuthScreensInitHandlerTest.tsx b/tests/ui/AuthScreensInitHandlerTest.tsx index dd1797b795e3c..9d91971869274 100644 --- a/tests/ui/AuthScreensInitHandlerTest.tsx +++ b/tests/ui/AuthScreensInitHandlerTest.tsx @@ -14,6 +14,7 @@ import {signOutAndRedirectToSignIn} from '@userActions/Session'; import {subscribeToUserEvents} from '@userActions/User'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import type {ReportAttributesDerivedValue} from '@src/types/onyx'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; import waitForBatchedUpdatesWithAct from '../utils/waitForBatchedUpdatesWithAct'; import wrapOnyxWithWaitForBatchedUpdates from '../utils/wrapOnyxWithWaitForBatchedUpdates'; @@ -150,57 +151,59 @@ describe('AuthScreensInitHandler', () => { await waitForBatchedUpdates(); }); - it('passes conciergeReportID to subscribeToUserEvents on mount', async () => { - const conciergeReportID = '12345'; - + it('calls subscribeToUserEvents with a getter function on mount', async () => { await Onyx.merge(ONYXKEYS.SESSION, {accountID: TEST_ACCOUNT_ID, email: 'test@test.com'}); - await Onyx.merge(ONYXKEYS.CONCIERGE_REPORT_ID, conciergeReportID); await waitForBatchedUpdates(); renderAuthScreensInitHandler(); await waitForBatchedUpdatesWithAct(); expect(mockedPusherInit).toHaveBeenCalled(); - expect(subscribeToUserEvents).toHaveBeenCalledWith(TEST_ACCOUNT_ID, conciergeReportID); + expect(subscribeToUserEvents).toHaveBeenCalledWith(TEST_ACCOUNT_ID, expect.any(Function)); }); - it('calls initializePusher when SIGN_IN_MODAL is active and conciergeReportID is loaded', async () => { + it('calls subscribeToUserEvents from sign-in modal effect when SIGN_IN_MODAL is active', async () => { mockedIsActiveRoute.mockReturnValue(true); - const conciergeReportID = '67890'; - await Onyx.merge(ONYXKEYS.SESSION, {accountID: TEST_ACCOUNT_ID, email: 'test@test.com'}); - await Onyx.merge(ONYXKEYS.CONCIERGE_REPORT_ID, conciergeReportID); await waitForBatchedUpdates(); renderAuthScreensInitHandler(); await waitForBatchedUpdatesWithAct(); - // subscribeToUserEvents should be called with conciergeReportID from both mount and sign-in modal effects - expect(subscribeToUserEvents).toHaveBeenCalledWith(TEST_ACCOUNT_ID, conciergeReportID); + // Both mount effect AND sign-in modal effect fire → 2 calls + expect(subscribeToUserEvents).toHaveBeenCalledTimes(2); + expect(subscribeToUserEvents).toHaveBeenCalledWith(TEST_ACCOUNT_ID, expect.any(Function)); }); - it('does not call initializePusher from sign-in modal effect when conciergeReportID is still loading', async () => { - mockedIsActiveRoute.mockReturnValue(true); + it('getter passed to subscribeToUserEvents returns report attributes when available', async () => { + const mockReports = {testReport: {reportName: 'Test Report'}} as unknown as ReportAttributesDerivedValue['reports']; await Onyx.merge(ONYXKEYS.SESSION, {accountID: TEST_ACCOUNT_ID, email: 'test@test.com'}); + await Onyx.merge(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {reports: mockReports}); await waitForBatchedUpdates(); renderAuthScreensInitHandler(); await waitForBatchedUpdatesWithAct(); - // The mount effect calls subscribeToUserEvents with undefined conciergeReportID - expect(subscribeToUserEvents).toHaveBeenCalledWith(TEST_ACCOUNT_ID, undefined); + const mockCalls = (subscribeToUserEvents as jest.Mock).mock.calls; + const firstCallArgs = mockCalls.at(0) as unknown[]; + const getter = firstCallArgs.at(1) as () => unknown; + expect(getter()).toEqual(mockReports); }); - it('passes undefined conciergeReportID when not set', async () => { + it('getter passed to subscribeToUserEvents returns undefined when report attributes not yet loaded', async () => { await Onyx.merge(ONYXKEYS.SESSION, {accountID: TEST_ACCOUNT_ID, email: 'test@test.com'}); + // Intentionally do not set ONYXKEYS.DERIVED.REPORT_ATTRIBUTES await waitForBatchedUpdates(); renderAuthScreensInitHandler(); await waitForBatchedUpdatesWithAct(); - expect(subscribeToUserEvents).toHaveBeenCalledWith(TEST_ACCOUNT_ID, undefined); + const mockCalls = (subscribeToUserEvents as jest.Mock).mock.calls; + const firstCallArgs = mockCalls.at(0) as unknown[]; + const getter = firstCallArgs.at(1) as () => unknown; + expect(getter()).toBeUndefined(); }); it('signs out when logging in as new user during transition', async () => { diff --git a/tests/ui/MoneyRequestReportPreview.test.tsx b/tests/ui/MoneyRequestReportPreview.test.tsx index 47d068cd63c1c..b358ca6de45fa 100644 --- a/tests/ui/MoneyRequestReportPreview.test.tsx +++ b/tests/ui/MoneyRequestReportPreview.test.tsx @@ -15,6 +15,7 @@ import DateUtils from '@libs/DateUtils'; import {getFormattedCreated, isManagedCardTransaction} from '@libs/TransactionUtils'; import CONST from '@src/CONST'; import * as ReportActionUtils from '@src/libs/ReportActionsUtils'; +import {getReportName} from '@src/libs/ReportNameUtils'; import * as ReportUtils from '@src/libs/ReportUtils'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Report, Transaction, TransactionViolation, TransactionViolations} from '@src/types/onyx'; @@ -152,9 +153,7 @@ describe('MoneyRequestReportPreview', () => { }); await waitForBatchedUpdatesWithAct(); - // This will be fixed as follow up https://github.com/Expensify/App/pull/75357 - // eslint-disable-next-line @typescript-eslint/no-deprecated - expect(screen.getByText(ReportUtils.getReportName({report: mockIOUReport}))).toBeOnTheScreen(); + expect(screen.getByText(getReportName(mockIOUReport))).toBeOnTheScreen(); for (const transaction of arrayOfTransactions) { const {transactionDisplayAmount, transactionHeaderText} = getTransactionDisplayAmountAndHeaderText(transaction); diff --git a/tests/unit/Search/SearchQueryUtilsTest.ts b/tests/unit/Search/SearchQueryUtilsTest.ts index 442973153c205..5ed5c0580b3fd 100644 --- a/tests/unit/Search/SearchQueryUtilsTest.ts +++ b/tests/unit/Search/SearchQueryUtilsTest.ts @@ -479,7 +479,6 @@ describe('SearchQueryUtils', () => { currentUserAccountID, autoCompleteWithSpace: false, translate: translateLocal, - conciergeReportID: 'concierge-report-id', }); expect(result).toBe('type:expense date:this-month group-by:from tag:travel'); @@ -510,7 +509,6 @@ describe('SearchQueryUtils', () => { currentUserAccountID, autoCompleteWithSpace: false, translate: translateLocal, - conciergeReportID: 'concierge-report-id', }); expect(result).toBe('type:expense status:all merchant:Uber'); @@ -546,7 +544,6 @@ describe('SearchQueryUtils', () => { currentUserAccountID, autoCompleteWithSpace: false, translate: translateLocal, - conciergeReportID: 'concierge-report-id', }); expect(result).toBe('workspace:"Team Space" type:expense merchant:Starbucks'); @@ -585,7 +582,6 @@ describe('SearchQueryUtils', () => { currentUserAccountID, autoCompleteWithSpace: false, translate: translateLocal, - conciergeReportID: 'concierge-report-id', }); expect(result).toContain('limit:25'); @@ -609,7 +605,6 @@ describe('SearchQueryUtils', () => { currentUserAccountID, autoCompleteWithSpace: false, translate: translateLocal, - conciergeReportID: 'concierge-report-id', }); expect(result).not.toContain('limit:'); @@ -633,7 +628,6 @@ describe('SearchQueryUtils', () => { currentUserAccountID, autoCompleteWithSpace: false, translate: translateLocal, - conciergeReportID: 'concierge-report-id', }); expect(result).toContain('limit:50'); @@ -1196,7 +1190,6 @@ describe('SearchQueryUtils', () => { policies: mockPolicies, currentUserAccountID, translate: translateLocal, - conciergeReportID: 'concierge-report-id', }); expect(result).toBe('+15551234567'); @@ -1222,7 +1215,6 @@ describe('SearchQueryUtils', () => { policies: mockPolicies, currentUserAccountID, translate: translateLocal, - conciergeReportID: 'concierge-report-id', }); expect(result).toBe('Jane Doe'); @@ -1247,7 +1239,6 @@ describe('SearchQueryUtils', () => { policies: mockPolicies, currentUserAccountID, translate: translateLocal, - conciergeReportID: 'concierge-report-id', }); expect(result).toBe(CONST.SEARCH.ME); @@ -1266,7 +1257,6 @@ describe('SearchQueryUtils', () => { policies: mockPolicies, currentUserAccountID, translate: translateLocal, - conciergeReportID: 'concierge-report-id', }); expect(result).toBe('88888'); @@ -1291,7 +1281,6 @@ describe('SearchQueryUtils', () => { policies: mockPolicies, currentUserAccountID, translate: translateLocal, - conciergeReportID: 'concierge-report-id', }); expect(result).toBe('Custom Name'); @@ -1317,7 +1306,6 @@ describe('SearchQueryUtils', () => { policies: mockPolicies, currentUserAccountID, translate: translateLocal, - conciergeReportID: 'concierge-report-id', }); expect(result).toBe('+15551112222'); @@ -1351,7 +1339,6 @@ describe('SearchQueryUtils', () => { policies: mockPolicies, currentUserAccountID, translate: translateLocal, - conciergeReportID: 'concierge-report-id', }); expect(result).toBe('+15553334444'); @@ -1603,15 +1590,14 @@ describe('SearchQueryUtils', () => { }); }); - describe('getFilterDisplayValue with conciergeReportID', () => { + describe('getFilterDisplayValue', () => { const mockCardList = {}; const mockCardFeeds = {}; const mockPolicies = {}; const currentUserAccountID = 12345; - it('should use conciergeReportID when resolving "in" filter with a report', () => { + it('should resolve report name for "in" filter with a report', () => { const reportID = '999'; - const conciergeReportID = '999'; const mockReports: OnyxCollection = { [`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]: { reportID, @@ -1630,11 +1616,10 @@ describe('SearchQueryUtils', () => { policies: mockPolicies, currentUserAccountID, translate: translateLocal, - conciergeReportID, }); // The result depends on getReportName internal logic, but - // what matters is that conciergeReportID is passed through + // what matters is that reportAttributes is passed through expect(typeof result).toBe('string'); expect(result.length).toBeGreaterThan(0); }); @@ -1650,13 +1635,12 @@ describe('SearchQueryUtils', () => { policies: mockPolicies, currentUserAccountID, translate: translateLocal, - conciergeReportID: 'concierge-123', }); expect(result).toBe('nonexistent-report-id'); }); - it('should handle amount filter correctly regardless of conciergeReportID', () => { + it('should handle amount filter correctly regardless of reportAttributes', () => { const result = getFilterDisplayValue({ filterName: CONST.SEARCH.SYNTAX_FILTER_KEYS.AMOUNT, filterValue: '150000', @@ -1667,13 +1651,12 @@ describe('SearchQueryUtils', () => { policies: mockPolicies, currentUserAccountID, translate: translateLocal, - conciergeReportID: 'concierge-123', }); expect(result).toBe('1500'); }); - it('should handle exported_to filter correctly regardless of conciergeReportID', () => { + it('should handle exported_to filter correctly regardless of reportAttributes', () => { const result = getFilterDisplayValue({ filterName: CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTED_TO, filterValue: CONST.REPORT.EXPORT_OPTIONS.REPORT_LEVEL_EXPORT, @@ -1684,7 +1667,6 @@ describe('SearchQueryUtils', () => { policies: mockPolicies, currentUserAccountID, translate: translateLocal, - conciergeReportID: 'concierge-123', }); expect(result).toBe(CONST.REPORT.EXPORT_OPTION_LABELS.REPORT_LEVEL_EXPORT); @@ -1707,7 +1689,6 @@ describe('SearchQueryUtils', () => { policies, currentUserAccountID, translate: translateLocal, - conciergeReportID: 'concierge-123', }); expect(result).toBe('My Workspace'); @@ -1724,7 +1705,6 @@ describe('SearchQueryUtils', () => { policies: mockPolicies, currentUserAccountID, translate: translateLocal, - conciergeReportID: 'concierge-123', }); expect(result).toBe('GL:travel'); @@ -1739,7 +1719,6 @@ describe('SearchQueryUtils', () => { const emptyPolicies: OnyxCollection = {}; const emptyTaxRates: Record = {}; const currentUserAccountID = 12345; - const conciergeReportID = 'concierge-report-id'; it('should resolve tax rate IDs to human-readable names', () => { const taxRates: Record = { @@ -1763,7 +1742,6 @@ describe('SearchQueryUtils', () => { emptyPolicies, currentUserAccountID, translateLocal, - conciergeReportID, ); expect(result).toHaveLength(2); @@ -1792,7 +1770,6 @@ describe('SearchQueryUtils', () => { emptyPolicies, currentUserAccountID, translateLocal, - conciergeReportID, ); expect(result).toHaveLength(1); @@ -1821,7 +1798,6 @@ describe('SearchQueryUtils', () => { emptyPolicies, currentUserAccountID, translateLocal, - conciergeReportID, ); expect(result).toHaveLength(1); @@ -1850,7 +1826,6 @@ describe('SearchQueryUtils', () => { emptyPolicies, currentUserAccountID, translateLocal, - conciergeReportID, ); expect(result).toHaveLength(1); @@ -1871,14 +1846,13 @@ describe('SearchQueryUtils', () => { emptyPolicies, currentUserAccountID, translateLocal, - conciergeReportID, ); expect(result).toHaveLength(1); expect(result.at(0)?.value).toBe('1500'); }); - it('should pass conciergeReportID through to getFilterDisplayValue for in filter', () => { + it('should resolve report name for in filter', () => { const reportID = '555'; const mockReports: OnyxCollection = { [`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]: { @@ -1900,7 +1874,6 @@ describe('SearchQueryUtils', () => { emptyPolicies, currentUserAccountID, translateLocal, - conciergeReportID, ); expect(result).toHaveLength(1); @@ -1908,16 +1881,15 @@ describe('SearchQueryUtils', () => { }); }); - describe('buildUserReadableQueryString with conciergeReportID', () => { + describe('buildUserReadableQueryString', () => { const emptyReports: OnyxCollection = {}; const emptyCardList: OnyxTypes.CardList = {}; const emptyCardFeeds: OnyxCollection = {}; const emptyPolicies: OnyxCollection = {}; const emptyTaxRates: Record = {}; const currentUserAccountID = 12345; - const conciergeReportID = 'concierge-report-id'; - test('passes conciergeReportID through for in-filter queries', () => { + test('resolves in-filter queries with report names', () => { const reportID = '777'; const reports: OnyxCollection = { [`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]: { @@ -1943,14 +1915,13 @@ describe('SearchQueryUtils', () => { currentUserAccountID, autoCompleteWithSpace: false, translate: translateLocal, - conciergeReportID, }); expect(result).toContain('in:'); expect(typeof result).toBe('string'); }); - test('resolves from filter with personal details and conciergeReportID', () => { + test('resolves from filter with personal details', () => { const personalDetails = { '78901': { accountID: 78901, @@ -1976,7 +1947,6 @@ describe('SearchQueryUtils', () => { currentUserAccountID, autoCompleteWithSpace: false, translate: translateLocal, - conciergeReportID, }); expect(result).toContain('from:"Jane Doe"'); @@ -2008,7 +1978,6 @@ describe('SearchQueryUtils', () => { currentUserAccountID, autoCompleteWithSpace: false, translate: translateLocal, - conciergeReportID, }); expect(result).toContain(`from:${CONST.SEARCH.ME}`); @@ -2032,7 +2001,6 @@ describe('SearchQueryUtils', () => { currentUserAccountID, autoCompleteWithSpace: true, translate: translateLocal, - conciergeReportID, }); expect(result.endsWith(' ')).toBe(true); diff --git a/tests/unit/Search/buildSubstitutionsMapTest.ts b/tests/unit/Search/buildSubstitutionsMapTest.ts index bf818eca9de90..f3241fd17484f 100644 --- a/tests/unit/Search/buildSubstitutionsMapTest.ts +++ b/tests/unit/Search/buildSubstitutionsMapTest.ts @@ -80,14 +80,14 @@ describe('buildSubstitutionsMap should return correct substitutions map', () => test('when there were no substitutions', () => { const userQuery = 'foo bar'; - const result = buildSubstitutionsMap(userQuery, personalDetailsMock, reportsMock, taxRatesMock, {}, cardFeedsMock, {}, 12345, translateLocal, 'concierge-report-id'); + const result = buildSubstitutionsMap(userQuery, personalDetailsMock, reportsMock, taxRatesMock, {}, cardFeedsMock, {}, 12345, translateLocal, {}); expect(result).toStrictEqual({}); }); test('when query has a single substitution', () => { const userQuery = 'foo from:12345'; - const result = buildSubstitutionsMap(userQuery, personalDetailsMock, reportsMock, taxRatesMock, {}, cardFeedsMock, {}, 11111, translateLocal, 'concierge-report-id'); + const result = buildSubstitutionsMap(userQuery, personalDetailsMock, reportsMock, taxRatesMock, {}, cardFeedsMock, {}, 11111, translateLocal, {}); expect(result).toStrictEqual({ 'from:John Doe': '12345', @@ -97,7 +97,7 @@ describe('buildSubstitutionsMap should return correct substitutions map', () => test('when query has multiple substitutions of different types', () => { const userQuery = 'from:78901,12345 to:nonExistingGuy@mail.com cardID:11223344 in:rep123 taxRate:id_TAX_1 groupBy:cards feed:"1234_oauth.americanexpressfdx.com 1001"'; - const result = buildSubstitutionsMap(userQuery, personalDetailsMock, reportsMock, taxRatesMock, cardListMock, cardFeedsMock, {}, 11111, translateLocal, 'concierge-report-id'); + const result = buildSubstitutionsMap(userQuery, personalDetailsMock, reportsMock, taxRatesMock, cardListMock, cardFeedsMock, {}, 11111, translateLocal, {}); expect(result).toStrictEqual({ 'from:Jane Doe': '78901', @@ -112,7 +112,7 @@ describe('buildSubstitutionsMap should return correct substitutions map', () => test('when query has a substitution for the current user', () => { const userQuery = 'from:12345'; - const result = buildSubstitutionsMap(userQuery, personalDetailsMock, reportsMock, taxRatesMock, cardListMock, cardFeedsMock, {}, 12345, translateLocal, 'concierge-report-id'); + const result = buildSubstitutionsMap(userQuery, personalDetailsMock, reportsMock, taxRatesMock, cardListMock, cardFeedsMock, {}, 12345, translateLocal, {}); expect(result).toStrictEqual({ 'from:me': '12345', diff --git a/tests/unit/showReportActionNotificationTest.ts b/tests/unit/showReportActionNotificationTest.ts index aed1f1de98e21..a7b88a480c953 100644 --- a/tests/unit/showReportActionNotificationTest.ts +++ b/tests/unit/showReportActionNotificationTest.ts @@ -46,7 +46,7 @@ const CURRENT_USER_ACCOUNT_ID = 1; const CURRENT_USER_LOGIN = 'test@user.com'; const REPORT_ID = '100'; const OTHER_USER_ACCOUNT_ID = 2; -const CONCIERGE_REPORT_ID = '42'; +const REPORT_ATTRIBUTES = {someReportKey: {reportName: 'Test Report'}} as Record; describe('showReportActionNotification', () => { beforeAll(() => { @@ -76,7 +76,7 @@ describe('showReportActionNotification', () => { await waitForBatchedUpdates(); } - it('passes conciergeReportID to showModifiedExpenseNotification for MODIFIED_EXPENSE actions', async () => { + it('passes reportAttributes to showModifiedExpenseNotification for MODIFIED_EXPENSE actions', async () => { await setupReport(); const reportAction = { @@ -93,17 +93,17 @@ describe('showReportActionNotification', () => { reportAction as Parameters[1], CURRENT_USER_ACCOUNT_ID, CURRENT_USER_LOGIN, - CONCIERGE_REPORT_ID, + REPORT_ATTRIBUTES as Parameters[4], ); await waitForBatchedUpdates(); expect(mockShowModifiedExpenseNotification).toHaveBeenCalledTimes(1); const callArgs = mockShowModifiedExpenseNotification.mock.calls.at(0)?.at(0) as Record; - expect(callArgs.conciergeReportID).toBe(CONCIERGE_REPORT_ID); + expect(callArgs.reportAttributes).toBe(REPORT_ATTRIBUTES); expect(mockShowCommentNotification).not.toHaveBeenCalled(); }); - it('passes undefined conciergeReportID to showModifiedExpenseNotification when not provided', async () => { + it('passes undefined reportAttributes to showModifiedExpenseNotification when not provided', async () => { await setupReport(); const reportAction = { @@ -120,7 +120,7 @@ describe('showReportActionNotification', () => { expect(mockShowModifiedExpenseNotification).toHaveBeenCalledTimes(1); const callArgs = mockShowModifiedExpenseNotification.mock.calls.at(0)?.at(0) as Record; - expect(callArgs.conciergeReportID).toBeUndefined(); + expect(callArgs.reportAttributes).toBeUndefined(); expect(mockShowCommentNotification).not.toHaveBeenCalled(); }); @@ -141,7 +141,7 @@ describe('showReportActionNotification', () => { reportAction as Parameters[1], CURRENT_USER_ACCOUNT_ID, CURRENT_USER_LOGIN, - CONCIERGE_REPORT_ID, + REPORT_ATTRIBUTES as Parameters[4], ); await waitForBatchedUpdates();