Skip to content
Open
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 @@ -333,10 +333,11 @@ function MoneyReportHeaderSelectionDropdown({reportID, primaryAction, isReportIn
iouReport={moneyRequestReport}
onPaymentSelect={onSelectionModePaymentSelect}
onWorkspacePolicySelect={(selectedPolicy, triggerKYCFlow) => {
if (shouldBlockAction(undefined, true)) {
const continueWithWorkspace = () => triggerKYCFlow({policy: selectedPolicy});
if (shouldBlockAction(undefined, true, continueWithWorkspace)) {
return;
}
triggerKYCFlow({policy: selectedPolicy});
continueWithWorkspace();
}}
onSuccessfulKYC={selectionModeKYCSuccess}
primaryAction={primaryAction}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,10 +262,11 @@ function SelectionToolbar({reportID, transactions, reportActions}: SelectionTool
onSelectionModePaymentSelect={onSelectionModePaymentSelect}
selectionModeKYCSuccess={selectionModeKYCSuccess}
onWorkspacePolicySelect={(selectedPolicy, triggerKYCFlow) => {
if (shouldBlockAction(undefined, true)) {
const continueWithWorkspace = () => triggerKYCFlow({policy: selectedPolicy});
if (shouldBlockAction(undefined, true, continueWithWorkspace)) {
return;
}
triggerKYCFlow({policy: selectedPolicy});
continueWithWorkspace();
}}
primaryAction={primaryAction}
selectedTransactionsOptions={selectedTransactionsOptions}
Expand Down
24 changes: 13 additions & 11 deletions src/hooks/useSelectionModePayment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import {payInvoice, payMoneyRequest} from '@libs/actions/IOU/PayMoneyRequest';
import {generateDefaultWorkspaceName} from '@libs/actions/Policy/Policy';
import deferModalPresentationAfterPopoverDismiss from '@libs/deferModalPresentationAfterPopoverDismiss';
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
import Navigation from '@libs/Navigation/Navigation';
import {isTrackOnboardingChoice} from '@libs/OnboardingUtils';
import type {KYCFlowEvent, TriggerKYCFlow, WorkspacePolicyPaymentOption} from '@libs/PaymentUtils';
import {selectPaymentType} from '@libs/PaymentUtils';
Expand All @@ -22,11 +20,10 @@ import refreshSearchAfterReportAction from '@libs/SearchRefreshUtils';

import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import {DYNAMIC_ROUTES} from '@src/ROUTES';
import type * as OnyxTypes from '@src/types/onyx';
import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage';

import {delegateEmailSelector, isUserValidatedSelector} from '@selectors/Account';
import {delegateEmailSelector} from '@selectors/Account';
import {hasSeenTourSelector} from '@selectors/Onboarding';
import {personalDetailsLoginSelector} from '@selectors/PersonalDetails';
import truncate from 'lodash/truncate';
Expand All @@ -46,6 +43,7 @@ import usePaymentOptions from './usePaymentOptions';
import usePermissions from './usePermissions';
import usePolicy from './usePolicy';
import useSearchShouldCalculateTotals from './useSearchShouldCalculateTotals';
import useVerifyAccountAndResume from './useVerifyAccountAndResume';

type HoldMenuOpenParams = {
requestType: ActionHandledType;
Expand Down Expand Up @@ -96,7 +94,6 @@ function useSelectionModePayment({
const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(moneyRequestReport?.chatReportID)}`);
const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getNonEmptyStringOnyxID(moneyRequestReport?.policyID)}`);
const [session] = useOnyx(ONYXKEYS.SESSION);
const [isUserValidated] = useOnyx(ONYXKEYS.ACCOUNT, {selector: isUserValidatedSelector});
const [delegateEmail] = useOnyx(ONYXKEYS.ACCOUNT, {selector: delegateEmailSelector});
const [allTransactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS);
const [nextStep] = useOnyx(`${ONYXKEYS.COLLECTION.NEXT_STEP}${getNonEmptyStringOnyxID(moneyRequestReport?.reportID)}`);
Expand Down Expand Up @@ -124,6 +121,9 @@ function useSelectionModePayment({
const {showLockedAccountModal} = useLockedAccountActions();
const kycWallRef = useContext(KYCWallContext);

// Store the pending payment and resume it after the user validates, instead of dropping it on the way to the magic-code screen.
const {isUserValidated, verifyAccountAndResume} = useVerifyAccountAndResume((retry) => retry?.());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Re-check locks before resuming selection payments

When an unvalidated user starts a selection-mode payment, this resume handler invokes the stored retry directly after magic-code validation. That retry is the press-time closure, so if NVP_PRIVATE_LOCK_ACCOUNT_DETAILS loads late or the account becomes locked while the verify-account screen is open, the resumed flow bypasses shouldBlockAction and confirmPayment does not re-check isAccountLocked, allowing the payment/KYC flow to continue instead of showing the locked-account modal. Please re-run the current non-validation blockers before executing the stored retry.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is getting account locked while typing the verification code a realistic scenario ? I'd say no


const expensifyIcons = useMemoizedLazyExpensifyIcons(['Cash', 'ArrowRight', 'Building'] as const);

const hasViolations = hasViolationsReportUtils(moneyRequestReport?.reportID, allTransactionViolations, accountID, email ?? '');
Expand All @@ -138,7 +138,7 @@ function useSelectionModePayment({
}
};

const shouldBlockAction = (paymentMethodType?: PaymentMethodType, deferBlockingPresentation = false) => {
const shouldBlockAction = (paymentMethodType?: PaymentMethodType, deferBlockingPresentation = false, retry?: () => void) => {
if (isDelegateAccessRestricted) {
presentBlockingAction(showDelegateNoAccessModal, deferBlockingPresentation);
return true;
Expand All @@ -148,7 +148,7 @@ function useSelectionModePayment({
return true;
}
if (!isUserValidated && paymentMethodType !== CONST.IOU.PAYMENT_TYPE.ELSEWHERE) {
presentBlockingAction(() => Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.VERIFY_ACCOUNT.path)), deferBlockingPresentation);
presentBlockingAction(() => verifyAccountAndResume(retry), deferBlockingPresentation);
return true;
}
return false;
Expand Down Expand Up @@ -265,10 +265,11 @@ function useSelectionModePayment({
})();

const handleWorkspaceSelected = (wp: OnyxTypes.Policy) => {
if (shouldBlockAction(undefined, true)) {
const continueWithWorkspace = () => kycWallRef.current?.continueAction?.({policy: wp});
if (shouldBlockAction(undefined, true, continueWithWorkspace)) {
return;
}
kycWallRef.current?.continueAction?.({policy: wp});
continueWithWorkspace();
};

const paymentSubMenuItems: PopoverMenuItem[] = (() => {
Expand Down Expand Up @@ -318,10 +319,11 @@ function useSelectionModePayment({
};

const onSelectionModePaymentSelect = (event: KYCFlowEvent, iouPaymentType: PaymentMethodType, triggerKYCFlow: TriggerKYCFlow) => {
if (shouldBlockAction(iouPaymentType, true)) {
const resumePaymentSelect = () => invokePaymentSelect(event, iouPaymentType, triggerKYCFlow);
if (shouldBlockAction(iouPaymentType, true, resumePaymentSelect)) {
return;
}
invokePaymentSelect(event, iouPaymentType, triggerKYCFlow);
resumePaymentSelect();
};

const selectionModeKYCSuccess = (type?: PaymentMethodType) => {
Expand Down
5 changes: 3 additions & 2 deletions src/hooks/useSelectionModeReportActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,11 @@ function useSelectionModeReportActions({
const onSelectionModePaymentSelect = (event: KYCFlowEvent, iouPaymentType: PaymentMethodType, triggerKYCFlow: TriggerKYCFlow) => {
TransitionTracker.runAfterTransitions({
callback: () => {
if (shouldBlockAction(iouPaymentType)) {
const resumePaymentSelect = () => invokePaymentSelect(event, iouPaymentType, triggerKYCFlow);
if (shouldBlockAction(iouPaymentType, false, resumePaymentSelect)) {
return;
}
invokePaymentSelect(event, iouPaymentType, triggerKYCFlow);
resumePaymentSelect();
},
waitForUpcomingTransition: true,
});
Expand Down
Loading