diff --git a/src/components/MagicCodeInput.tsx b/src/components/MagicCodeInput.tsx index e965ed3017214..00599a0b6476f 100644 --- a/src/components/MagicCodeInput.tsx +++ b/src/components/MagicCodeInput.tsx @@ -79,6 +79,9 @@ type MagicCodeInputProps = { /** Function to call when the input is changed */ onChangeText?: (value: string) => void; + /** Callback that is called when the text input is focused */ + onFocus?: () => void; + /** Function to call when the input is submitted or fully complete */ onFulfill?: (value: string) => void; @@ -137,6 +140,7 @@ function MagicCodeInput( errorText = '', shouldSubmitOnComplete = true, onChangeText: onChangeTextProp = () => {}, + onFocus: onFocusProps, maxLength = CONST.MAGIC_CODE_LENGTH, onFulfill = () => {}, isDisableKeyboard = false, @@ -257,6 +261,7 @@ function MagicCodeInput( lastValue.current = TEXT_INPUT_EMPTY_STATE; setInputAndIndex(lastFocusedIndex.current); } + onFocusProps?.(); event.preventDefault(); }; @@ -480,7 +485,7 @@ function MagicCodeInput( inputStyle={[styles.inputTransparent]} role={CONST.ROLE.PRESENTATION} style={[styles.inputTransparent]} - textInputContainerStyles={[styles.borderNone, styles.bgTransparent]} + textInputContainerStyles={[styles.borderTransparent, styles.bgTransparent]} testID={testID} /> diff --git a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.tsx b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.tsx index 458c5929c0fc9..f600b423dfd74 100644 --- a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.tsx +++ b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.tsx @@ -21,12 +21,15 @@ type BaseTwoFactorAuthFormProps = { // Set this to false in order to disable 2FA when a valid code is entered. validateInsteadOfDisable?: boolean; + /** Callback that is called when the text input is focused */ + onFocus?: () => void; + shouldAutoFocusOnMobile?: boolean; }; const isMobile = !canFocusInputOnScreenFocus(); -function BaseTwoFactorAuthForm({autoComplete, validateInsteadOfDisable, shouldAutoFocusOnMobile = true}: BaseTwoFactorAuthFormProps, ref: ForwardedRef) { +function BaseTwoFactorAuthForm({autoComplete, validateInsteadOfDisable, onFocus, shouldAutoFocusOnMobile = true}: BaseTwoFactorAuthFormProps, ref: ForwardedRef) { const {translate} = useLocalize(); const [formError, setFormError] = useState<{twoFactorAuthCode?: string}>({}); const [account] = useOnyx(ONYXKEYS.ACCOUNT, {canBeMissing: false}); @@ -117,6 +120,7 @@ function BaseTwoFactorAuthForm({autoComplete, validateInsteadOfDisable, shouldAu name="twoFactorAuthCode" value={twoFactorAuthCode} onChangeText={onTextInput} + onFocus={onFocus} onFulfill={validateAndSubmitForm} errorText={formError.twoFactorAuthCode ?? getLatestErrorMessage(account)} ref={inputRef} diff --git a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/index.tsx b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/index.tsx index 83aab740da426..3a9720d69337d 100644 --- a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/index.tsx +++ b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/index.tsx @@ -2,12 +2,13 @@ import React from 'react'; import BaseTwoFactorAuthForm from './BaseTwoFactorAuthForm'; import type {TwoFactorAuthFormProps} from './types'; -function TwoFactorAuthForm({innerRef, validateInsteadOfDisable, shouldAutoFocusOnMobile}: TwoFactorAuthFormProps) { +function TwoFactorAuthForm({innerRef, validateInsteadOfDisable, onFocus, shouldAutoFocusOnMobile}: TwoFactorAuthFormProps) { return ( ); diff --git a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/types.ts b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/types.ts index 00bb663079e7e..baedf75088c62 100644 --- a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/types.ts +++ b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/types.ts @@ -12,6 +12,9 @@ type TwoFactorAuthFormProps = { // Set this to true in order to call the validateTwoFactorAuth action which is used when setting up 2FA for the first time. // Set this to false in order to disable 2FA when a valid code is entered. validateInsteadOfDisable?: boolean; + + /** Callback that is called when the text input is focused */ + onFocus?: () => void; }; export type {TwoFactorAuthFormProps, BaseTwoFactorAuthFormRef}; diff --git a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthWrapper.tsx b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthWrapper.tsx index 60774bb0c121c..807798e57f503 100644 --- a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthWrapper.tsx +++ b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthWrapper.tsx @@ -6,6 +6,7 @@ import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import useOnyx from '@hooks/useOnyx'; +import useViewportOffsetTop from '@hooks/useViewportOffsetTop'; import {quitAndNavigateBack} from '@libs/actions/TwoFactorAuthActions'; import CONST from '@src/CONST'; import type {StepCounterParams} from '@src/languages/params'; @@ -28,10 +29,21 @@ type TwoFactorAuthWrapperProps = ChildrenProps & { /** Flag to indicate if the keyboard avoiding view should be enabled */ shouldEnableKeyboardAvoidingView?: boolean; + + /** Flag to indicate if the viewport offset top should be enabled */ + shouldEnableViewportOffsetTop?: boolean; }; -function TwoFactorAuthWrapper({stepName, title, stepCounter, onBackButtonPress, shouldEnableKeyboardAvoidingView = true, children}: TwoFactorAuthWrapperProps) { - const [account] = useOnyx(ONYXKEYS.ACCOUNT); +function TwoFactorAuthWrapper({ + stepName, + title, + stepCounter, + onBackButtonPress, + shouldEnableKeyboardAvoidingView = true, + shouldEnableViewportOffsetTop = false, + children, +}: TwoFactorAuthWrapperProps) { + const [account] = useOnyx(ONYXKEYS.ACCOUNT, {canBeMissing: false}); const isActingAsDelegate = !!account?.delegatedAccess?.delegate; // eslint-disable-next-line rulesdir/no-negated-variables @@ -58,6 +70,8 @@ function TwoFactorAuthWrapper({stepName, title, stepCounter, onBackButtonPress, } }, [account, stepName]); + const viewportOffsetTop = useViewportOffsetTop(); + if (isActingAsDelegate) { return ( (null); + const handleInputFocus = useCallback(() => { + InteractionManager.runAfterInteractions(() => { + requestAnimationFrame(() => { + scrollViewRef.current?.scrollToEnd({animated: true}); + }); + }); + }, []); + return ( Navigation.goBack(ROUTES.SETTINGS_2FA_ROOT.getRoute(route.params?.backTo, route.params?.forwardTo))} + shouldEnableViewportOffsetTop > - + {translate('twoFactorAuth.scanCode')} {translate('twoFactorAuth.authenticatorApp')}. @@ -116,27 +129,28 @@ function VerifyPage({route}: VerifyPageProps) { {translate('twoFactorAuth.enterCode')} - - - - -