Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback';
import MoneyRequestReceiptView from '@components/ReportActionItem/MoneyRequestReceiptView';
import ReportActionsSkeletonView from '@components/ReportActionsSkeletonView';
import ReportHeaderSkeletonView from '@components/ReportHeaderSkeletonView';
import useLatchedTransactionIDs from '@hooks/useLatchedTransactionIDs';
import useNetwork from '@hooks/useNetwork';
import useOnyx from '@hooks/useOnyx';
import usePaginatedReportActions from '@hooks/usePaginatedReportActions';
Expand Down Expand Up @@ -139,7 +140,12 @@ function MoneyRequestReportView({report, reportLoadingState, shouldDisplayReport
return transactions.filter((transaction) => transaction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
}, [transactions, isOffline]);
const reportTransactionIDs = visibleTransactions.map((transaction) => transaction.transactionID);
const transactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, reportActions ?? [], isOffline, reportTransactionIDs);

const latchedTransactionIDs = useLatchedTransactionIDs(reportTransactionIDs, reportID);
const reportTransactionIDsLatched = latchedTransactionIDs ? reportTransactionIDs.filter((id) => latchedTransactionIDs.has(id)) : reportTransactionIDs;
const visibleTransactionsLatched = latchedTransactionIDs ? visibleTransactions.filter((t) => latchedTransactionIDs.has(t.transactionID)) : visibleTransactions;

const transactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, reportActions ?? [], isOffline, reportTransactionIDsLatched);

