From bdd3915c423987748eb36b3f412dbdbb8ffdcee3 Mon Sep 17 00:00:00 2001 From: StanislavShevchenko Date: Wed, 8 Jan 2020 15:21:21 +0200 Subject: [PATCH] feat(UI): the next button is overlapped by system keyboard on the sign up screen (#1064) * add condition for min hight for smal screen * add hook to use Keyboard * added isMobileKeyboardShown to simpleStore after focused on input * added isMobileKeyboardShown to simpleStore after focused on input * hide btn from mobile and tablet * check autoFocus * autoFocus only desktop * fixed autoFocus only mobile * fixed snapshot and hidden btn in phone screen * down btn on focus * increase the height of the screen by focus in the input * fixed only Iphone5 * fixed only Iphone5 * fixed snapshots * uses onTouchstart * revert signupwrapper * call onFocus if is mobile * commit for test android * remove css and add condition for android and ISO * fixed snapshots * trying add scroll on android * change minHeight only for android * refactor: save original device height and use * refactor: moved originalScreenHeight to Orientation.js Co-authored-by: Alexey Kosinski <36693645+AlexeyKosinski@users.noreply.github.com> --- src/SignupRouter.js | 13 +++++-- src/components/common/form/InputText.js | 38 ++++++++++++------- .../__snapshots__/InputGoodDollar.js.snap | 2 + .../__tests__/__snapshots__/InputText.js.snap | 2 + .../__snapshots__/AmountInput.js.snap | 1 + .../__tests__/__snapshots__/Amount.js.snap | 1 + .../__tests__/__snapshots__/Reason.js.snap | 1 + .../__tests__/__snapshots__/Who.js.snap | 1 + .../__snapshots__/IOSWebAppSignIn.js.snap | 1 + .../__tests__/__snapshots__/Mnemonics.js.snap | 1 + src/components/signup/EmailForm.js | 24 ++++++++---- src/components/signup/PhoneForm.web.js | 38 ++++++++++++++++--- src/components/signup/SignupState.js | 1 - .../__tests__/__snapshots__/EmailForm.js.snap | 5 ++- .../__tests__/__snapshots__/NameForm.js.snap | 2 + .../__snapshots__/PhoneForm.web.js.snap | 2 + src/index.css | 2 +- src/lib/undux/SimpleStore.js | 2 + src/lib/utils/Orientation.js | 8 ++++ 19 files changed, 111 insertions(+), 34 deletions(-) diff --git a/src/SignupRouter.js b/src/SignupRouter.js index 659a5c8f5a..aa4adef2d0 100644 --- a/src/SignupRouter.js +++ b/src/SignupRouter.js @@ -3,7 +3,7 @@ import { createBrowserApp } from '@react-navigation/web' import { createSwitchNavigator } from '@react-navigation/core' import { Platform } from 'react-native' -import { isMobileSafari } from 'mobile-device-detect' +import { isAndroid, isMobileSafari } from 'mobile-device-detect' import Signup from './components/signup/SignupState' import SigninInfo from './components/signin/SigninInfo' import IOSWebAppSignIn from './components/signin/IOSWebAppSignIn' @@ -14,6 +14,7 @@ import './components/appNavigation/blurFx.css' import SimpleStore from './lib/undux/SimpleStore.js' import { fireEventFromNavigation } from './lib/analytics/analytics' import isWebApp from './lib/utils/isWebApp' +import { getOriginalScreenHeight } from './lib/utils/Orientation' const initialRouteName = isMobileSafari && isWebApp ? 'IOSWebAppSignIn' : 'Auth' const router = createSwitchNavigator( @@ -42,15 +43,21 @@ const fullScreenContainer = { display: 'flex', flexGrow: 1, flexDirection: 'column', - minHeight: 480, } const Router = () => { const store = SimpleStore.useStore() const { visible: dialogVisible } = store.get('currentScreen').dialogData + const isShowKeyboard = store.get && store.get('isMobileKeyboardShown') + let minHeight = 480 + + if (isAndroid && isShowKeyboard) { + minHeight = getOriginalScreenHeight() + } + return ( <> - + fireEventFromNavigation(action)} /> diff --git a/src/components/common/form/InputText.js b/src/components/common/form/InputText.js index be31031df1..d6f024558b 100644 --- a/src/components/common/form/InputText.js +++ b/src/components/common/form/InputText.js @@ -1,6 +1,6 @@ // @flow import React, { useEffect } from 'react' -import { isMobileSafari } from 'mobile-device-detect' +import { isMobile, isMobileSafari } from 'mobile-device-detect' import { StyleSheet, TextInput, TouchableOpacity, View } from 'react-native' import normalize from '../../../lib/utils/normalizeText' import SimpleStore from '../../../lib/undux/SimpleStore' @@ -12,16 +12,31 @@ import ErrorText from './ErrorText' const InputText = ({ error, onCleanUpField, styles, theme, style, getRef, ...props }: any) => { const simpleStore = SimpleStore.useStore() - const onFocusMobileSafari = () => { - window.scrollTo(0, 0) - document.body.scrollTop = 0 - simpleStore.set('isMobileSafariKeyboardShown')(true) + const shouldChangeSizeOnKeyboardShown = isMobileSafari && simpleStore.set && Config.safariMobileKeyboardGuidedSize + + const onFocus = () => { + if (shouldChangeSizeOnKeyboardShown) { + window.scrollTo(0, 0) + document.body.scrollTop = 0 + simpleStore.set('isMobileSafariKeyboardShown')(true) + } + if (isMobile) { + simpleStore.set('isMobileKeyboardShown')(true) + } } - const onBlurMobileSafari = () => simpleStore.set('isMobileSafariKeyboardShown')(false) + const onBlur = () => { + if (shouldChangeSizeOnKeyboardShown) { + simpleStore.set('isMobileSafariKeyboardShown')(false) + } + if (isMobile) { + simpleStore.set('isMobileKeyboardShown')(false) + } + } useEffect(() => { - return () => simpleStore.set('isMobileSafariKeyboardShown')(false) + simpleStore.set('isMobileSafariKeyboardShown')(false) + simpleStore.set('isMobileKeyboardShown')(false) }, []) const inputColor = error ? theme.colors.red : theme.colors.darkGray @@ -30,7 +45,6 @@ const InputText = ({ error, onCleanUpField, styles, theme, style, getRef, ...pro color: inputColor, } - const shouldChangeSizeOnKeyboardShown = isMobileSafari && simpleStore.set && Config.safariMobileKeyboardGuidedSize return ( @@ -40,17 +54,13 @@ const InputText = ({ error, onCleanUpField, styles, theme, style, getRef, ...pro style={[styles.input, inputStyle, style]} placeholderTextColor={theme.colors.gray50Percent} onFocus={() => { - if (shouldChangeSizeOnKeyboardShown) { - onFocusMobileSafari() - } if (props.onFocus) { props.onFocus() } }} + onTouchStart={onFocus} onBlur={() => { - if (shouldChangeSizeOnKeyboardShown) { - onBlurMobileSafari() - } + onBlur() if (props.onBlur) { props.onBlur() } diff --git a/src/components/common/form/__tests__/__snapshots__/InputGoodDollar.js.snap b/src/components/common/form/__tests__/__snapshots__/InputGoodDollar.js.snap index 2491083aac..0340272e45 100644 --- a/src/components/common/form/__tests__/__snapshots__/InputGoodDollar.js.snap +++ b/src/components/common/form/__tests__/__snapshots__/InputGoodDollar.js.snap @@ -67,6 +67,7 @@ exports[`InputGoodDollar matches snapshot 1`] = ` onKeyDown={[Function]} onKeyPress={[Function]} onSelect={[Function]} + onTouchStart={[Function]} placeholder="0 G$" readOnly={false} spellCheck={true} @@ -184,6 +185,7 @@ exports[`InputGoodDollar matches snapshot 2`] = ` onKeyDown={[Function]} onKeyPress={[Function]} onSelect={[Function]} + onTouchStart={[Function]} placeholder="0 G$" readOnly={false} spellCheck={true} diff --git a/src/components/common/form/__tests__/__snapshots__/InputText.js.snap b/src/components/common/form/__tests__/__snapshots__/InputText.js.snap index d31c794e76..466c89af40 100644 --- a/src/components/common/form/__tests__/__snapshots__/InputText.js.snap +++ b/src/components/common/form/__tests__/__snapshots__/InputText.js.snap @@ -67,6 +67,7 @@ exports[`InputText empty matches snapshot 1`] = ` onKeyDown={[Function]} onKeyPress={[Function]} onSelect={[Function]} + onTouchStart={[Function]} readOnly={false} spellCheck={true} style={ @@ -180,6 +181,7 @@ exports[`InputText matches snapshot 1`] = ` onKeyDown={[Function]} onKeyPress={[Function]} onSelect={[Function]} + onTouchStart={[Function]} readOnly={false} spellCheck={true} style={ diff --git a/src/components/common/view/__tests__/__snapshots__/AmountInput.js.snap b/src/components/common/view/__tests__/__snapshots__/AmountInput.js.snap index abae2a42f6..37e7b9e27f 100644 --- a/src/components/common/view/__tests__/__snapshots__/AmountInput.js.snap +++ b/src/components/common/view/__tests__/__snapshots__/AmountInput.js.snap @@ -106,6 +106,7 @@ exports[`AmountInput matches snapshot 1`] = ` onResponderTerminationRequest={[Function]} onSelect={[Function]} onStartShouldSetResponder={[Function]} + onTouchStart={[Function]} placeholder="0 G$" readOnly={false} spellCheck={true} diff --git a/src/components/dashboard/__tests__/__snapshots__/Amount.js.snap b/src/components/dashboard/__tests__/__snapshots__/Amount.js.snap index 29138fe562..a33177aeb1 100644 --- a/src/components/dashboard/__tests__/__snapshots__/Amount.js.snap +++ b/src/components/dashboard/__tests__/__snapshots__/Amount.js.snap @@ -433,6 +433,7 @@ exports[`Amount matches snapshot 1`] = ` onResponderTerminationRequest={[Function]} onSelect={[Function]} onStartShouldSetResponder={[Function]} + onTouchStart={[Function]} placeholder="0 G$" readOnly={false} spellCheck={true} diff --git a/src/components/dashboard/__tests__/__snapshots__/Reason.js.snap b/src/components/dashboard/__tests__/__snapshots__/Reason.js.snap index e4af377cb1..f08cf2f0da 100644 --- a/src/components/dashboard/__tests__/__snapshots__/Reason.js.snap +++ b/src/components/dashboard/__tests__/__snapshots__/Reason.js.snap @@ -393,6 +393,7 @@ exports[`Reason matches snapshot 1`] = ` onKeyDown={[Function]} onKeyPress={[Function]} onSelect={[Function]} + onTouchStart={[Function]} placeholder="Add a message" readOnly={false} spellCheck={true} diff --git a/src/components/dashboard/__tests__/__snapshots__/Who.js.snap b/src/components/dashboard/__tests__/__snapshots__/Who.js.snap index 1187b2ce81..c8e0d05fac 100644 --- a/src/components/dashboard/__tests__/__snapshots__/Who.js.snap +++ b/src/components/dashboard/__tests__/__snapshots__/Who.js.snap @@ -405,6 +405,7 @@ exports[`Who matches snapshot 1`] = ` onKeyDown={[Function]} onKeyPress={[Function]} onSelect={[Function]} + onTouchStart={[Function]} placeholder="Enter the recipient name" readOnly={false} spellCheck={true} diff --git a/src/components/signin/__tests__/__snapshots__/IOSWebAppSignIn.js.snap b/src/components/signin/__tests__/__snapshots__/IOSWebAppSignIn.js.snap index 4c198c84e8..e3f82cb741 100644 --- a/src/components/signin/__tests__/__snapshots__/IOSWebAppSignIn.js.snap +++ b/src/components/signin/__tests__/__snapshots__/IOSWebAppSignIn.js.snap @@ -274,6 +274,7 @@ sent to you by text message: onKeyDown={[Function]} onKeyPress={[Function]} onSelect={[Function]} + onTouchStart={[Function]} readOnly={false} spellCheck={true} style={ diff --git a/src/components/signin/__tests__/__snapshots__/Mnemonics.js.snap b/src/components/signin/__tests__/__snapshots__/Mnemonics.js.snap index 87d127f9ce..e561cf05c7 100644 --- a/src/components/signin/__tests__/__snapshots__/Mnemonics.js.snap +++ b/src/components/signin/__tests__/__snapshots__/Mnemonics.js.snap @@ -205,6 +205,7 @@ exports[`SignIn - Mnemonics matches snapshot 1`] = ` onKeyDown={[Function]} onKeyPress={[Function]} onSelect={[Function]} + onTouchStart={[Function]} readOnly={false} spellCheck={true} style={ diff --git a/src/components/signup/EmailForm.js b/src/components/signup/EmailForm.js index c7eeda0c66..415a484f0a 100644 --- a/src/components/signup/EmailForm.js +++ b/src/components/signup/EmailForm.js @@ -1,6 +1,8 @@ // @flow import React from 'react' import debounce from 'lodash/debounce' +import SimpleStore from '../../lib/undux/SimpleStore' +import { getScreenHeight } from '../../lib/utils/Orientation' import { getDesignRelativeHeight } from '../../lib/utils/sizes' import { userModelValidations } from '../../lib/gundb/UserModel' @@ -63,7 +65,8 @@ class EmailForm extends React.Component { const errorMessage = this.state.errorMessage || this.props.screenProps.error this.props.screenProps.error = undefined const { key } = this.props.navigation.state - const { styles } = this.props + const { styles, theme, store } = this.props + const isShowKeyboard = store.get && store.get('isMobileKeyboardShown') return ( { /> - - + + {/*change fontSize only for small screen (iPhone5 , etc.)*/} + We respect your privacy and will never sell or give away your info to any third party. @@ -116,10 +128,6 @@ const getStylesFromProps = ({ theme }) => ({ height: getDesignRelativeHeight(200), paddingBottom: theme.sizes.defaultDouble, }, - bottomContent: { - marginTop: 'auto', - marginBottom: theme.sizes.default, - }, }) -export default withStyles(getStylesFromProps)(EmailForm) +export default withStyles(getStylesFromProps)(SimpleStore.withStore(EmailForm)) diff --git a/src/components/signup/PhoneForm.web.js b/src/components/signup/PhoneForm.web.js index dc0532a487..bca08824f9 100644 --- a/src/components/signup/PhoneForm.web.js +++ b/src/components/signup/PhoneForm.web.js @@ -1,11 +1,14 @@ // @flow +import { isMobile } from 'mobile-device-detect' import React from 'react' import PhoneInput from 'react-phone-number-input' import debounce from 'lodash/debounce' import './PhoneForm.css' import { getDesignRelativeHeight } from '../../lib/utils/sizes' import { userModelValidations } from '../../lib/gundb/UserModel' +import { getScreenHeight } from '../../lib/utils/Orientation' import logger from '../../lib/logger/pino-logger' +import SimpleStore from '../../lib/undux/SimpleStore' import { withStyles } from '../../lib/styles' import Config from '../../config/config' import { getFirstWord } from '../../lib/utils/getFirstWord' @@ -38,6 +41,20 @@ class PhoneForm extends React.Component { isValid: true, } + onFocus = () => { + const { store } = this.props + if (isMobile) { + store.set('isMobileKeyboardShown')(true) + } + } + + onBlur = () => { + const { store } = this.props + if (isMobile) { + store.set('isMobileKeyboardShown')(false) + } + } + componentDidUpdate() { if (this.props.screenProps.data.countryCode !== this.state.countryCode) { this.setState({ @@ -80,9 +97,9 @@ class PhoneForm extends React.Component { this.props.screenProps.error = undefined const { key } = this.props.navigation.state - const { styles } = this.props + const { styles, store, theme } = this.props const { fullName, loading } = this.props.screenProps.data - + const isShowKeyboard = store.get && store.get('isMobileKeyboardShown') return (
@@ -100,12 +117,23 @@ class PhoneForm extends React.Component { error={errorMessage} onKeyDown={this.handleEnter} country={this.state.countryCode} + onTouchStart={this.onFocus} + onBlur={this.onBlur} /> - - + + {/*change fontSize only for small screen (iPhone5 , etc.)*/} + A verification code will be sent to this number @@ -132,4 +160,4 @@ const getStylesFromProps = ({ theme }) => ({ }, }) -export default withStyles(getStylesFromProps)(PhoneForm) +export default withStyles(getStylesFromProps)(SimpleStore.withStore(PhoneForm)) diff --git a/src/components/signup/SignupState.js b/src/components/signup/SignupState.js index b755449ec1..a021349fdf 100644 --- a/src/components/signup/SignupState.js +++ b/src/components/signup/SignupState.js @@ -444,7 +444,6 @@ const Signup = ({ navigation }: { navigation: any, screenProps: any }) => { }, [navigation.state.index]) const { scrollableContainer, contentContainer } = styles - return ( diff --git a/src/components/signup/__tests__/__snapshots__/EmailForm.js.snap b/src/components/signup/__tests__/__snapshots__/EmailForm.js.snap index bb6e3b7ff4..13992328bd 100644 --- a/src/components/signup/__tests__/__snapshots__/EmailForm.js.snap +++ b/src/components/signup/__tests__/__snapshots__/EmailForm.js.snap @@ -233,8 +233,8 @@ exports[`EmailForm matches snapshot 1`] = ` "alignItems": "center", "flexDirection": "row", "justifyContent": "center", - "marginBottom": "8px", - "marginTop": "auto", + "marginBottom": "16px", + "marginTop": "16px", "msFlexAlign": "center", "msFlexDirection": "row", "msFlexPack": "center", @@ -292,6 +292,7 @@ exports[`EmailForm matches snapshot 1`] = ` onKeyDown={[Function]} onKeyPress={[Function]} onSelect={[Function]} + onTouchStart={[Function]} readOnly={false} spellCheck={true} style={ diff --git a/src/components/signup/__tests__/__snapshots__/NameForm.js.snap b/src/components/signup/__tests__/__snapshots__/NameForm.js.snap index 35d6aaa570..8f53b02407 100644 --- a/src/components/signup/__tests__/__snapshots__/NameForm.js.snap +++ b/src/components/signup/__tests__/__snapshots__/NameForm.js.snap @@ -252,6 +252,7 @@ exports[`NameForm matches snapshot 1`] = ` onKeyDown={[Function]} onKeyPress={[Function]} onSelect={[Function]} + onTouchStart={[Function]} readOnly={false} spellCheck={true} style={ @@ -762,6 +763,7 @@ exports[`NameForm matches snapshot with empty value 1`] = ` onKeyDown={[Function]} onKeyPress={[Function]} onSelect={[Function]} + onTouchStart={[Function]} readOnly={false} spellCheck={true} style={ diff --git a/src/components/signup/__tests__/__snapshots__/PhoneForm.web.js.snap b/src/components/signup/__tests__/__snapshots__/PhoneForm.web.js.snap index f94c3dad29..836eaa3292 100644 --- a/src/components/signup/__tests__/__snapshots__/PhoneForm.web.js.snap +++ b/src/components/signup/__tests__/__snapshots__/PhoneForm.web.js.snap @@ -1770,6 +1770,7 @@ so we could verify you onChange={[Function]} onFocus={[Function]} onKeyDown={[Function]} + onTouchStart={[Function]} type="tel" value="" /> @@ -1813,6 +1814,7 @@ so we could verify you "alignItems": "center", "flexDirection": "row", "justifyContent": "center", + "marginBottom": "8px", "marginTop": "auto", "msFlexAlign": "center", "msFlexDirection": "row", diff --git a/src/index.css b/src/index.css index 7cc84e3604..6bb195f957 100755 --- a/src/index.css +++ b/src/index.css @@ -22,7 +22,7 @@ html { #root { display: flex; flex-direction: column; - overflow: hidden; + /*overflow: hidden;*/ width: 100%; } diff --git a/src/lib/undux/SimpleStore.js b/src/lib/undux/SimpleStore.js index 6114720900..47c6c5761b 100644 --- a/src/lib/undux/SimpleStore.js +++ b/src/lib/undux/SimpleStore.js @@ -54,6 +54,7 @@ export type State = { visible: boolean, }, isMobileSafariKeyboardShown: boolean, + isMobileKeyboardShown: boolean, currentFeed: any, addWebApp: { show: boolean, @@ -83,6 +84,7 @@ const initialState: State = { visible: false, }, isMobileSafariKeyboardShown: false, + isMobileKeyboardShown: false, currentFeed: null, addWebApp: { show: false, diff --git a/src/lib/utils/Orientation.js b/src/lib/utils/Orientation.js index 4e7443e271..c2aa0cba8e 100644 --- a/src/lib/utils/Orientation.js +++ b/src/lib/utils/Orientation.js @@ -2,6 +2,14 @@ import { Dimensions } from 'react-native' import { isBrowser, isMobileOnly } from 'mobile-device-detect' import { theme } from '../../components/theme/styles' +let originalScreenHeight = 0 + +if (!originalScreenHeight) { + originalScreenHeight = Dimensions.get('window').height +} + +export const getOriginalScreenHeight = () => originalScreenHeight + export const getScreenHeight = () => Dimensions.get('window').height export const getMaxDeviceHeight = () => (isMobileOnly ? getScreenHeight() : theme.sizes.maxHeightForTabletAndDesktop)