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
10 changes: 5 additions & 5 deletions src/hooks/useReportActionsListModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ import useReportIsArchived from './useReportIsArchived';
/**
* Single read/derive pipeline for the report-actions list: the subscriptions and derivations the skeleton
* decision and the list render both need, computed once. Side-effect-free (no writes/navigation/telemetry).
* The guard calls it once and passes `state`/`actions` via `ReportActionsListStateContext` and
* `ReportActionsListActionsContext` so the content doesn't re-subscribe.
* The guard publishes actions directly and gives the source state to `ReportActionsListStateProvider`
* to prepare the actions that content renders.
*/
function useReportActionsListModel(reportID: string, isReportLoadPending: boolean) {
const {isOffline} = useNetworkWithOfflineStatus();
Expand Down Expand Up @@ -133,7 +133,7 @@ function useReportActionsListModel(reportID: string, isReportLoadPending: boolea
hasUnreadConciergeMessageFromOthers,
};

// The render state slice on `ReportActionsListStateContext`; this is what drives list re-renders.
// Source state for `ReportActionsListStateProvider`; presentation filtering does not affect readiness.
// Ambient state (network, route, archived, concierge chat history) is read locally in the content instead
// of carried here.
const state = {
Expand Down Expand Up @@ -170,8 +170,8 @@ function useReportActionsListModel(reportID: string, isReportLoadPending: boolea

type ReportActionsListModel = ReturnType<typeof useReportActionsListModel>;
type ReportActionsReadinessSignals = ReportActionsListModel['readinessSignals'];
type ReportActionsListState = ReportActionsListModel['state'];
type ReportActionsListSourceState = ReportActionsListModel['state'];
type ReportActionsListActions = ReportActionsListModel['actions'];

export default useReportActionsListModel;
export type {ReportActionsReadinessSignals, ReportActionsListState, ReportActionsListActions};
export type {ReportActionsReadinessSignals, ReportActionsListSourceState, ReportActionsListActions};
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import useUnreadMarker from '@hooks/useUnreadMarker';

import Navigation from '@libs/Navigation/Navigation';
import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types';
import {shouldHidePayAction} from '@libs/ReportActionsUtils';
import {isArchivedReport} from '@libs/ReportUtils';

import type {ReportsSplitNavigatorParamList} from '@navigation/types';
Expand All @@ -42,7 +41,6 @@ import React, {useState} from 'react';

import type {ReportActionsListProps} from './types';

import filterHiddenSupportTicketSurveys from './filterHiddenSupportTicketSurveys';
import ReportActionsListFloatingMessageCounter from './ReportActionsListFloatingMessageCounter';
import useReportActionsListData from './useReportActionsListData';
import useReportActionsListRenderItem from './useReportActionsListRenderItem';
Expand All @@ -65,20 +63,13 @@ function ReportActionsListContent({reportID, onLayout}: ReportActionsListProps)
hasNewerActions,
oldestUnreadReportAction,
transactionThreadReport,
sortedAllReportActions,
sortedReportActions: unfilteredReportActions,
sortedVisibleReportActions: unfilteredVisibleReportActions,
sortedReportActions,
sortedVisibleReportActions,
isConciergeHiddenHistory,
shouldShowConciergeWelcome,
isConciergeHistoryExpanded,
} = useReportActionsListState();

// Remove rows hidden by the renderer before calculating summary counts, headers, and scroll positions.
const paymentFilteredReportActions = report?.isWaitingOnBankAccount ? unfilteredReportActions.filter((action) => !shouldHidePayAction(action, true)) : unfilteredReportActions;
const paymentFilteredVisibleReportActions = report?.isWaitingOnBankAccount
? unfilteredVisibleReportActions.filter((action) => !shouldHidePayAction(action, true))
: unfilteredVisibleReportActions;

const {handleShowPreviousMessages: onShowPreviousMessages} = useReportActionsListActions();

const {isOffline} = useNetwork();
Expand All @@ -95,19 +86,6 @@ function ReportActionsListContent({reportID, onLayout}: ReportActionsListProps)
useRetireMerchantRuleSuggestionOnLeave(reportID);

const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`);
// Hidden surveys must not become unread targets that have no rendered row.
const sortedReportActions = filterHiddenSupportTicketSurveys({
reportActions: paymentFilteredReportActions,
sortedAllReportActions,
report,
reportNameValuePairs,
});
const sortedVisibleReportActions = filterHiddenSupportTicketSurveys({
reportActions: paymentFilteredVisibleReportActions,
sortedAllReportActions,
report,
reportNameValuePairs,
});
const isReportArchived = !!isArchivedReport(reportNameValuePairs);

const reportAttributesSelector = (value: OnyxEntry<OnyxTypes.ReportAttributesDerivedValue>) => {
Expand Down Expand Up @@ -158,8 +136,6 @@ function ReportActionsListContent({reportID, onLayout}: ReportActionsListProps)
const {listID, listProps, shouldBeAlignedToTop, isFloatingMessageCounterVisible, isActionBadgeAboveViewport, scrollToBottomAndMarkReportAsRead, scrollToActionBadgeTarget} =
useReportActionsListScroll({
reportID,
// Hidden surveys still prove that the selected page contains the newest action.
sortedVisibleReportActions: paymentFilteredVisibleReportActions,
renderedVisibleReportActions: listData,
reportActionIDToDisplayIndex,
hasScrolledOverThreshold,
Expand Down
1 change: 0 additions & 1 deletion src/pages/inbox/report/ReportActionsList/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ type UseReportActionsListDataParams = {
type UseReportActionsListScrollParams = Pick<
Parameters<typeof useReportActionsScroll>[0],
| 'reportID'
| 'sortedVisibleReportActions'
| 'renderedVisibleReportActions'
| 'hasScrolledOverThreshold'
| 'markNewestActionAsRead'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ function keyExtractor(item: OnyxTypes.ReportAction): string {
/** Owns initial positioning, pagination, unread tracking, and scroll events for the report-actions list. */
function useReportActionsListScroll({
reportID,
sortedVisibleReportActions,
renderedVisibleReportActions: listData,
reportActionIDToDisplayIndex,
hasScrolledOverThreshold,
Expand All @@ -56,6 +55,7 @@ function useReportActionsListScroll({
report,
hasOnceLoadedReportActions,
hasNewerActions,
scrollReportActions,
sortedAllReportActions,
oldestUnreadReportAction,
transactionThreadReport,
Expand Down Expand Up @@ -126,7 +126,7 @@ function useReportActionsListScroll({
report,
transactionThreadReport,
parentReportAction,
sortedVisibleReportActions,
sortedVisibleReportActions: scrollReportActions,
renderedVisibleReportActions: listData,
reportActionIDToDisplayIndex,
keyExtractor,
Expand Down
9 changes: 8 additions & 1 deletion src/pages/inbox/report/ReportActionsListContext.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import type {ReportActionsListActions, ReportActionsListState, ReportActionsReadinessSignals} from '@hooks/useReportActionsListModel';
import type {ReportActionsListActions, ReportActionsListSourceState, ReportActionsReadinessSignals} from '@hooks/useReportActionsListModel';

import {isUnread} from '@libs/ReportUtils';

import type {ReportAction} from '@src/types/onyx';
import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';

import {createContext, useContext} from 'react';

type ReportActionsListState = ReportActionsListSourceState & {
/** Selected page before survey filtering, so hidden surveys still establish scroll freshness. */
scrollReportActions: ReportAction[];
};

/**
* Carries the render `state` slice from the guard to `ReportActionsList` so the list renders from the same
* derivations as the skeleton decision without re-subscribing.
Expand Down Expand Up @@ -116,3 +122,4 @@ function computeReportActionsSkeletonState(readinessSignals: ReportActionsReadin
}

export {ReportActionsListStateContext, ReportActionsListActionsContext, useReportActionsListState, useReportActionsListActions, computeReportActionsSkeletonState};
export type {ReportActionsListState};
57 changes: 57 additions & 0 deletions src/pages/inbox/report/ReportActionsListStateProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/** Prepare visible actions without rerunning pagination when survey metadata changes. */
import useOnyx from '@hooks/useOnyx';
import type {ReportActionsListSourceState} from '@hooks/useReportActionsListModel';

import {shouldHidePayAction} from '@libs/ReportActionsUtils';

import ONYXKEYS from '@src/ONYXKEYS';
import type {ReportNameValuePairs} from '@src/types/onyx';

import type {ReactNode} from 'react';
import type {OnyxEntry} from 'react-native-onyx';

import React from 'react';

import filterHiddenSupportTicketSurveys from './ReportActionsList/filterHiddenSupportTicketSurveys';
import {ReportActionsListStateContext} from './ReportActionsListContext';

type ReportActionsListStateProviderProps = {
state: ReportActionsListSourceState;
children: ReactNode;
};

const reopenedAsReportIDSelector = (reportNameValuePairs: OnyxEntry<ReportNameValuePairs>) => reportNameValuePairs?.reopenedAsReportID;

function ReportActionsListStateProvider({state, children}: ReportActionsListStateProviderProps) {
const {report, sortedReportActions, sortedVisibleReportActions, sortedAllReportActions} = state;
const [reopenedAsReportID] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`, {selector: reopenedAsReportIDSelector});

const paymentFilteredReportActions = report?.isWaitingOnBankAccount ? sortedReportActions.filter((action) => !shouldHidePayAction(action, true)) : sortedReportActions;
const paymentFilteredVisibleReportActions = report?.isWaitingOnBankAccount
? sortedVisibleReportActions.filter((action) => !shouldHidePayAction(action, true))
: sortedVisibleReportActions;
const surveyNameValuePairs = {reopenedAsReportID};
const surveyFilteredReportActions = filterHiddenSupportTicketSurveys({
reportActions: paymentFilteredReportActions,
sortedAllReportActions,
report,
reportNameValuePairs: surveyNameValuePairs,
});
const surveyFilteredVisibleReportActions = filterHiddenSupportTicketSurveys({
reportActions: paymentFilteredVisibleReportActions,
sortedAllReportActions,
report,
reportNameValuePairs: surveyNameValuePairs,
});

const value = {
...state,
sortedReportActions: surveyFilteredReportActions,
sortedVisibleReportActions: surveyFilteredVisibleReportActions,
scrollReportActions: paymentFilteredVisibleReportActions,
};

return <ReportActionsListStateContext.Provider value={value}>{children}</ReportActionsListStateContext.Provider>;
}

export default ReportActionsListStateProvider;
5 changes: 3 additions & 2 deletions src/pages/inbox/report/ReportActionsSkeletonGuard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import type {ReactNode} from 'react';
import React, {useEffect} from 'react';

import AskConciergeWelcome from './AskConciergeWelcome';
import {computeReportActionsSkeletonState, ReportActionsListActionsContext, ReportActionsListStateContext} from './ReportActionsListContext';
import {computeReportActionsSkeletonState, ReportActionsListActionsContext} from './ReportActionsListContext';
import ReportActionsListStateProvider from './ReportActionsListStateProvider';
import ReportActionsLoadingSkeleton from './ReportActionsLoadingSkeleton';

type ReportActionsSkeletonGuardProps = {
Expand Down Expand Up @@ -96,7 +97,7 @@ function ReportActionsSkeletonGuard({reportID, children}: ReportActionsSkeletonG

return (
<ReportActionsListActionsContext.Provider value={actions}>
<ReportActionsListStateContext.Provider value={state}>{children}</ReportActionsListStateContext.Provider>
<ReportActionsListStateProvider state={state}>{children}</ReportActionsListStateProvider>
</ReportActionsListActionsContext.Provider>
);
}
Expand Down
Loading
Loading