Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

23593 secondary contact method transition #24002

Merged
merged 10 commits into from
Aug 3, 2023
28 changes: 1 addition & 27 deletions src/components/MagicCodeInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ const propTypes = {
/** Should the input auto focus */
autoFocus: PropTypes.bool,

/** Whether we should wait before focusing the TextInput, useful when using transitions */
shouldDelayFocus: PropTypes.bool,

/** Error text to display */
errorText: PropTypes.string,

Expand Down Expand Up @@ -58,7 +55,6 @@ const defaultProps = {
value: undefined,
name: '',
autoFocus: true,
shouldDelayFocus: false,
errorText: '',
shouldSubmitOnComplete: true,
innerRef: null,
Expand Down Expand Up @@ -141,28 +137,6 @@ function MagicCodeInput(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.value, props.shouldSubmitOnComplete]);

useEffect(() => {
if (!props.autoFocus) {
return;
}

let focusTimeout = null;
if (props.shouldDelayFocus) {
focusTimeout = setTimeout(() => inputRefs.current[0].focus(), CONST.ANIMATED_TRANSITION);
} else {
inputRefs.current[0].focus();
}

return () => {
if (!focusTimeout) {
return;
}
clearTimeout(focusTimeout);
};
// We only want this to run on mount
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

/**
* Callback for the onFocus event, updates the indexes
* of the currently focused input.
Expand Down Expand Up @@ -290,7 +264,7 @@ function MagicCodeInput(props) {
<View style={[StyleSheet.absoluteFillObject, styles.w100, isMobileSafari ? styles.bgTransparent : styles.opacity0]}>
<TextInput
ref={(ref) => (inputRefs.current[index] = ref)}
autoFocus={index === 0 && props.autoFocus && !props.shouldDelayFocus}
autoFocus={index === 0 && props.autoFocus}
inputMode="numeric"
textContentType="oneTimeCode"
name={props.name}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ class ContactMethodDetailsPage extends Component {
this.state = {
isDeleteModalOpen: false,
};

this.validateCodeFormRef = React.createRef();
}

componentDidMount() {
Expand Down Expand Up @@ -217,7 +219,7 @@ class ContactMethodDetailsPage extends Component {
const isFailedAddContactMethod = Boolean(lodashGet(loginData, 'errorFields.addedLogin'));

return (
<ScreenWrapper>
<ScreenWrapper onEntryTransitionEnd={() => this.validateCodeFormRef.current && this.validateCodeFormRef.current.focus()}>
<HeaderWithBackButton
title={formattedContactMethod}
onBackButtonPress={() => Navigation.goBack(ROUTES.SETTINGS_CONTACT_METHODS)}
Expand Down Expand Up @@ -251,6 +253,7 @@ class ContactMethodDetailsPage extends Component {
contactMethod={contactMethod}
hasMagicCodeBeenSent={hasMagicCodeBeenSent}
loginList={this.props.loginList}
ref={this.validateCodeFormRef}
/>
</View>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {useCallback, useState, useEffect, useRef} from 'react';
import React, {useCallback, useState, useEffect, useRef, useImperativeHandle} from 'react';
import {View} from 'react-native';
import PropTypes from 'prop-types';
import _ from 'underscore';
Expand All @@ -16,7 +16,6 @@ import * as User from '../../../../../libs/actions/User';
import Button from '../../../../../components/Button';
import DotIndicatorMessage from '../../../../../components/DotIndicatorMessage';
import * as Session from '../../../../../libs/actions/Session';
import shouldDelayFocus from '../../../../../libs/shouldDelayFocus';
import Text from '../../../../../components/Text';
import {withNetwork} from '../../../../../components/OnyxProvider';
import PressableWithFeedback from '../../../../../components/Pressable/PressableWithFeedback';
Expand Down Expand Up @@ -51,6 +50,9 @@ const propTypes = {
pendingFields: PropTypes.objectOf(PropTypes.objectOf(PropTypes.string)),
}).isRequired,

/** Forwarded inner ref */
innerRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),

/* Onyx Props */

/** The details about the account that the user is signing in with */
Expand All @@ -65,6 +67,7 @@ const propTypes = {

const defaultProps = {
account: {},
innerRef: () => {},
};

function BaseValidateCodeForm(props) {
Expand All @@ -74,6 +77,15 @@ function BaseValidateCodeForm(props) {
const inputValidateCodeRef = useRef();
const validateLoginError = ErrorUtils.getEarliestErrorField(loginData, 'validateLogin');

useImperativeHandle(props.innerRef, () => ({
focus() {
if (!inputValidateCodeRef.current) {
return;
}
inputValidateCodeRef.current.focus();
},
}));

useEffect(() => {
if (!props.hasMagicCodeBeenSent) {
return;
Expand Down Expand Up @@ -138,8 +150,7 @@ function BaseValidateCodeForm(props) {
errorText={formError.validateCode ? props.translate(formError.validateCode) : ErrorUtils.getLatestErrorMessage(props.account)}
hasError={!_.isEmpty(validateLoginError)}
onFulfill={validateAndSubmitForm}
autoFocus
shouldDelayFocus={shouldDelayFocus}
autoFocus={false}
/>
<OfflineWithFeedback
pendingAction={lodashGet(loginData, 'pendingFields.validateCodeSent', null)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import React from 'react';
import React, {forwardRef} from 'react';
import BaseValidateCodeForm from './BaseValidateCodeForm';

function ValidateCodeForm(props) {
return (
<BaseValidateCodeForm
autoComplete="sms-otp"
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
/>
);
}
const ValidateCodeForm = forwardRef((props, ref) => (
<BaseValidateCodeForm
autoComplete="sms-otp"
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
innerRef={ref}
/>
));

ValidateCodeForm.displayName = 'ValidateCodeForm';

Expand Down
19 changes: 9 additions & 10 deletions src/pages/settings/Profile/Contacts/ValidateCodeForm/index.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import React from 'react';
import React, {forwardRef} from 'react';
import BaseValidateCodeForm from './BaseValidateCodeForm';

function ValidateCodeForm(props) {
return (
<BaseValidateCodeForm
autoComplete="one-time-code"
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
/>
);
}
const ValidateCodeForm = forwardRef((props, ref) => (
<BaseValidateCodeForm
autoComplete="one-time-code"
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
innerRef={ref}
/>
));

ValidateCodeForm.displayName = 'ValidateCodeForm';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ function BaseTwoFactorAuthForm(props) {
validateAndSubmitForm() {
validateAndSubmitForm();
},
focus() {
if (!inputRef.current) {
return;
}
inputRef.current.focus();
},
}));

return (
Expand All @@ -89,6 +95,7 @@ function BaseTwoFactorAuthForm(props) {
onFulfill={validateAndSubmitForm}
errorText={formError.twoFactorAuthCode ? props.translate(formError.twoFactorAuthCode) : ErrorUtils.getLatestErrorMessage(props.account)}
ref={inputRef}
autoFocus={false}
/>
);
}
Expand Down
5 changes: 4 additions & 1 deletion src/pages/settings/Security/TwoFactorAuth/VerifyPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,10 @@ function VerifyPage(props) {
}

return (
<ScreenWrapper shouldShowOfflineIndicator={false}>
<ScreenWrapper
shouldShowOfflineIndicator={false}
onEntryTransitionEnd={() => formRef.current && formRef.current.focus()}
>
<HeaderWithBackButton
title={props.translate('twoFactorAuth.headerTitle')}
stepCounter={{
Expand Down