Skip to content

Commit

Permalink
Merge pull request #24002 from joh42/fix/23593
Browse files Browse the repository at this point in the history
  • Loading branch information
thienlnam authored Aug 3, 2023
2 parents 55eccde + f588696 commit d051341
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 53 deletions.
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

0 comments on commit d051341

Please sign in to comment.