From 8c9f5665cca57a10f754df0b9ae65b3b4e66a3da Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Wed, 6 Aug 2025 15:42:06 +0200 Subject: [PATCH] Revert "Merge pull request #67205 from allgandalf/fixSearch.ts" This reverts commit 6782a29d1cc909e96021393f904ddfb6deb3724c, reversing changes made to 4121f2726d9aa114af2e058d72c9592c84440698. --- package.json | 2 +- .../Search/ReportListItemHeader.tsx | 24 +-------- .../Search/TransactionListItem.tsx | 25 +--------- src/libs/actions/Search.ts | 48 ++++++++++-------- .../Search/handleActionButtonPressTest.ts | 49 ++----------------- 5 files changed, 36 insertions(+), 112 deletions(-) diff --git a/package.json b/package.json index 02efa6e424e4..2e4579c6cd82 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "test:debug": "TZ=utc NODE_OPTIONS='--inspect-brk --experimental-vm-modules' jest --runInBand", "perf-test": "NODE_OPTIONS=--experimental-vm-modules npx reassure", "typecheck": "NODE_OPTIONS=--max_old_space_size=8192 tsc", - "lint": "NODE_OPTIONS=--max_old_space_size=8192 eslint . --max-warnings=311 --cache --cache-location=node_modules/.cache/eslint", + "lint": "NODE_OPTIONS=--max_old_space_size=8192 eslint . --max-warnings=313 --cache --cache-location=node_modules/.cache/eslint", "lint-changed": "NODE_OPTIONS=--max_old_space_size=8192 ./scripts/lintChanged.sh", "lint-watch": "npx eslint-watch --watch --changed", "shellcheck": "./scripts/shellCheck.sh", diff --git a/src/components/SelectionList/Search/ReportListItemHeader.tsx b/src/components/SelectionList/Search/ReportListItemHeader.tsx index a8b927a970fc..ca677b1621f4 100644 --- a/src/components/SelectionList/Search/ReportListItemHeader.tsx +++ b/src/components/SelectionList/Search/ReportListItemHeader.tsx @@ -1,4 +1,4 @@ -import React, {useMemo} from 'react'; +import React from 'react'; import {View} from 'react-native'; import type {ColorValue} from 'react-native'; import Checkbox from '@components/Checkbox'; @@ -6,7 +6,6 @@ import ReportSearchHeader from '@components/ReportSearchHeader'; import {useSearchContext} from '@components/Search/SearchContext'; import type {ListItem, TransactionReportGroupListItemType} from '@components/SelectionList/types'; import TextWithTooltip from '@components/TextWithTooltip'; -import useOnyx from '@hooks/useOnyx'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; @@ -14,8 +13,6 @@ import useThemeStyles from '@hooks/useThemeStyles'; import {convertToDisplayString} from '@libs/CurrencyUtils'; import {handleActionButtonPress} from '@userActions/Search'; import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import type {SearchPolicy, SearchReport} from '@src/types/onyx/SearchResults'; import ActionCell from './ActionCell'; import UserInfoAndActionButtonRow from './UserInfoAndActionButtonRow'; @@ -152,30 +149,13 @@ function ReportListItemHeader({report: reportItem, onSel const theme = useTheme(); const {currentSearchHash, currentSearchKey} = useSearchContext(); const {isLargeScreenWidth, shouldUseNarrowLayout} = useResponsiveLayout(); - const [lastPaymentMethod] = useOnyx(ONYXKEYS.NVP_LAST_PAYMENT_METHOD, {canBeMissing: true}); const thereIsFromAndTo = !!reportItem?.from && !!reportItem?.to; const showUserInfo = (reportItem.type === CONST.REPORT.TYPE.IOU && thereIsFromAndTo) || (reportItem.type === CONST.REPORT.TYPE.EXPENSE && !!reportItem?.from); - const [snapshot] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${currentSearchHash}`, {canBeMissing: true}); - const snapshotReport = useMemo(() => { - return (snapshot?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${reportItem.reportID}`] ?? {}) as SearchReport; - }, [snapshot, reportItem.reportID]); - const snapshotPolicy = useMemo(() => { - return (snapshot?.data?.[`${ONYXKEYS.COLLECTION.POLICY}${reportItem.policyID}`] ?? {}) as SearchPolicy; - }, [snapshot, reportItem.policyID]); const avatarBorderColor = StyleUtils.getItemBackgroundColorStyle(!!reportItem.isSelected, !!isFocused, !!isDisabled, theme.activeComponentBG, theme.hoverComponentBG)?.backgroundColor ?? theme.highlightBG; const handleOnButtonPress = () => { - handleActionButtonPress( - currentSearchHash, - reportItem, - () => onSelectRow(reportItem as unknown as TItem), - shouldUseNarrowLayout && !!canSelectMultiple, - snapshotReport, - snapshotPolicy, - lastPaymentMethod, - currentSearchKey, - ); + handleActionButtonPress(currentSearchHash, reportItem, () => onSelectRow(reportItem as unknown as TItem), shouldUseNarrowLayout && !!canSelectMultiple, currentSearchKey); }; return !isLargeScreenWidth ? ( diff --git a/src/components/SelectionList/Search/TransactionListItem.tsx b/src/components/SelectionList/Search/TransactionListItem.tsx index 25cd8f40a50c..f586330fa3e7 100644 --- a/src/components/SelectionList/Search/TransactionListItem.tsx +++ b/src/components/SelectionList/Search/TransactionListItem.tsx @@ -8,7 +8,6 @@ import {useSearchContext} from '@components/Search/SearchContext'; import type {ListItem, TransactionListItemProps, TransactionListItemType} from '@components/SelectionList/types'; import TransactionItemRow from '@components/TransactionItemRow'; import useAnimatedHighlightStyle from '@hooks/useAnimatedHighlightStyle'; -import useOnyx from '@hooks/useOnyx'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useStyleUtils from '@hooks/useStyleUtils'; import useSyncFocus from '@hooks/useSyncFocus'; @@ -17,8 +16,6 @@ import useThemeStyles from '@hooks/useThemeStyles'; import {handleActionButtonPress as handleActionButtonPressUtil} from '@libs/actions/Search'; import variables from '@styles/variables'; import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import type {SearchPolicy, SearchReport} from '@src/types/onyx/SearchResults'; import UserInfoAndActionButtonRow from './UserInfoAndActionButtonRow'; function TransactionListItem({ @@ -42,15 +39,6 @@ function TransactionListItem({ const {isLargeScreenWidth, shouldUseNarrowLayout} = useResponsiveLayout(); const {currentSearchHash, currentSearchKey} = useSearchContext(); - const [snapshot] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${currentSearchHash}`, {canBeMissing: true}); - const snapshotReport = useMemo(() => { - return (snapshot?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionItem.reportID}`] ?? {}) as SearchReport; - }, [snapshot, transactionItem.reportID]); - - const snapshotPolicy = useMemo(() => { - return (snapshot?.data?.[`${ONYXKEYS.COLLECTION.POLICY}${transactionItem.policyID}`] ?? {}) as SearchPolicy; - }, [snapshot, transactionItem.policyID]); - const [lastPaymentMethod] = useOnyx(`${ONYXKEYS.NVP_LAST_PAYMENT_METHOD}`, {canBeMissing: true}); const pressableStyle = [ styles.transactionListItemStyle, @@ -75,17 +63,8 @@ function TransactionListItem({ }, [transactionItem]); const handleActionButtonPress = useCallback(() => { - handleActionButtonPressUtil( - currentSearchHash, - transactionItem, - () => onSelectRow(item), - shouldUseNarrowLayout && !!canSelectMultiple, - snapshotReport, - snapshotPolicy, - lastPaymentMethod, - currentSearchKey, - ); - }, [currentSearchHash, transactionItem, shouldUseNarrowLayout, canSelectMultiple, snapshotReport, snapshotPolicy, lastPaymentMethod, currentSearchKey, onSelectRow, item]); + handleActionButtonPressUtil(currentSearchHash, transactionItem, () => onSelectRow(item), shouldUseNarrowLayout && !!canSelectMultiple, currentSearchKey); + }, [canSelectMultiple, currentSearchHash, currentSearchKey, item, onSelectRow, shouldUseNarrowLayout, transactionItem]); const handleCheckboxPress = useCallback(() => { onCheckboxPress?.(item); diff --git a/src/libs/actions/Search.ts b/src/libs/actions/Search.ts index 57cf73d512da..2105bfaf4cb0 100644 --- a/src/libs/actions/Search.ts +++ b/src/libs/actions/Search.ts @@ -1,5 +1,5 @@ import Onyx from 'react-native-onyx'; -import type {OnyxEntry, OnyxUpdate} from 'react-native-onyx'; +import type {OnyxCollection, OnyxEntry, OnyxUpdate} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import type {FormOnyxValues} from '@components/Form/types'; import type {PaymentData, SearchQueryJSON} from '@components/Search/types'; @@ -22,20 +22,34 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import {FILTER_KEYS} from '@src/types/form/SearchAdvancedFiltersForm'; import type {SearchAdvancedFiltersForm} from '@src/types/form/SearchAdvancedFiltersForm'; -import type {LastPaymentMethod, LastPaymentMethodType, Policy} from '@src/types/onyx'; import type {PaymentInformation} from '@src/types/onyx/LastPaymentMethod'; +import type {LastPaymentMethod, LastPaymentMethodType, Policy, SearchResults} from '@src/types/onyx'; import type {ConnectionName} from '@src/types/onyx/Policy'; import type {SearchPolicy, SearchReport, SearchTransaction} from '@src/types/onyx/SearchResults'; import type Nullable from '@src/types/utils/Nullable'; +let lastPaymentMethod: OnyxEntry; +Onyx.connect({ + key: ONYXKEYS.NVP_LAST_PAYMENT_METHOD, + callback: (val) => { + lastPaymentMethod = val; + }, +}); + +let allSnapshots: OnyxCollection; +Onyx.connect({ + key: ONYXKEYS.COLLECTION.SNAPSHOT, + callback: (val) => { + allSnapshots = val; + }, + waitForCollectionCallback: true, +}); + function handleActionButtonPress( hash: number, item: TransactionListItemType | TransactionReportGroupListItemType, goToItem: () => void, isInMobileSelectionMode: boolean, - snapshotReport: SearchReport, - snapshotPolicy: SearchPolicy, - lastPaymentMethod: OnyxEntry, currentSearchKey?: SearchKey, ) { // The transactionIDList is needed to handle actions taken on `status:""` where transactions on single expense reports can be approved/paid. @@ -51,13 +65,14 @@ function handleActionButtonPress( switch (item.action) { case CONST.SEARCH.ACTION_TYPES.PAY: - getPayActionCallback(hash, item, goToItem, snapshotReport, snapshotPolicy, lastPaymentMethod, currentSearchKey); + getPayActionCallback(hash, item, goToItem, currentSearchKey); return; case CONST.SEARCH.ACTION_TYPES.APPROVE: approveMoneyRequestOnSearch(hash, [item.reportID], transactionID, currentSearchKey); return; case CONST.SEARCH.ACTION_TYPES.SUBMIT: { - submitMoneyRequestOnSearch(hash, [item], [snapshotPolicy], transactionID, currentSearchKey); + const policy = (allSnapshots?.[`${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`]?.data?.[`${ONYXKEYS.COLLECTION.POLICY}${item.policyID}`] ?? {}) as SearchPolicy; + submitMoneyRequestOnSearch(hash, [item], [policy], transactionID, currentSearchKey); return; } case CONST.SEARCH.ACTION_TYPES.EXPORT_TO_ACCOUNTING: { @@ -65,7 +80,7 @@ function handleActionButtonPress( return; } - const policy = (snapshotPolicy ?? {}) as Policy; + const policy = (allSnapshots?.[`${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`]?.data?.[`${ONYXKEYS.COLLECTION.POLICY}${item.policyID}`] ?? {}) as Policy; const connectedIntegration = getValidConnectedIntegration(policy); if (!connectedIntegration) { @@ -126,23 +141,16 @@ function getReportType(reportID?: string) { return undefined; } -function getPayActionCallback( - hash: number, - item: TransactionListItemType | TransactionReportGroupListItemType, - goToItem: () => void, - snapshotReport: SearchReport, - snapshotPolicy: SearchPolicy, - lastPaymentMethod: OnyxEntry, - currentSearchKey?: SearchKey, -) { - const lastPolicyPaymentMethod = getLastPolicyPaymentMethod(item.policyID, lastPaymentMethod, getReportType(item.reportID)); +function getPayActionCallback(hash: number, item: TransactionListItemType | TransactionReportGroupListItemType, goToItem: () => void, currentSearchKey?: SearchKey) { + const lastPolicyPaymentMethod = getLastPolicyPaymentMethod(item.policyID, lastPaymentMethod); if (!lastPolicyPaymentMethod || !Object.values(CONST.IOU.PAYMENT_TYPE).includes(lastPolicyPaymentMethod)) { goToItem(); return; } - const amount = Math.abs((snapshotReport?.total ?? 0) - (snapshotReport?.nonReimbursableTotal ?? 0)); + const report = (allSnapshots?.[`${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`]?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${item.reportID}`] ?? {}) as SearchReport; + const amount = Math.abs((report?.total ?? 0) - (report?.nonReimbursableTotal ?? 0)); const transactionID = isTransactionListItemType(item) ? [item.transactionID] : undefined; if (lastPolicyPaymentMethod === CONST.IOU.PAYMENT_TYPE.ELSEWHERE) { @@ -150,7 +158,7 @@ function getPayActionCallback( return; } - const hasVBBA = !!snapshotPolicy?.achAccount?.bankAccountID; + const hasVBBA = !!allSnapshots?.[`${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`]?.data?.[`${ONYXKEYS.COLLECTION.POLICY}${item.policyID}`]?.achAccount?.bankAccountID; if (hasVBBA) { payMoneyRequestOnSearch(hash, [{reportID: item.reportID, amount, paymentType: lastPolicyPaymentMethod}], transactionID, currentSearchKey); return; diff --git a/tests/unit/Search/handleActionButtonPressTest.ts b/tests/unit/Search/handleActionButtonPressTest.ts index 0c1902165a85..150ed7177181 100644 --- a/tests/unit/Search/handleActionButtonPressTest.ts +++ b/tests/unit/Search/handleActionButtonPressTest.ts @@ -1,10 +1,6 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import type {OnyxEntry} from 'react-native-onyx'; -import Onyx from 'react-native-onyx'; import type {TransactionReportGroupListItemType} from '@components/SelectionList/types'; import {handleActionButtonPress} from '@libs/actions/Search'; -import ONYXKEYS from '@src/ONYXKEYS'; -import type {LastPaymentMethod, SearchResults} from '@src/types/onyx'; jest.mock('@src/components/ConfirmedRoute.tsx'); @@ -221,62 +217,23 @@ const updatedMockReportItem = { }), }; -const mockSnapshotForItem: OnyxEntry = { - // @ts-expect-error: Allow partial record in snapshot update for testing - data: { - [`${ONYXKEYS.COLLECTION.POLICY}${mockReportItemWithHold?.policyID}`]: { - ...(mockReportItemWithHold.policyID - ? { - [String(mockReportItemWithHold.policyID)]: { - type: 'policy', - id: String(mockReportItemWithHold.policyID), - role: 'admin', - owner: 'apb@apb.com', - ...mockReportItemWithHold, - }, - } - : {}), - }, - }, -}; - -const mockLastPaymentMethod: OnyxEntry = { - expense: 'Elsewhere', - lastUsed: 'Elsewhere', -}; - describe('handleActionButtonPress', () => { const searchHash = 1; - beforeAll(() => { - Onyx.merge( - `${ONYXKEYS.COLLECTION.SNAPSHOT}${searchHash}`, - // @ts-expect-error: Allow partial record in snapshot update for testing - mockSnapshotForItem, - ); - Onyx.merge(ONYXKEYS.NVP_LAST_PAYMENT_METHOD, mockLastPaymentMethod); - }); - - const snapshotReport = mockSnapshotForItem?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${mockReportItemWithHold.reportID}`] ?? {}; - const snapshotPolicy = mockSnapshotForItem?.data?.[`${ONYXKEYS.COLLECTION.POLICY}${mockReportItemWithHold.policyID}`] ?? {}; - test('Should navigate to item when report has one transaction on hold', () => { const goToItem = jest.fn(() => {}); - // @ts-expect-error: Allow partial record in snapshot update for testing - handleActionButtonPress(searchHash, mockReportItemWithHold, goToItem, false, snapshotReport, snapshotPolicy, mockLastPaymentMethod); + handleActionButtonPress(searchHash, mockReportItemWithHold, goToItem, false); expect(goToItem).toHaveBeenCalledTimes(1); }); test('Should not navigate to item when the hold is removed', () => { const goToItem = jest.fn(() => {}); - // @ts-expect-error: Allow partial record in snapshot update for testing - handleActionButtonPress(searchHash, updatedMockReportItem, goToItem, false, snapshotReport, snapshotPolicy, mockLastPaymentMethod); + handleActionButtonPress(searchHash, updatedMockReportItem, goToItem, false); expect(goToItem).toHaveBeenCalledTimes(0); }); test('Should run goToItem callback when user is in mobile selection mode', () => { const goToItem = jest.fn(() => {}); - // @ts-expect-error: Allow partial record in snapshot update for testing - handleActionButtonPress(searchHash, updatedMockReportItem, goToItem, true, snapshotReport, snapshotPolicy, mockLastPaymentMethod); + handleActionButtonPress(searchHash, updatedMockReportItem, goToItem, true); expect(goToItem).toHaveBeenCalledTimes(1); }); });