From ed7f2f719e44fa4a07eee9926902518df6d4103b Mon Sep 17 00:00:00 2001 From: Cong Pham Date: Wed, 15 May 2024 23:36:53 +0700 Subject: [PATCH 1/5] handle login scroll on virtual viewport --- src/components/ScreenWrapper.tsx | 2 +- src/pages/signin/LoginForm/BaseLoginForm.tsx | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/components/ScreenWrapper.tsx b/src/components/ScreenWrapper.tsx index e53823860ce0..45326ec822df 100644 --- a/src/components/ScreenWrapper.tsx +++ b/src/components/ScreenWrapper.tsx @@ -202,7 +202,7 @@ function ScreenWrapper( // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const isAvoidingViewportScroll = useTackInputFocus(shouldEnableMaxHeight && shouldAvoidScrollOnVirtualViewport && Browser.isMobileSafari()); + const isAvoidingViewportScroll = useTackInputFocus(shouldEnableMaxHeight && shouldAvoidScrollOnVirtualViewport && Browser.isMobileWebKit()); const contextValue = useMemo(() => ({didScreenTransitionEnd}), [didScreenTransitionEnd]); return ( diff --git a/src/pages/signin/LoginForm/BaseLoginForm.tsx b/src/pages/signin/LoginForm/BaseLoginForm.tsx index 4286a2603341..310819cd7365 100644 --- a/src/pages/signin/LoginForm/BaseLoginForm.tsx +++ b/src/pages/signin/LoginForm/BaseLoginForm.tsx @@ -2,7 +2,7 @@ import {useIsFocused} from '@react-navigation/native'; import Str from 'expensify-common/lib/str'; import type {ForwardedRef} from 'react'; import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; -import {View} from 'react-native'; +import {InteractionManager, View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; import DotIndicatorMessage from '@components/DotIndicatorMessage'; @@ -35,6 +35,8 @@ import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import type {CloseAccountForm} from '@src/types/form'; import type {Account, Credentials} from '@src/types/onyx'; +import htmlDivElementRef from '@src/types/utils/htmlDivElementRef'; +import viewRef from '@src/types/utils/viewRef'; import type LoginFormProps from './types'; import type {InputHandle} from './types'; @@ -216,6 +218,13 @@ function BaseLoginForm({account, credentials, closeAccount, blurOnSubmit = false const serverErrorText = useMemo(() => (account ? ErrorUtils.getLatestErrorMessage(account) : ''), [account]); const shouldShowServerError = !!serverErrorText && !formError; + const submitContainerRef = useRef(null); + const handleFocus = useCallback(() => { + InteractionManager.runAfterInteractions(() => { + htmlDivElementRef(submitContainerRef).current?.scrollIntoView?.({behavior: 'smooth', block: 'end'}); + }); + }, []); + return ( <> + Date: Mon, 3 Jun 2024 21:13:19 +0700 Subject: [PATCH 2/5] update specific platform --- src/pages/signin/LoginForm/BaseLoginForm.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pages/signin/LoginForm/BaseLoginForm.tsx b/src/pages/signin/LoginForm/BaseLoginForm.tsx index 310819cd7365..e4c6479071c0 100644 --- a/src/pages/signin/LoginForm/BaseLoginForm.tsx +++ b/src/pages/signin/LoginForm/BaseLoginForm.tsx @@ -3,6 +3,7 @@ import Str from 'expensify-common/lib/str'; import type {ForwardedRef} from 'react'; import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; import {InteractionManager, View} from 'react-native'; +import * as Browser from '@libs/Browser'; import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; import DotIndicatorMessage from '@components/DotIndicatorMessage'; @@ -220,6 +221,9 @@ function BaseLoginForm({account, credentials, closeAccount, blurOnSubmit = false const submitContainerRef = useRef(null); const handleFocus = useCallback(() => { + if (!Browser.isMobileWebKit()) { + return; + } InteractionManager.runAfterInteractions(() => { htmlDivElementRef(submitContainerRef).current?.scrollIntoView?.({behavior: 'smooth', block: 'end'}); }); From e992245d7a2b00d9f8476b3f525fc3fe62c4a859 Mon Sep 17 00:00:00 2001 From: Cong Pham Date: Tue, 4 Jun 2024 07:48:31 +0700 Subject: [PATCH 3/5] fix eslint --- src/pages/signin/LoginForm/BaseLoginForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/signin/LoginForm/BaseLoginForm.tsx b/src/pages/signin/LoginForm/BaseLoginForm.tsx index e4c6479071c0..cb7fe92732c8 100644 --- a/src/pages/signin/LoginForm/BaseLoginForm.tsx +++ b/src/pages/signin/LoginForm/BaseLoginForm.tsx @@ -3,7 +3,6 @@ import Str from 'expensify-common/lib/str'; import type {ForwardedRef} from 'react'; import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; import {InteractionManager, View} from 'react-native'; -import * as Browser from '@libs/Browser'; import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; import DotIndicatorMessage from '@components/DotIndicatorMessage'; @@ -20,6 +19,7 @@ import useNetwork from '@hooks/useNetwork'; import usePrevious from '@hooks/usePrevious'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; +import * as Browser from '@libs/Browser'; import canFocusInputOnScreenFocus from '@libs/canFocusInputOnScreenFocus'; import * as ErrorUtils from '@libs/ErrorUtils'; import isInputAutoFilled from '@libs/isInputAutoFilled'; From b18b68111d7c6f9894cc8866f5129ed0b9716754 Mon Sep 17 00:00:00 2001 From: Cong Pham Date: Thu, 6 Jun 2024 13:49:42 +0700 Subject: [PATCH 4/5] explain change behavior --- src/pages/signin/LoginForm/BaseLoginForm.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pages/signin/LoginForm/BaseLoginForm.tsx b/src/pages/signin/LoginForm/BaseLoginForm.tsx index cb7fe92732c8..29d6ee7bcc75 100644 --- a/src/pages/signin/LoginForm/BaseLoginForm.tsx +++ b/src/pages/signin/LoginForm/BaseLoginForm.tsx @@ -224,6 +224,9 @@ function BaseLoginForm({account, credentials, closeAccount, blurOnSubmit = false if (!Browser.isMobileWebKit()) { return; } + // On mobile WebKit browsers, when an input field gains focus, the keyboard appears and the virtual viewport is resized and scrolled to make the input field visible. + // This occurs even when there is enough space to display both the input field and the submit button in the current view. + // so this change to correct the scroll position when the input field gains focus. InteractionManager.runAfterInteractions(() => { htmlDivElementRef(submitContainerRef).current?.scrollIntoView?.({behavior: 'smooth', block: 'end'}); }); From d7714ee7e819d55f085d9f08ecefa5296a091651 Mon Sep 17 00:00:00 2001 From: Cong Pham Date: Sat, 8 Jun 2024 00:19:26 +0700 Subject: [PATCH 5/5] fix eslint --- src/pages/signin/LoginForm/BaseLoginForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/signin/LoginForm/BaseLoginForm.tsx b/src/pages/signin/LoginForm/BaseLoginForm.tsx index 29d6ee7bcc75..f51fd2fe5880 100644 --- a/src/pages/signin/LoginForm/BaseLoginForm.tsx +++ b/src/pages/signin/LoginForm/BaseLoginForm.tsx @@ -224,7 +224,7 @@ function BaseLoginForm({account, credentials, closeAccount, blurOnSubmit = false if (!Browser.isMobileWebKit()) { return; } - // On mobile WebKit browsers, when an input field gains focus, the keyboard appears and the virtual viewport is resized and scrolled to make the input field visible. + // On mobile WebKit browsers, when an input field gains focus, the keyboard appears and the virtual viewport is resized and scrolled to make the input field visible. // This occurs even when there is enough space to display both the input field and the submit button in the current view. // so this change to correct the scroll position when the input field gains focus. InteractionManager.runAfterInteractions(() => {