diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index 296b76593f6..893fd59e38b 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -193,7 +193,7 @@ const ROUTES = {
},
SETTINGS_CONTACT_METHOD_DETAILS: {
route: 'settings/profile/contact-methods/:contactMethod/details',
- getRoute: (contactMethod: string) => `settings/profile/contact-methods/${encodeURIComponent(contactMethod)}/details` as const,
+ getRoute: (contactMethod: string, backTo?: string) => getUrlWithBackToParam(`settings/profile/contact-methods/${encodeURIComponent(contactMethod)}/details`, backTo),
},
SETTINGS_NEW_CONTACT_METHOD: {
route: 'settings/profile/contact-methods/new',
diff --git a/src/components/ValidateAccountMessage.tsx b/src/components/ValidateAccountMessage.tsx
new file mode 100644
index 00000000000..be43c298596
--- /dev/null
+++ b/src/components/ValidateAccountMessage.tsx
@@ -0,0 +1,56 @@
+import React from 'react';
+import {View} from 'react-native';
+import {useOnyx} from 'react-native-onyx';
+import useLocalize from '@hooks/useLocalize';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import Navigation from '@libs/Navigation/Navigation';
+import variables from '@styles/variables';
+import * as Session from '@userActions/Session';
+import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
+import Icon from './Icon';
+import * as Expensicons from './Icon/Expensicons';
+import Text from './Text';
+import TextLink from './TextLink';
+
+type ValidateAccountMessageProps = {backTo?: string | undefined};
+function ValidateAccountMessage({backTo}: ValidateAccountMessageProps) {
+ const theme = useTheme();
+ const styles = useThemeStyles();
+ const {translate} = useLocalize();
+ const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST);
+ const loginNames = Object.keys(loginList ?? {});
+
+ return (
+
+
+
+
+ {translate('bankAccount.validateAccountError.phrase1')}
+ Session.signOutAndRedirectToSignIn()}
+ >
+ {translate('bankAccount.validateAccountError.phrase2')}
+
+ {translate('bankAccount.validateAccountError.phrase3')}
+ {
+ const login = loginList?.[loginNames?.[0]] ?? {};
+ Navigation.navigate(ROUTES.SETTINGS_CONTACT_METHOD_DETAILS.getRoute(login?.partnerUserID ?? loginNames?.[0], backTo));
+ }}
+ >
+ {translate('bankAccount.validateAccountError.phrase4')}
+
+ .
+
+
+ );
+}
+
+export default ValidateAccountMessage;
diff --git a/src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts b/src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts
index 1bb9cce7e64..611831544bd 100644
--- a/src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts
+++ b/src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts
@@ -124,11 +124,7 @@ function getMatchingRootRouteForRHPRoute(route: NavigationPartialRoute): Navigat
// If there is rhpNavigator in the state generated for backTo url, we want to get root route matching to this rhp screen.
if (rhpNavigator && rhpNavigator.state) {
- const isRHPinState = stateForBackTo.routes[0].name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR;
-
- if (isRHPinState) {
- return getMatchingRootRouteForRHPRoute(findFocusedRoute(stateForBackTo) as NavigationPartialRoute);
- }
+ return getMatchingRootRouteForRHPRoute(findFocusedRoute(stateForBackTo) as NavigationPartialRoute);
}
// If we know that backTo targets the root route (central pane or full screen) we want to use it.
diff --git a/src/pages/ReimbursementAccount/BankAccountStep.tsx b/src/pages/ReimbursementAccount/BankAccountStep.tsx
index 689b646f465..69e60587872 100644
--- a/src/pages/ReimbursementAccount/BankAccountStep.tsx
+++ b/src/pages/ReimbursementAccount/BankAccountStep.tsx
@@ -14,16 +14,14 @@ import ScrollView from '@components/ScrollView';
import Section from '@components/Section';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
+import ValidateAccountMessage from '@components/ValidateAccountMessage';
import useLocalize from '@hooks/useLocalize';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import getPlaidDesktopMessage from '@libs/getPlaidDesktopMessage';
-import Navigation from '@libs/Navigation/Navigation';
-import variables from '@styles/variables';
import * as BankAccounts from '@userActions/BankAccounts';
import * as Link from '@userActions/Link';
import * as ReimbursementAccount from '@userActions/ReimbursementAccount';
-import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
@@ -38,9 +36,6 @@ type BankAccountStepOnyxProps = {
/** If the plaid button has been disabled */
isPlaidDisabled: OnyxEntry;
-
- /** Login list for the user that is signed in */
- loginList: OnyxEntry;
};
type BankAccountStepProps = BankAccountStepOnyxProps & {
@@ -73,7 +68,6 @@ function BankAccountStep({
receivedRedirectURI,
reimbursementAccount,
onBackButtonPress,
- loginList,
isPlaidDisabled = false,
}: BankAccountStepProps) {
const theme = useTheme();
@@ -86,7 +80,6 @@ function BankAccountStep({
}
const plaidDesktopMessage = getPlaidDesktopMessage();
const bankAccountRoute = `${ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute('new', policyID, ROUTES.WORKSPACE_INITIAL.getRoute(policyID))}`;
- const loginNames = Object.keys(loginList ?? {});
const removeExistingBankAccountDetails = () => {
const bankAccountData: Partial = {
@@ -168,35 +161,7 @@ function BankAccountStep({
/>
- {!user?.validated && (
-
-
-
-
- {translate('bankAccount.validateAccountError.phrase1')}
- Session.signOutAndRedirectToSignIn()}
- >
- {translate('bankAccount.validateAccountError.phrase2')}
-
- {translate('bankAccount.validateAccountError.phrase3')}
- {
- const login = loginList?.[loginNames?.[0]] ?? {};
- Navigation.navigate(ROUTES.SETTINGS_CONTACT_METHOD_DETAILS.getRoute(login?.partnerUserID ?? loginNames?.[0]));
- }}
- >
- {translate('bankAccount.validateAccountError.phrase4')}
-
- .
-
-
- )}
+ {!user?.validated && }
{translate('common.privacy')}
({
isPlaidDisabled: {
key: ONYXKEYS.IS_PLAID_DISABLED,
},
- loginList: {
- key: ONYXKEYS.LOGIN_LIST,
- },
})(BankAccountStep);
diff --git a/src/pages/settings/Security/TwoFactorAuth/Steps/CodesStep.tsx b/src/pages/settings/Security/TwoFactorAuth/Steps/CodesStep.tsx
index edda91d4a8e..dd3d3b87a12 100644
--- a/src/pages/settings/Security/TwoFactorAuth/Steps/CodesStep.tsx
+++ b/src/pages/settings/Security/TwoFactorAuth/Steps/CodesStep.tsx
@@ -1,3 +1,5 @@
+import type {RouteProp} from '@react-navigation/native';
+import {useRoute} from '@react-navigation/native';
import React, {useEffect, useState} from 'react';
import {ActivityIndicator, View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
@@ -10,13 +12,14 @@ import PressableWithDelayToggle from '@components/Pressable/PressableWithDelayTo
import ScrollView from '@components/ScrollView';
import Section from '@components/Section';
import Text from '@components/Text';
+import ValidateAccountMessage from '@components/ValidateAccountMessage';
import useLocalize from '@hooks/useLocalize';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import Clipboard from '@libs/Clipboard';
import localFileDownload from '@libs/localFileDownload';
-import type {BackToParams} from '@libs/Navigation/types';
+import type {BackToParams, SettingsNavigatorParamList} from '@libs/Navigation/types';
import StepWrapper from '@pages/settings/Security/TwoFactorAuth/StepWrapper/StepWrapper';
import useTwoFactorAuthContext from '@pages/settings/Security/TwoFactorAuth/TwoFactorAuthContext/useTwoFactorAuth';
import type {BaseTwoFactorAuthFormOnyxProps} from '@pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/types';
@@ -24,26 +27,30 @@ import * as Session from '@userActions/Session';
import * as TwoFactorAuthActions from '@userActions/TwoFactorAuthActions';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
+import type SCREENS from '@src/SCREENS';
type CodesStepProps = BaseTwoFactorAuthFormOnyxProps & BackToParams;
-function CodesStep({account, backTo}: CodesStepProps) {
+function CodesStep({account, user, backTo}: CodesStepProps) {
const theme = useTheme();
const styles = useThemeStyles();
const {translate} = useLocalize();
const {isExtraSmallScreenWidth, isSmallScreenWidth} = useResponsiveLayout();
const [error, setError] = useState('');
+ const isUserValidated = user?.validated;
+ const route = useRoute>();
const {setStep} = useTwoFactorAuthContext();
useEffect(() => {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
- if (account?.requiresTwoFactorAuth || account?.recoveryCodes) {
+ if (account?.requiresTwoFactorAuth || account?.recoveryCodes || !isUserValidated) {
return;
}
Session.toggleTwoFactorAuth(true);
// eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps -- We want to run this when component mounts
- }, []);
+ }, [isUserValidated]);
return (
TwoFactorAuthActions.quitAndNavigateBack(backTo)}
>
-
-
- {translate('twoFactorAuth.codesLoseAccess')}
-
-
- {account?.isLoading ? (
-
-
-
- ) : (
- <>
-
- {!!account?.recoveryCodes &&
- account?.recoveryCodes?.split(', ').map((code) => (
-
- {code}
-
- ))}
+ {isUserValidated && (
+
+
+ {translate('twoFactorAuth.codesLoseAccess')}
+
+
+ {account?.isLoading ? (
+
+
-
- {
- Clipboard.setString(account?.recoveryCodes ?? '');
- setError('');
- TwoFactorAuthActions.setCodesAreCopied();
- }}
- styles={[styles.button, styles.buttonMedium, styles.twoFactorAuthCodesButton]}
- textStyles={[styles.buttonMediumText]}
- accessible={false}
- tooltipText=""
- tooltipTextChecked=""
- />
- {
- localFileDownload('two-factor-auth-codes', account?.recoveryCodes ?? '');
- setError('');
- TwoFactorAuthActions.setCodesAreCopied();
- }}
- inline={false}
- styles={[styles.button, styles.buttonMedium, styles.twoFactorAuthCodesButton]}
- textStyles={[styles.buttonMediumText]}
- accessible={false}
- tooltipText=""
- tooltipTextChecked=""
- />
-
- >
- )}
-
-
+ ) : (
+ <>
+
+ {!!account?.recoveryCodes &&
+ account?.recoveryCodes?.split(', ').map((code) => (
+
+ {code}
+
+ ))}
+
+
+ {
+ Clipboard.setString(account?.recoveryCodes ?? '');
+ setError('');
+ TwoFactorAuthActions.setCodesAreCopied();
+ }}
+ styles={[styles.button, styles.buttonMedium, styles.twoFactorAuthCodesButton]}
+ textStyles={[styles.buttonMediumText]}
+ accessible={false}
+ tooltipText=""
+ tooltipTextChecked=""
+ />
+ {
+ localFileDownload('two-factor-auth-codes', account?.recoveryCodes ?? '');
+ setError('');
+ TwoFactorAuthActions.setCodesAreCopied();
+ }}
+ inline={false}
+ styles={[styles.button, styles.buttonMedium, styles.twoFactorAuthCodesButton]}
+ textStyles={[styles.buttonMediumText]}
+ accessible={false}
+ tooltipText=""
+ tooltipTextChecked=""
+ />
+
+ >
+ )}
+
+
+ )}
+ {!isUserValidated && }
{!!error && (
{
if (!account?.codesAreCopied) {
@@ -151,4 +162,7 @@ CodesStep.displayName = 'CodesStep';
export default withOnyx({
account: {key: ONYXKEYS.ACCOUNT},
+ user: {
+ key: ONYXKEYS.USER,
+ },
})(CodesStep);
diff --git a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/types.ts b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/types.ts
index baac250a3d6..97510a2a3a2 100644
--- a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/types.ts
+++ b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/types.ts
@@ -1,9 +1,10 @@
import type {ForwardedRef} from 'react';
import type {OnyxEntry} from 'react-native-onyx';
-import type {Account} from '@src/types/onyx';
+import type {Account, User} from '@src/types/onyx';
type BaseTwoFactorAuthFormOnyxProps = {
account: OnyxEntry;
+ user?: OnyxEntry;
};
type BaseTwoFactorAuthFormRef = {