Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions src/components/TouchableDismissKeyboard/index.ios.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* On iOS sometimes the keyboard doesn't dismiss itself
* when you tap outside of the input that pulled it up.
* Therefore this component is necessary to ensure users
* can still dismiss the keyboard on iOS.
*/
import React from 'react';
import {TouchableWithoutFeedback, Keyboard} from 'react-native';
import PropTypes from 'prop-types';
import withKeyboardState, {keyboardStatePropTypes} from '../withKeyboardState';

const propTypes = {
/** The children which should be contained in this wrapper component. */
children: PropTypes.node.isRequired,

...keyboardStatePropTypes,
};

const TouchableDismissKeyboard = (props) => {
const dismissKeyboardWhenTappedOutsideOfInput = () => {
if (!props.isKeyboardShown) {
return;
}
Keyboard.dismiss();
};

return (
<TouchableWithoutFeedback onPress={dismissKeyboardWhenTappedOutsideOfInput}>
{props.children}
</TouchableWithoutFeedback>
);
};

TouchableDismissKeyboard.propTypes = propTypes;
TouchableDismissKeyboard.displayName = 'TouchableDismissKeyboard';

export default withKeyboardState(TouchableDismissKeyboard);
13 changes: 13 additions & 0 deletions src/components/TouchableDismissKeyboard/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import PropTypes from 'prop-types';

const propTypes = {
/** The children which should be contained in this wrapper component. */
children: PropTypes.node.isRequired,
};

const TouchableDismissKeyboard = props => props.children;

TouchableDismissKeyboard.propTypes = propTypes;
TouchableDismissKeyboard.displayName = 'TouchableDismissKeyboard';

export default TouchableDismissKeyboard;
105 changes: 46 additions & 59 deletions src/pages/signin/SignInPageLayout/SignInPageContent.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import {View, TouchableWithoutFeedback, Keyboard} from 'react-native';
import {View} from 'react-native';
import PropTypes from 'prop-types';
import {withSafeAreaInsets} from 'react-native-safe-area-context';
import styles from '../../../styles/styles';
Expand All @@ -10,9 +10,9 @@ import TermsAndLicenses from '../TermsAndLicenses';
import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize';
import SignInPageForm from '../../../components/SignInPageForm';
import compose from '../../../libs/compose';
import withKeyboardState, {keyboardStatePropTypes} from '../../../components/withKeyboardState';
import withWindowDimensions, {windowDimensionsPropTypes} from '../../../components/withWindowDimensions';
import KeyboardAvoidingView from '../../../components/KeyboardAvoidingView';
import TouchableDismissKeyboard from '../../../components/TouchableDismissKeyboard';

const propTypes = {
/** The children to show inside the layout */
Expand All @@ -27,75 +27,62 @@ const propTypes = {

...withLocalizePropTypes,
...windowDimensionsPropTypes,
...keyboardStatePropTypes,
};

const SignInPageContent = (props) => {
const dismissKeyboardWhenTappedOutsideOfInput = () => {
if (!props.isKeyboardShown) {
return;
}
Keyboard.dismiss();
};
const SignInPageContent = props => (
<TouchableDismissKeyboard>
<View
style={[
styles.flex1,
styles.signInPageLeftContainer,
!props.isSmallScreenWidth && styles.signInPageLeftContainerWide,
]}
>
<KeyboardAvoidingView
behavior="padding"
style={[styles.flex1, styles.alignSelfCenter, styles.signInPageWelcomeFormContainer]}

return (
<TouchableWithoutFeedback onPress={dismissKeyboardWhenTappedOutsideOfInput}>
<View
style={[
styles.flex1,
styles.signInPageLeftContainer,
!props.isSmallScreenWidth && styles.signInPageLeftContainerWide,
]}
// This vertical offset is here to add some more margin above the keyboard. Without it, the TOS and footer stuff still hides behind the keyboard by a few pixels.
keyboardVerticalOffset={50}
>
<KeyboardAvoidingView
behavior="padding"
style={[styles.flex1, styles.alignSelfCenter, styles.signInPageWelcomeFormContainer]}
{/* This empty view creates margin on the top of the sign in form which will shrink and grow depending on if the keyboard is open or not */}
<View style={[styles.flexGrow1, styles.signInPageContentTopSpacer]} />

// This vertical offset is here to add some more margin above the keyboard. Without it, the TOS and footer stuff still hides behind the keyboard by a few pixels.
keyboardVerticalOffset={50}
>
{/* This empty view creates margin on the top of the sign in form which will shrink and grow depending on if the keyboard is open or not */}
<View style={[styles.flexGrow1, styles.signInPageContentTopSpacer]} />

<View style={[styles.flexGrow2]}>
<SignInPageForm style={[styles.alignSelfStretch]}>
<View style={[
styles.componentHeightLarge,
...(props.isSmallScreenWidth ? [styles.mb2] : [styles.mt6, styles.mb5]),
]}
>
<ExpensifyCashLogo
width={variables.componentSizeLarge}
height={variables.componentSizeLarge}
/>
<View style={[styles.flexGrow2]}>
<SignInPageForm style={[styles.alignSelfStretch]}>
<View style={[
styles.componentHeightLarge,
...(props.isSmallScreenWidth ? [styles.mb2] : [styles.mt6, styles.mb5]),
]}
>
<ExpensifyCashLogo
width={variables.componentSizeLarge}
height={variables.componentSizeLarge}
/>
</View>
{props.shouldShowWelcomeText && (
<View style={[styles.signInPageWelcomeTextContainer]}>
<Text style={[styles.mv5, styles.textLabel, styles.h3]}>
{props.welcomeText}
</Text>
</View>
{props.shouldShowWelcomeText && (
<View style={[styles.signInPageWelcomeTextContainer]}>
<Text style={[styles.mv5, styles.textLabel, styles.h3]}>
{props.welcomeText}
</Text>
</View>
)}
{props.children}
</SignInPageForm>
</View>
<View style={[styles.mv5]}>
<TermsAndLicenses />
</View>
</KeyboardAvoidingView>
</View>
</TouchableWithoutFeedback>
);
};
)}
{props.children}
</SignInPageForm>
</View>
<View style={[styles.mv5]}>
<TermsAndLicenses />
</View>
</KeyboardAvoidingView>
</View>
</TouchableDismissKeyboard>
);

SignInPageContent.propTypes = propTypes;
SignInPageContent.displayName = 'SignInPageContent';

export default compose(
withWindowDimensions,
withLocalize,

Comment thread
jasperhuangg marked this conversation as resolved.
// KeyboardState HOC is needed to trigger recalculation of the UI when keyboard opens or closes
withKeyboardState,
withSafeAreaInsets,
)(SignInPageContent);