From fb6c504db065c02d7b4d8865860178af92c9226f Mon Sep 17 00:00:00 2001 From: joh42 <138504087+joh42@users.noreply.github.com> Date: Tue, 1 Aug 2023 14:58:18 +0200 Subject: [PATCH 1/9] added MagicCodeInput transitionEnd focusing for the 2FA page --- .../TwoFactorAuthForm/BaseTwoFactorAuthForm.js | 6 ++++++ src/pages/settings/Security/TwoFactorAuth/VerifyPage.js | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js index 7455a19f1131..cc9f2d714e47 100644 --- a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js +++ b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js @@ -75,6 +75,11 @@ function BaseTwoFactorAuthForm(props) { validateAndSubmitForm() { validateAndSubmitForm(); }, + focusAfterTransitionEnd() { + if (inputRef.current && inputRef.current.focus) { + inputRef.current.focus(); + } + }, })); return ( @@ -89,6 +94,7 @@ function BaseTwoFactorAuthForm(props) { onFulfill={validateAndSubmitForm} errorText={formError.twoFactorAuthCode ? props.translate(formError.twoFactorAuthCode) : ErrorUtils.getLatestErrorMessage(props.account)} ref={inputRef} + autoFocus={false} /> ); } diff --git a/src/pages/settings/Security/TwoFactorAuth/VerifyPage.js b/src/pages/settings/Security/TwoFactorAuth/VerifyPage.js index 502d48a919d2..bb04a83ae76c 100644 --- a/src/pages/settings/Security/TwoFactorAuth/VerifyPage.js +++ b/src/pages/settings/Security/TwoFactorAuth/VerifyPage.js @@ -93,7 +93,10 @@ function VerifyPage(props) { } return ( - + formRef.current && formRef.current.focusAfterTransitionEnd()} + > Date: Tue, 1 Aug 2023 15:10:45 +0200 Subject: [PATCH 2/9] added ref for the ValidateCodeForm --- .../Contacts/ContactMethodDetailsPage.js | 3 +++ .../ValidateCodeForm/BaseValidateCodeForm.js | 3 +++ .../ValidateCodeForm/index.android.js | 19 +++++++++---------- .../Contacts/ValidateCodeForm/index.js | 19 +++++++++---------- 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js index 2289e68e7bd1..95f125471756 100644 --- a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js +++ b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js @@ -103,6 +103,8 @@ class ContactMethodDetailsPage extends Component { this.state = { isDeleteModalOpen: false, }; + + this.validateCodeFormRef = React.createRef(); } componentDidMount() { @@ -251,6 +253,7 @@ class ContactMethodDetailsPage extends Component { contactMethod={contactMethod} hasMagicCodeBeenSent={hasMagicCodeBeenSent} loginList={this.props.loginList} + ref={this.validateCodeFormRef} /> )} diff --git a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js index ea81413fcbb5..424e89fea6e7 100644 --- a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js +++ b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js @@ -51,6 +51,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 */ diff --git a/src/pages/settings/Profile/Contacts/ValidateCodeForm/index.android.js b/src/pages/settings/Profile/Contacts/ValidateCodeForm/index.android.js index 30c5517b8375..a193dc8d2eae 100644 --- a/src/pages/settings/Profile/Contacts/ValidateCodeForm/index.android.js +++ b/src/pages/settings/Profile/Contacts/ValidateCodeForm/index.android.js @@ -1,15 +1,14 @@ -import React from 'react'; +import React, {forwardRef} from 'react'; import BaseValidateCodeForm from './BaseValidateCodeForm'; -function ValidateCodeForm(props) { - return ( - - ); -} +const ValidateCodeForm = forwardRef((props, ref) => ( + +)); ValidateCodeForm.displayName = 'ValidateCodeForm'; diff --git a/src/pages/settings/Profile/Contacts/ValidateCodeForm/index.js b/src/pages/settings/Profile/Contacts/ValidateCodeForm/index.js index 6ef0c91b6d37..bb4e5ed36b47 100644 --- a/src/pages/settings/Profile/Contacts/ValidateCodeForm/index.js +++ b/src/pages/settings/Profile/Contacts/ValidateCodeForm/index.js @@ -1,15 +1,14 @@ -import React from 'react'; +import React, {forwardRef} from 'react'; import BaseValidateCodeForm from './BaseValidateCodeForm'; -function ValidateCodeForm(props) { - return ( - - ); -} +const ValidateCodeForm = forwardRef((props, ref) => ( + +)); ValidateCodeForm.displayName = 'ValidateCodeForm'; From 9db06983e84c6fdf6291609348d2ca6b0eb73420 Mon Sep 17 00:00:00 2001 From: joh42 <138504087+joh42@users.noreply.github.com> Date: Tue, 1 Aug 2023 15:18:43 +0200 Subject: [PATCH 3/9] added MagicCodeInput transitionEnd focusing for the ContactMethodDetails page --- .../Profile/Contacts/ContactMethodDetailsPage.js | 4 +++- .../ValidateCodeForm/BaseValidateCodeForm.js | 13 ++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js index 95f125471756..a036d4bdc427 100644 --- a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js +++ b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js @@ -219,7 +219,9 @@ class ContactMethodDetailsPage extends Component { const isFailedAddContactMethod = Boolean(lodashGet(loginData, 'errorFields.addedLogin')); return ( - + this.validateCodeFormRef.current && this.validateCodeFormRef.current.focusAfterTransitionEnd()} + > Navigation.goBack(ROUTES.SETTINGS_CONTACT_METHODS)} diff --git a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js index 424e89fea6e7..e1f78cc85c95 100644 --- a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js +++ b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js @@ -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'; @@ -77,6 +77,14 @@ function BaseValidateCodeForm(props) { const inputValidateCodeRef = useRef(); const validateLoginError = ErrorUtils.getEarliestErrorField(loginData, 'validateLogin'); + useImperativeHandle(props.innerRef, () => ({ + focusAfterTransitionEnd() { + if (inputValidateCodeRef.current && inputValidateCodeRef.current.focus) { + inputValidateCodeRef.current.focus(); + } + }, + })); + useEffect(() => { if (!props.hasMagicCodeBeenSent) { return; @@ -141,8 +149,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} /> Date: Tue, 1 Aug 2023 15:22:13 +0200 Subject: [PATCH 4/9] removed MagicCodeInput shouldDelayFocus logic in favor of focusing using onEntryTransitionEnd --- src/components/MagicCodeInput.js | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/src/components/MagicCodeInput.js b/src/components/MagicCodeInput.js index cea98cfd3747..dd1c93d9280a 100644 --- a/src/components/MagicCodeInput.js +++ b/src/components/MagicCodeInput.js @@ -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, @@ -58,7 +55,6 @@ const defaultProps = { value: undefined, name: '', autoFocus: true, - shouldDelayFocus: false, errorText: '', shouldSubmitOnComplete: true, innerRef: null, @@ -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. @@ -290,7 +264,7 @@ function MagicCodeInput(props) { (inputRefs.current[index] = ref)} - autoFocus={index === 0 && props.autoFocus && !props.shouldDelayFocus} + autoFocus={index === 0 && props.autoFocus} inputMode="numeric" textContentType="oneTimeCode" name={props.name} From 67406d92f5a23ac4ec9d29d31b90c17400b46eb6 Mon Sep 17 00:00:00 2001 From: joh42 <138504087+joh42@users.noreply.github.com> Date: Tue, 1 Aug 2023 15:28:22 +0200 Subject: [PATCH 5/9] removed unused shouldDelayFocus import --- .../Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js index e1f78cc85c95..9b3de9941474 100644 --- a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js +++ b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js @@ -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'; From 866bd9d351ac60b229dc71b94cfa76f78f2e29cc Mon Sep 17 00:00:00 2001 From: joh42 <138504087+joh42@users.noreply.github.com> Date: Tue, 1 Aug 2023 15:51:23 +0200 Subject: [PATCH 6/9] renamed focusAfterTransitionEnd to just focus --- src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js | 2 +- .../Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js | 2 +- .../TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js | 2 +- src/pages/settings/Security/TwoFactorAuth/VerifyPage.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js index a036d4bdc427..3cb2375483f6 100644 --- a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js +++ b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js @@ -220,7 +220,7 @@ class ContactMethodDetailsPage extends Component { return ( this.validateCodeFormRef.current && this.validateCodeFormRef.current.focusAfterTransitionEnd()} + onEntryTransitionEnd={() => this.validateCodeFormRef.current && this.validateCodeFormRef.current.focus()} > ({ - focusAfterTransitionEnd() { + focus() { if (inputValidateCodeRef.current && inputValidateCodeRef.current.focus) { inputValidateCodeRef.current.focus(); } diff --git a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js index cc9f2d714e47..697ce5c27e30 100644 --- a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js +++ b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js @@ -75,7 +75,7 @@ function BaseTwoFactorAuthForm(props) { validateAndSubmitForm() { validateAndSubmitForm(); }, - focusAfterTransitionEnd() { + focus() { if (inputRef.current && inputRef.current.focus) { inputRef.current.focus(); } diff --git a/src/pages/settings/Security/TwoFactorAuth/VerifyPage.js b/src/pages/settings/Security/TwoFactorAuth/VerifyPage.js index bb04a83ae76c..e67f0469db62 100644 --- a/src/pages/settings/Security/TwoFactorAuth/VerifyPage.js +++ b/src/pages/settings/Security/TwoFactorAuth/VerifyPage.js @@ -95,7 +95,7 @@ function VerifyPage(props) { return ( formRef.current && formRef.current.focusAfterTransitionEnd()} + onEntryTransitionEnd={() => formRef.current && formRef.current.focus()} > Date: Tue, 1 Aug 2023 16:39:12 +0200 Subject: [PATCH 7/9] fixed linting errors (early return and default prop) --- .../Contacts/ValidateCodeForm/BaseValidateCodeForm.js | 6 ++++-- .../TwoFactorAuthForm/BaseTwoFactorAuthForm.js | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js index 5852ed6f564b..a149e4995972 100644 --- a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js +++ b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js @@ -67,6 +67,7 @@ const propTypes = { const defaultProps = { account: {}, + innerRef: () => {}, }; function BaseValidateCodeForm(props) { @@ -78,9 +79,10 @@ function BaseValidateCodeForm(props) { useImperativeHandle(props.innerRef, () => ({ focus() { - if (inputValidateCodeRef.current && inputValidateCodeRef.current.focus) { - inputValidateCodeRef.current.focus(); + if (!(inputValidateCodeRef.current && inputValidateCodeRef.current.focus)) { + return; } + inputValidateCodeRef.current.focus(); }, })); diff --git a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js index 697ce5c27e30..870194953c1e 100644 --- a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js +++ b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js @@ -76,9 +76,10 @@ function BaseTwoFactorAuthForm(props) { validateAndSubmitForm(); }, focus() { - if (inputRef.current && inputRef.current.focus) { - inputRef.current.focus(); + if (!(inputRef.current && inputRef.current.focus)) { + return; } + inputRef.current.focus(); }, })); From e10aceca0f67454a19dac20c0a11417a5c2915eb Mon Sep 17 00:00:00 2001 From: joh42 <138504087+joh42@users.noreply.github.com> Date: Tue, 1 Aug 2023 16:44:40 +0200 Subject: [PATCH 8/9] fixed prettier diff --- .../settings/Profile/Contacts/ContactMethodDetailsPage.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js index 3cb2375483f6..7b2cf85ef141 100644 --- a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js +++ b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js @@ -219,9 +219,7 @@ class ContactMethodDetailsPage extends Component { const isFailedAddContactMethod = Boolean(lodashGet(loginData, 'errorFields.addedLogin')); return ( - this.validateCodeFormRef.current && this.validateCodeFormRef.current.focus()} - > + this.validateCodeFormRef.current && this.validateCodeFormRef.current.focus()}> Navigation.goBack(ROUTES.SETTINGS_CONTACT_METHODS)} From 270628e0481da242b6b062053e2eddf0c732f322 Mon Sep 17 00:00:00 2001 From: joh42 <138504087+joh42@users.noreply.github.com> Date: Thu, 3 Aug 2023 12:05:17 +0200 Subject: [PATCH 9/9] removed redundant check for focus function --- .../Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js | 2 +- .../TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js index a149e4995972..578e4dc3a2f6 100644 --- a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js +++ b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js @@ -79,7 +79,7 @@ function BaseValidateCodeForm(props) { useImperativeHandle(props.innerRef, () => ({ focus() { - if (!(inputValidateCodeRef.current && inputValidateCodeRef.current.focus)) { + if (!inputValidateCodeRef.current) { return; } inputValidateCodeRef.current.focus(); diff --git a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js index 870194953c1e..4c0bf81210b4 100644 --- a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js +++ b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js @@ -76,7 +76,7 @@ function BaseTwoFactorAuthForm(props) { validateAndSubmitForm(); }, focus() { - if (!(inputRef.current && inputRef.current.focus)) { + if (!inputRef.current) { return; } inputRef.current.focus();