Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
03be3c8
Add selection mode Submit/Approve/Pay actions for mobile layout.
Krishna2323 Mar 19, 2026
250471a
Add ProcessMoneyReportHoldMenu to mobile selection mode
Krishna2323 Mar 19, 2026
9e3293c
Remove production gate from selection mode actions and add unit tests
Krishna2323 Mar 19, 2026
51c513d
Merge remote-tracking branch 'upstream/main' into krishna2323/issue/7…
Krishna2323 Mar 23, 2026
b74539f
fix ESLint.
Krishna2323 Mar 23, 2026
7ede93d
Fix selection mode actions parity between desktop and mobile
Krishna2323 Mar 23, 2026
0892245
Merge branch 'Expensify:main' into krishna2323/issue/72502-3
Krishna2323 Mar 25, 2026
8d6d5ca
Fix mobile selection mode parity issues with desktop implementation
Krishna2323 Mar 26, 2026
f320ba4
fix tests.
Krishna2323 Mar 26, 2026
d379acb
Add production gate and exit selection mode after report-level actions
Krishna2323 Mar 26, 2026
7394139
remove beta guard from MoneyReportHeader.
Krishna2323 Mar 26, 2026
1f93cfd
fix dropdown width issue and modal close lag.
Krishna2323 Mar 26, 2026
478765b
add missing invoiceReceiverPolicy param and clarify InteractionManage…
Krishna2323 Mar 30, 2026
6fde98e
make useSelectionModeReportActions React Compiler compatible
Krishna2323 Mar 30, 2026
0e86346
Merge branch 'Expensify:main' into krishna2323/issue/72502-3
Krishna2323 Apr 1, 2026
99b6e0f
fix ESLint.
Krishna2323 Apr 1, 2026
81c323e
Merge branch 'Expensify:main' into krishna2323/issue/72502-3
Krishna2323 Apr 2, 2026
35e49b5
fix: use ref-wrapping pattern for paymentSubMenuItems to avoid infini…
Krishna2323 Apr 2, 2026
f1cfe98
Merge branch 'main' into krishna2323/issue/72502-3
Krishna2323 Apr 3, 2026
a99e693
fix ESLint.
Krishna2323 Apr 3, 2026
80b4241
remove manual useMemo/useCallback from useSelectionModeReportActions …
Krishna2323 Apr 3, 2026
58f0ec2
add shouldBlockDirectPayment check, pass missing props to ProcessMone…
Krishna2323 Apr 3, 2026
fbde5d5
update tests.
Krishna2323 Apr 3, 2026
8ff44cf
use correct submit/approve button text for track-intent users and doc…
Krishna2323 Apr 3, 2026
08543a0
Merge branch 'Expensify:main' into krishna2323/issue/72502-3
Krishna2323 Apr 6, 2026
be2c121
Merge remote-tracking branch 'upstream/main' into krishna2323/issue/7…
Krishna2323 Apr 6, 2026
e9e4451
revert track-intent copy logic from selection mode actions.
Krishna2323 Apr 6, 2026
4f39d76
Merge branch 'main' into krishna2323/issue/72502-3
Krishna2323 Apr 7, 2026
8827c18
fix ESLint.
Krishna2323 Apr 7, 2026
2a07310
Merge branch 'Expensify:main' into krishna2323/issue/72502-3
Krishna2323 Apr 8, 2026
d71cb58
fix ESLint.
Krishna2323 Apr 8, 2026
422c9cb
Align non-reimbursable payment logic with desktop to prevent regressions
Krishna2323 Apr 8, 2026
9b6344e
Merge branch 'Expensify:main' into krishna2323/issue/72502-3
Krishna2323 Apr 9, 2026
cf711e4
Remove SELECTION_MODE_REPORT_ACTIONS beta gate from mobile
Krishna2323 Apr 9, 2026
3a67e41
Merge branch 'Expensify:main' into krishna2323/issue/72502-3
Krishna2323 Apr 9, 2026
cc74ecc
fix ESLint.
Krishna2323 Apr 9, 2026
3bdbf5d
Merge remote-tracking branch 'origin/main' into krishna2323/issue/725…
Krishna2323 Apr 9, 2026
58d51b6
Merge branch 'main' from upstream into krishna2323/issue/72502-3
Krishna2323 Apr 9, 2026
9fd4dfd
Rename checkForNecessaryAction to shouldBlockAction for bool naming c…
Krishna2323 Apr 9, 2026
7a867d9
Rename checkForNecessaryAction to shouldBlockAction in tests
Krishna2323 Apr 9, 2026
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
1 change: 1 addition & 0 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,7 @@ const CONST = {
SUGGESTED_FOLLOWUPS: 'suggestedFollowups',
FREEZE_CARD: 'freezeCard',
NEW_MANUAL_EXPENSE_FLOW: 'newManualExpenseFlow',
SELECTION_MODE_REPORT_ACTIONS: 'selectionModeReportActions',
},
BUTTON_STATES: {
DEFAULT: 'default',
Expand Down
9 changes: 2 additions & 7 deletions src/components/MoneyReportHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'
import useDefaultExpensePolicy from '@hooks/useDefaultExpensePolicy';
import useDeleteTransactions from '@hooks/useDeleteTransactions';
import useDuplicateTransactionsAndViolations from '@hooks/useDuplicateTransactionsAndViolations';
import useEnvironment from '@hooks/useEnvironment';
import useGetIOUReportFromReportAction from '@hooks/useGetIOUReportFromReportAction';
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
import useLocalize from '@hooks/useLocalize';
Expand Down Expand Up @@ -310,7 +309,6 @@ function MoneyReportHeader({reportID: reportIDProp, shouldDisplayBackButton = fa
const draftTransactionIDs = Object.keys(transactionDrafts ?? {});

const {translate, localeCompare, toLocaleDigit} = useLocalize();
const {isProduction} = useEnvironment();
const encryptedAuthToken = session?.encryptedAuthToken ?? '';

const exportTemplates = useMemo(
Expand Down Expand Up @@ -1593,9 +1591,6 @@ function MoneyReportHeader({reportID: reportIDProp, shouldDisplayBackButton = fa
}, [isDelegateAccessRestricted, showDelegateNoAccessModal, isAccountLocked, showLockedAccountModal, isUserValidated, moneyRequestReport]);

const selectionModeReportLevelActions = useMemo(() => {
if (isProduction) {
return [];
}
const actions: Array<DropdownOption<string> & Pick<PopoverMenuItem, 'backButtonText' | 'rightIcon'>> = [];
if (hasSubmitAction && !shouldBlockSubmit) {
actions.push({
Expand Down Expand Up @@ -1637,7 +1632,6 @@ function MoneyReportHeader({reportID: reportIDProp, shouldDisplayBackButton = fa
}
return actions;
}, [
isProduction,
hasSubmitAction,
shouldBlockSubmit,
hasApproveAction,
Expand Down Expand Up @@ -2331,7 +2325,8 @@ function MoneyReportHeader({reportID: reportIDProp, shouldDisplayBackButton = fa
const shouldShowSelectedTransactionsButton = !!selectedTransactionsOptions.length && !transactionThreadReportID;
const popoverUseScrollView = shouldPopoverUseScrollView(selectedTransactionsOptions);

const hasPayInSelectionMode = allExpensesSelected && hasPayAction;
const hasActualPaymentOptions = paymentButtonOptions.some((opt) => Object.values(CONST.IOU.PAYMENT_TYPE).some((type) => type === opt.value));
const hasPayInSelectionMode = allExpensesSelected && hasPayAction && hasActualPaymentOptions;

const makePaymentSelectHandler = useCallback(
(fromSelectionMode: boolean) => (event: KYCFlowEvent, iouPaymentType: PaymentMethodType, triggerKYCFlow: TriggerKYCFlow) => {
Expand Down
3 changes: 2 additions & 1 deletion src/components/MoneyReportHeaderKYCDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useThemeStyles from '@hooks/useThemeStyles';
import {isSecondaryActionAPaymentOption} from '@libs/PaymentUtils';
import type {KYCFlowEvent, TriggerKYCFlow} from '@libs/PaymentUtils';
import shouldPopoverUseScrollView from '@libs/shouldPopoverUseScrollView';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';
import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage';
Expand Down Expand Up @@ -82,7 +83,7 @@ function MoneyReportHeaderKYCDropdown({
}}
buttonRef={buttonRef}
shouldAlwaysShowDropdownMenu
shouldPopoverUseScrollView={applicableSecondaryActions.length >= CONST.DROPDOWN_SCROLL_THRESHOLD}
shouldPopoverUseScrollView={shouldPopoverUseScrollView(applicableSecondaryActions)}
customText={customText ?? translate('common.more')}
options={applicableSecondaryActions}
isSplitButton={false}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ import {useDelegateNoAccessActions, useDelegateNoAccessState} from '@components/
import FlatListWithScrollKey from '@components/FlatList/FlatListWithScrollKey';
import HoldOrRejectEducationalModal from '@components/HoldOrRejectEducationalModal';
import {ModalActions} from '@components/Modal/Global/ModalContext';
import MoneyReportHeaderKYCDropdown from '@components/MoneyReportHeaderKYCDropdown';
import OfflineWithFeedback from '@components/OfflineWithFeedback';
import {usePersonalDetails} from '@components/OnyxListItemProvider';
import {PressableWithFeedback} from '@components/Pressable';
import ProcessMoneyReportHoldMenu from '@components/ProcessMoneyReportHoldMenu';
import ScrollView from '@components/ScrollView';
import {useSearchActionsContext, useSearchStateContext} from '@components/Search/SearchContext';
import Text from '@components/Text';
Expand All @@ -36,6 +38,7 @@ import useReportScrollManager from '@hooks/useReportScrollManager';
import useResponsiveLayoutOnWideRHP from '@hooks/useResponsiveLayoutOnWideRHP';
import useScrollToEndOnNewMessageReceived from '@hooks/useScrollToEndOnNewMessageReceived';
import useSelectedTransactionsActions from '@hooks/useSelectedTransactionsActions';
import useSelectionModeReportActions from '@hooks/useSelectionModeReportActions';
import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import {dismissRejectUseExplanation} from '@libs/actions/IOU';
Expand Down Expand Up @@ -222,6 +225,36 @@ function MoneyRequestReportActionsList({

const isMobileSelectionModeEnabled = useMobileSelectionMode();
const {showConfirmModal} = useConfirmModal();

const {
selectionModeReportLevelActions,
allExpensesSelected,
hasPayInSelectionMode,
onSelectionModePaymentSelect,
selectionModeKYCSuccess,
primaryAction,
kycWallRef,
isHoldMenuVisible,
requestType,
paymentType,
selectedVBBAToPayFromHoldMenu,
handleHoldMenuClose,
handleHoldMenuConfirm,
hasOnlyHeldExpenses,
nonHeldAmount,
fullAmount,
hasValidNonHeldAmount,
} = useSelectionModeReportActions({
report,
chatReport,
policy,
reportActions,
reportNameValuePairs,
reportMetadata,
transactions: transactionsWithoutPendingDelete,
selectedTransactionIDs,
});

const beginExportWithTemplate = useCallback(
(templateName: string, templateType: string, transactionIDList: string[]) => {
if (isOffline) {
Expand Down Expand Up @@ -302,7 +335,7 @@ function MoneyRequestReportActionsList({
const [rejectModalAction, setRejectModalAction] = useState<ValueOf<typeof CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.REJECT_BULK> | null>(null);

const selectedTransactionsOptions = useMemo(() => {
return originalSelectedTransactionsOptions.map((option) => {
const mappedOptions = originalSelectedTransactionsOptions.map((option) => {
if (option.value === CONST.REPORT.SECONDARY_ACTIONS.REJECT) {
return {
...option,
Expand All @@ -322,7 +355,12 @@ function MoneyRequestReportActionsList({
}
return option;
});
}, [originalSelectedTransactionsOptions, dismissedRejectUseExplanation, isDelegateAccessRestricted, showDelegateNoAccessModal]);

if (allExpensesSelected && selectionModeReportLevelActions.length) {
return [...selectionModeReportLevelActions, ...mappedOptions];
}
return mappedOptions;
}, [originalSelectedTransactionsOptions, dismissedRejectUseExplanation, isDelegateAccessRestricted, showDelegateNoAccessModal, allExpensesSelected, selectionModeReportLevelActions]);

const popoverUseScrollView = shouldPopoverUseScrollView(selectedTransactionsOptions);

Expand Down Expand Up @@ -715,7 +753,6 @@ function MoneyRequestReportActionsList({
isReportArchived,
reportNameValuePairs?.origin,
reportNameValuePairs?.originalID,
isOffline,
],
);

Expand Down Expand Up @@ -785,17 +822,33 @@ function MoneyRequestReportActionsList({
>
{shouldUseNarrowLayout && isMobileSelectionModeEnabled && (
<OfflineWithFeedback pendingAction={reportPendingAction}>
<ButtonWithDropdownMenu
onPress={() => null}
options={selectedTransactionsOptions}
customText={translate('workspace.common.selected', {
count: selectedTransactionIDs.length,
})}
isSplitButton={false}
shouldAlwaysShowDropdownMenu
shouldPopoverUseScrollView={popoverUseScrollView}
wrapperStyle={[styles.w100, styles.ph5]}
/>
{hasPayInSelectionMode ? (
<View style={styles.ph5}>
<MoneyReportHeaderKYCDropdown
chatReportID={chatReport?.reportID}
iouReport={report}
onPaymentSelect={onSelectionModePaymentSelect}
onSuccessfulKYC={selectionModeKYCSuccess}
primaryAction={primaryAction}
applicableSecondaryActions={selectedTransactionsOptions}
customText={translate('workspace.common.selected', {count: selectedTransactionIDs.length})}
shouldShowSuccessStyle
ref={kycWallRef}
/>
</View>
) : (
<ButtonWithDropdownMenu
onPress={() => null}
options={selectedTransactionsOptions}
customText={translate('workspace.common.selected', {
count: selectedTransactionIDs.length,
})}
isSplitButton={false}
shouldAlwaysShowDropdownMenu
shouldPopoverUseScrollView={popoverUseScrollView}
wrapperStyle={[styles.w100, styles.ph5]}
/>
)}
<View style={[styles.alignItemsCenter, styles.userSelectNone, styles.flexRow, styles.pt6, styles.ph8, styles.pb3]}>
<Checkbox
accessibilityLabel={translate('accessibilityHints.selectAllItems')}
Expand Down Expand Up @@ -916,6 +969,20 @@ function MoneyRequestReportActionsList({
onConfirm={dismissRejectModalBasedOnAction}
/>
)}
<ProcessMoneyReportHoldMenu
nonHeldAmount={!hasOnlyHeldExpenses && hasValidNonHeldAmount ? nonHeldAmount : undefined}
requestType={requestType}
fullAmount={fullAmount}
onClose={handleHoldMenuClose}
isVisible={isHoldMenuVisible}
paymentType={paymentType}
methodID={paymentType === CONST.IOU.PAYMENT_TYPE.VBBA ? selectedVBBAToPayFromHoldMenu : undefined}
chatReport={chatReport}
moneyRequestReport={report}
hasNonHeldExpenses={!hasOnlyHeldExpenses}
startAnimation={handleHoldMenuConfirm}
transactionCount={transactions.length}
/>
</View>
);
}
Expand Down
Loading
Loading