Skip to content

Commit

Permalink
Merge pull request Expensify#23060 from koko57/fix/19496-2fa-steps-re…
Browse files Browse the repository at this point in the history
…factor

Fix/19496 2fa steps refactor
  • Loading branch information
deetergp authored Aug 18, 2023
2 parents 3d07591 + 30ca6de commit 582aa46
Show file tree
Hide file tree
Showing 27 changed files with 694 additions and 579 deletions.
11 changes: 11 additions & 0 deletions src/CONST.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ const CONST = {
ANIMATED_TRANSITION: 300,
ANIMATED_TRANSITION_FROM_VALUE: 100,
ANIMATION_IN_TIMING: 100,
ANIMATION_DIRECTION: {
IN: 'in',
OUT: 'out',
},
ARROW_HIDE_DELAY: 3000,

API_ATTACHMENT_VALIDATIONS: {
Expand Down Expand Up @@ -2534,6 +2538,13 @@ const CONST = {
AFTER_WEEK: 'afterWeek',
CUSTOM: 'custom',
},
TWO_FACTOR_AUTH_STEPS: {
CODES: 'CODES',
VERIFY: 'VERIFY',
SUCCESS: 'SUCCESS',
ENABLED: 'ENABLED',
DISABLED: 'DISABLED',
},
TAB: {
RECEIPT_TAB_ID: 'ReceiptTab',
MANUAL: 'manual',
Expand Down
6 changes: 1 addition & 5 deletions src/ROUTES.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,7 @@ export default {
SETTINGS_CONTACT_METHOD_DETAILS: `${SETTINGS_CONTACT_METHODS}/:contactMethod/details`,
getEditContactMethodRoute: (contactMethod) => `${SETTINGS_CONTACT_METHODS}/${encodeURIComponent(contactMethod)}/details`,
SETTINGS_NEW_CONTACT_METHOD: `${SETTINGS_CONTACT_METHODS}/new`,
SETTINGS_2FA_IS_ENABLED: 'settings/security/two-factor-auth/enabled',
SETTINGS_2FA_DISABLE: 'settings/security/two-factor-auth/disable',
SETTINGS_2FA_CODES: 'settings/security/two-factor-auth/codes',
SETTINGS_2FA_VERIFY: 'settings/security/two-factor-auth/verify',
SETTINGS_2FA_SUCCESS: 'settings/security/two-factor-auth/success',
SETTINGS_2FA: 'settings/security/two-factor-auth',
SETTINGS_STATUS,
SETTINGS_STATUS_SET,
NEW_GROUP: 'new/group',
Expand Down
5 changes: 5 additions & 0 deletions src/components/AnimatedStep/AnimatedStepContext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import {createContext} from 'react';

const AnimatedStepContext = createContext();

export default AnimatedStepContext;
17 changes: 17 additions & 0 deletions src/components/AnimatedStep/AnimatedStepProvider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React, {useState} from 'react';
import PropTypes from 'prop-types';
import AnimatedStepContext from './AnimatedStepContext';
import CONST from '../../CONST';

const propTypes = {
children: PropTypes.node.isRequired,
};

function AnimatedStepProvider({children}) {
const [animationDirection, setAnimationDirection] = useState(CONST.ANIMATION_DIRECTION.IN);

return <AnimatedStepContext.Provider value={{animationDirection, setAnimationDirection}}>{children}</AnimatedStepContext.Provider>;
}

AnimatedStepProvider.propTypes = propTypes;
export default AnimatedStepProvider;
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import * as Animatable from 'react-native-animatable';
import CONST from '../CONST';
import styles from '../styles/styles';
import CONST from '../../CONST';
import styles from '../../styles/styles';

const propTypes = {
/** Children to wrap in AnimatedStep. */
Expand All @@ -14,27 +14,37 @@ const propTypes = {

/** Whether we're animating the step in or out */
direction: PropTypes.oneOf(['in', 'out']),

/** Callback to fire when the animation ends */
onAnimationEnd: PropTypes.func,
};

const defaultProps = {
direction: 'in',
style: [],
onAnimationEnd: () => {},
};

function AnimatedStep(props) {
function getAnimationStyle(direction) {
let animationStyle;

if (direction === 'in') {
animationStyle = styles.makeSlideInTranslation('translateX', CONST.ANIMATED_TRANSITION_FROM_VALUE);
} else if (direction === 'out') {
animationStyle = styles.makeSlideInTranslation('translateX', -CONST.ANIMATED_TRANSITION_FROM_VALUE);
}
return animationStyle;
function getAnimationStyle(direction) {
let transitionValue;

if (direction === 'in') {
transitionValue = CONST.ANIMATED_TRANSITION_FROM_VALUE;
} else if (direction === 'out') {
transitionValue = -CONST.ANIMATED_TRANSITION_FROM_VALUE;
}
return styles.makeSlideInTranslation('translateX', transitionValue);
}

function AnimatedStep(props) {
return (
<Animatable.View
onAnimationEnd={() => {
if (!props.onAnimationEnd) {
return;
}
props.onAnimationEnd();
}}
duration={CONST.ANIMATED_TRANSITION}
animation={getAnimationStyle(props.direction)}
useNativeDriver
Expand Down
12 changes: 12 additions & 0 deletions src/components/AnimatedStep/useAnimatedStepContext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {useContext} from 'react';
import AnimatedStepContext from './AnimatedStepContext';

function useAnimatedStepContext() {
const context = useContext(AnimatedStepContext);
if (!context) {
throw new Error('useAnimatedStepContext must be used within an AnimatedStepContextProvider');
}
return context;
}

export default useAnimatedStepContext;
34 changes: 3 additions & 31 deletions src/libs/Navigation/AppNavigator/ModalStackNavigators.js
Original file line number Diff line number Diff line change
Expand Up @@ -637,38 +637,10 @@ const SettingsModalStackNavigator = createModalStackNavigator([
},
{
getComponent: () => {
const SettingsTwoFactorAuthIsEnabled = require('../../../pages/settings/Security/TwoFactorAuth/IsEnabledPage').default;
return SettingsTwoFactorAuthIsEnabled;
const SettingsTwoFactorAuth = require('../../../pages/settings/Security/TwoFactorAuth/TwoFactorAuthPage').default;
return SettingsTwoFactorAuth;
},
name: 'Settings_TwoFactorAuthIsEnabled',
},
{
getComponent: () => {
const SettingsTwoFactorAuthDisable = require('../../../pages/settings/Security/TwoFactorAuth/DisablePage').default;
return SettingsTwoFactorAuthDisable;
},
name: 'Settings_TwoFactorAuthDisable',
},
{
getComponent: () => {
const SettingsTwoFactorAuthCodes = require('../../../pages/settings/Security/TwoFactorAuth/CodesPage').default;
return SettingsTwoFactorAuthCodes;
},
name: 'Settings_TwoFactorAuthCodes',
},
{
getComponent: () => {
const SettingsTwoFactorAuthVerify = require('../../../pages/settings/Security/TwoFactorAuth/VerifyPage').default;
return SettingsTwoFactorAuthVerify;
},
name: 'Settings_TwoFactorAuthVerify',
},
{
getComponent: () => {
const SettingsTwoFactorAuthSuccess = require('../../../pages/settings/Security/TwoFactorAuth/SuccessPage').default;
return SettingsTwoFactorAuthSuccess;
},
name: 'Settings_TwoFactorAuthSuccess',
name: 'Settings_TwoFactorAuth',
},
]);

Expand Down
20 changes: 2 additions & 18 deletions src/libs/Navigation/linkingConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,24 +156,8 @@ export default {
path: ROUTES.SETTINGS_PERSONAL_DETAILS_ADDRESS,
exact: true,
},
Settings_TwoFactorAuthIsEnabled: {
path: ROUTES.SETTINGS_2FA_IS_ENABLED,
exact: true,
},
Settings_TwoFactorAuthDisable: {
path: ROUTES.SETTINGS_2FA_DISABLE,
exact: true,
},
Settings_TwoFactorAuthCodes: {
path: ROUTES.SETTINGS_2FA_CODES,
exact: true,
},
Settings_TwoFactorAuthVerify: {
path: ROUTES.SETTINGS_2FA_VERIFY,
exact: true,
},
Settings_TwoFactorAuthSuccess: {
path: ROUTES.SETTINGS_2FA_SUCCESS,
Settings_TwoFactorAuth: {
path: ROUTES.SETTINGS_2FA,
exact: true,
},
Settings_Share_Code: {
Expand Down
22 changes: 17 additions & 5 deletions src/libs/actions/TwoFactorAuthActions.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
import Onyx from 'react-native-onyx';
import ONYXKEYS from '../../ONYXKEYS';
import Navigation from '../Navigation/Navigation';
import ROUTES from '../../ROUTES';

/**
* Clear 2FA data if the flow is interrupted without finishing
*/
function clearTwoFactorAuthData() {
Onyx.merge(ONYXKEYS.ACCOUNT, {recoveryCodes: '', twoFactorAuthSecretKey: ''});
Onyx.merge(ONYXKEYS.ACCOUNT, {recoveryCodes: '', twoFactorAuthSecretKey: '', twoFactorAuthStep: '', codesAreCopied: false});
}

export {
// eslint-disable-next-line import/prefer-default-export
clearTwoFactorAuthData,
};
function setTwoFactorAuthStep(twoFactorAuthStep) {
Onyx.merge(ONYXKEYS.ACCOUNT, {twoFactorAuthStep});
}

function setCodesAreCopied() {
Onyx.merge(ONYXKEYS.ACCOUNT, {codesAreCopied: true});
}

function quitAndNavigateBackToSettings() {
clearTwoFactorAuthData();
Navigation.goBack(ROUTES.SETTINGS_SECURITY);
}

export {clearTwoFactorAuthData, setTwoFactorAuthStep, quitAndNavigateBackToSettings, setCodesAreCopied};
10 changes: 1 addition & 9 deletions src/pages/settings/Security/SecuritySettingsPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import withLocalize, {withLocalizePropTypes} from '../../../components/withLocal
import MenuItem from '../../../components/MenuItem';
import compose from '../../../libs/compose';
import ONYXKEYS from '../../../ONYXKEYS';
import * as Session from '../../../libs/actions/Session';

const propTypes = {
...withLocalizePropTypes,
Expand All @@ -36,14 +35,7 @@ function SecuritySettingsPage(props) {
{
translationKey: 'twoFactorAuth.headerTitle',
icon: Expensicons.Shield,
action: () => {
if (props.account.requiresTwoFactorAuth) {
Navigation.navigate(ROUTES.SETTINGS_2FA_IS_ENABLED);
} else {
Session.toggleTwoFactorAuth(true);
Navigation.navigate(ROUTES.SETTINGS_2FA_CODES);
}
},
action: () => Navigation.navigate(ROUTES.SETTINGS_2FA),
},
{
translationKey: 'closeAccountPage.closeAccount',
Expand Down
Loading

0 comments on commit 582aa46

Please sign in to comment.