Skip to content

Commit

Permalink
Merge pull request #42603 from suneox/41108-login-scroll-on-virtual-v…
Browse files Browse the repository at this point in the history
…iewport

handle login scroll on virtual viewport
  • Loading branch information
madmax330 authored Jun 11, 2024
2 parents 6d82ec0 + d7714ee commit 98b2cb0
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/components/ScreenWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,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 (
Expand Down
24 changes: 22 additions & 2 deletions src/pages/signin/LoginForm/BaseLoginForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {useIsFocused} from '@react-navigation/native';
import {Str} from 'expensify-common';
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';
Expand All @@ -19,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';
Expand All @@ -34,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';

Expand Down Expand Up @@ -215,6 +218,19 @@ function BaseLoginForm({account, credentials, closeAccount, blurOnSubmit = false
const isSigningWithAppleOrGoogle = useRef(false);
const setIsSigningWithAppleOrGoogle = useCallback((isPressed: boolean) => (isSigningWithAppleOrGoogle.current = isPressed), []);

const submitContainerRef = useRef<View | HTMLDivElement>(null);
const handleFocus = useCallback(() => {
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'});
});
}, []);

return (
<>
<View
Expand Down Expand Up @@ -246,6 +262,7 @@ function BaseLoginForm({account, credentials, closeAccount, blurOnSubmit = false
validate(login);
}, 500)
}
onFocus={handleFocus}
onChangeText={onTextInput}
onSubmitEditing={validateAndSubmitForm}
autoCapitalize="none"
Expand All @@ -269,7 +286,10 @@ function BaseLoginForm({account, credentials, closeAccount, blurOnSubmit = false
// We need to unmount the submit button when the component is not visible so that the Enter button
// key handler gets unsubscribed
isVisible && (
<View style={[shouldShowServerError ? {} : styles.mt5]}>
<View
style={[shouldShowServerError ? {} : styles.mt5]}
ref={viewRef(submitContainerRef)}
>
<FormAlertWithSubmitButton
buttonText={translate('common.continue')}
isLoading={account?.isLoading && account?.loadingForm === CONST.FORMS.LOGIN_FORM}
Expand Down

0 comments on commit 98b2cb0

Please sign in to comment.