const isLoadingInitialReportActions = reportLoadingState?.isLoadingInitialReportActions;
const dismissReportCreationError = useCallback(() => {
Expand All @@ -159,10 +165,10 @@ function MoneyRequestReportView({report, reportLoadingState, shouldDisplayReport
const shouldShowOpenReportLoadingSkeleton = !!(isLoadingInitialReportActions && reportActions.length === 0 && !isOffline) || shouldWaitForTransactions;

const isEmptyTransactionReport = visibleTransactions?.length === 0 && transactionThreadReportID === undefined;
const shouldDisplayMoneyRequestActionsList = !!isEmptyTransactionReport || shouldDisplayReportTableView(report, visibleTransactions ?? []);
const shouldDisplayMoneyRequestActionsList = !!isEmptyTransactionReport || shouldDisplayReportTableView(report, visibleTransactionsLatched);

const [transactionThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`);
const shouldShowWideRHPReceipt = visibleTransactions.length === 1 && !isSmallScreenWidth && !!transactionThreadReport;
const shouldShowWideRHPReceipt = visibleTransactionsLatched.length === 1 && !isSmallScreenWidth && !!transactionThreadReport;

const reportHeaderView = useMemo(
() =>
Expand Down
19 changes: 19 additions & 0 deletions src/hooks/useLatchedTransactionIDs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {useState} from 'react';

/**
* Snapshots the first non-empty transaction-ID set so layout decisions driven by
* `transactions.length` stay stable across optimistic additions (e.g. Duplicate). Pass `resetKey`
* (typically the report ID) to re-snapshot when the component is reused for a different report
* via setParams without remount.
*/
function useLatchedTransactionIDs(transactionIDs: ReadonlyArray<string> | undefined, resetKey?: string): Set<string> | undefined {

Check failure on line 9 in src/hooks/useLatchedTransactionIDs.ts

View workflow job for this annotation

GitHub Actions / ESLint check

Array type using 'ReadonlyArray<string>' is forbidden for simple types. Use 'readonly string[]' instead

Check failure on line 9 in src/hooks/useLatchedTransactionIDs.ts

View workflow job for this annotation

GitHub Actions / ESLint check

Array type using 'ReadonlyArray<string>' is forbidden for simple types. Use 'readonly string[]' instead
const [latched, setLatched] = useState<{key: string | undefined; ids: Set<string>} | undefined>(undefined);
const isEmpty = !transactionIDs || transactionIDs.length === 0;
const keyChanged = latched !== undefined && latched.key !== resetKey;
if (!isEmpty && (latched === undefined || keyChanged)) {
setLatched({key: resetKey, ids: new Set(transactionIDs)});
}
return latched?.ids;
}

export default useLatchedTransactionIDs;
9 changes: 8 additions & 1 deletion src/pages/Search/SearchMoneyRequestReportPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'
import useDismissOnMoneyRequestReportRemoval from '@hooks/useDismissOnMoneyRequestReportRemoval';
import useDocumentTitle from '@hooks/useDocumentTitle';
import useIsReportReadyToDisplay from '@hooks/useIsReportReadyToDisplay';
import useLatchedTransactionIDs from '@hooks/useLatchedTransactionIDs';
import useNetwork from '@hooks/useNetwork';
import useOnyx from '@hooks/useOnyx';
import usePaginatedReportActions from '@hooks/usePaginatedReportActions';
Expand Down Expand Up @@ -178,8 +179,14 @@ function SearchMoneyRequestReportPage({route}: SearchMoneyRequestPageProps) {
return {snapshotTransaction: transaction, snapshotViolations: violations};
}, [snapshot?.data, allReportTransactions]);

const latchedIDsForLayout = useLatchedTransactionIDs(
visibleTransactions.map((t) => t.transactionID),
reportIDFromRoute,
);
const layoutLatchedTransactions = latchedIDsForLayout ? visibleTransactions.filter((t) => latchedIDsForLayout.has(t.transactionID)) : visibleTransactions;

// If there is more than one transaction, display the report in Super Wide RHP, otherwise it will be shown in Wide RHP
const shouldShowSuperWideRHP = visibleTransactions.length > 1;
const shouldShowSuperWideRHP = layoutLatchedTransactions.length > 1;

useShowSuperWideRHPVersion(shouldShowSuperWideRHP);

Expand Down
9 changes: 8 additions & 1 deletion src/pages/inbox/ReportActionsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {useRoute} from '@react-navigation/native';
import React from 'react';
import MoneyRequestReportActionsList from '@components/MoneyRequestReportView/MoneyRequestReportActionsList';
import ReportActionsSkeletonView from '@components/ReportActionsSkeletonView';
import useLatchedTransactionIDs from '@hooks/useLatchedTransactionIDs';
import useNetwork from '@hooks/useNetwork';
import useOnyx from '@hooks/useOnyx';
import usePaginatedReportActions from '@hooks/usePaginatedReportActions';
Expand Down Expand Up @@ -40,9 +41,15 @@ function ReportActionsList() {
const allReportTransactions = useReportTransactionsCollection(reportIDFromRoute);
const reportTransactions = getAllNonDeletedTransactions(allReportTransactions, reportActions, isOffline, true);

const latchedIDs = useLatchedTransactionIDs(
reportTransactions.map((t) => t.transactionID),
reportIDFromRoute,
);
const transactionsForViewDecision = latchedIDs ? reportTransactions.filter((t) => latchedIDs.has(t.transactionID)) : reportTransactions;

const isMoneyRequestOrInvoiceReport = isMoneyRequestReport(report) || isInvoiceReport(report);
const shouldWaitForTransactions = shouldWaitForTransactionsUtil(report, reportTransactions, reportLoadingState, isOffline);
const shouldDisplayMoneyRequestActionsList = isMoneyRequestOrInvoiceReport && shouldDisplayReportTableView(report, reportTransactions);
const shouldDisplayMoneyRequestActionsList = isMoneyRequestOrInvoiceReport && shouldDisplayReportTableView(report, transactionsForViewDecision);

if (!report || shouldWaitForTransactions) {
return <ReportActionsSkeletonView />;
Expand Down
12 changes: 10 additions & 2 deletions src/pages/inbox/WideRHPReceiptPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {Animated} from 'react-native';
import MoneyRequestReceiptView from '@components/ReportActionItem/MoneyRequestReceiptView';
import ScrollView from '@components/ScrollView';
import useShowWideRHPVersion from '@components/WideRHPContextProvider/useShowWideRHPVersion';
import useLatchedTransactionIDs from '@hooks/useLatchedTransactionIDs';
import useNetwork from '@hooks/useNetwork';
import useOnyx from '@hooks/useOnyx';
import usePaginatedReportActions from '@hooks/usePaginatedReportActions';
Expand Down Expand Up @@ -53,12 +54,19 @@ function WideRHPReceiptPanelGate() {
const allReportTransactions = useReportTransactionsCollection(reportIDFromRoute);
const reportTransactions = getAllNonDeletedTransactions(allReportTransactions, reportActions, isOffline, true);
const visibleTransactions = reportTransactions?.filter((transaction) => isOffline || transaction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
const reportTransactionIDs = visibleTransactions?.map((transaction) => transaction.transactionID);

const latchedIDs = useLatchedTransactionIDs(
visibleTransactions.map((t) => t.transactionID),
reportIDFromRoute,
);
const transactionsForViewDecision = latchedIDs ? visibleTransactions.filter((t) => latchedIDs.has(t.transactionID)) : visibleTransactions;

const reportTransactionIDs = transactionsForViewDecision.map((transaction) => transaction.transactionID);
const transactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, reportActions ?? [], isOffline, reportTransactionIDs);
const [transactionThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`);

const isMoneyRequestOrInvoiceReport = isMoneyRequestReport(report) || isInvoiceReport(report);
const shouldDisplayMoneyRequestActionsList = isMoneyRequestOrInvoiceReport && shouldDisplayReportTableView(report, visibleTransactions ?? []);
const shouldDisplayMoneyRequestActionsList = isMoneyRequestOrInvoiceReport && shouldDisplayReportTableView(report, transactionsForViewDecision);

const shouldShowWideRHP =
!shouldDisplayMoneyRequestActionsList &&
Expand Down
14 changes: 12 additions & 2 deletions src/pages/inbox/report/ReportActionsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import useConciergeSidePanelReportActions from '@hooks/useConciergeSidePanelRepo
import useCopySelectionHelper from '@hooks/useCopySelectionHelper';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useIsInSidePanel from '@hooks/useIsInSidePanel';
import useLatchedTransactionIDs from '@hooks/useLatchedTransactionIDs';
import useLoadReportActions from '@hooks/useLoadReportActions';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
Expand Down Expand Up @@ -112,9 +113,18 @@ function ReportActionsView({reportID, onLayout}: ReportActionsViewProps) {
[reportTransactionsForThreadID, isOffline],
);
const reportTransactionIDsForThread = useMemo(() => visibleTransactionsForThreadID?.map((t) => t.transactionID), [visibleTransactionsForThreadID]);

const latchedThreadIDs = useLatchedTransactionIDs(reportTransactionIDsForThread, reportID);
const reportTransactionIDsForThreadLatched = useMemo(() => {
if (!latchedThreadIDs) {
return reportTransactionIDsForThread;
}
return reportTransactionIDsForThread?.filter((id) => latchedThreadIDs.has(id));
}, [latchedThreadIDs, reportTransactionIDsForThread]);

const transactionThreadReportID = useMemo(
() => getOneTransactionThreadReportID(report, chatReport, allReportActions ?? [], isOffline, reportTransactionIDsForThread),
[report, chatReport, allReportActions, isOffline, reportTransactionIDsForThread],
() => getOneTransactionThreadReportID(report, chatReport, allReportActions ?? [], isOffline, reportTransactionIDsForThreadLatched),
[report, chatReport, allReportActions, isOffline, reportTransactionIDsForThreadLatched],
);

const isReportArchived = useReportIsArchived(reportID);
Expand Down
Loading