Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for: mWeb/Chrome - Payment - The keyboard overlaps the "Make default payment method" button #14725

Merged
merged 15 commits into from
Feb 9, 2023
Merged
24 changes: 6 additions & 18 deletions src/components/KeyboardSpacer/index.android.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,9 @@
/**
* On Android the keyboard covers the input fields on the bottom of the view. This component moves the
* view up with the keyboard allowing the user to see what they are typing.
* On Android we do not need to implement a keyboard spacer, so we return a null component.
*
* @returns {null}
* @constructor
*/
import React from 'react';
import {StatusBar} from 'react-native';
import BaseKeyboardSpacer from './BaseKeyboardSpacer';
import withWindowDimensions, {windowDimensionsPropTypes} from '../withWindowDimensions';
const KeyboardSpacer = () => null;

const KeyboardSpacer = () => (
<BaseKeyboardSpacer
topSpacing={StatusBar.currentHeight}
keyboardShowMethod="keyboardDidShow"
keyboardHideMethod="keyboardDidHide"
/>
);

KeyboardSpacer.propTypes = windowDimensionsPropTypes;
KeyboardSpacer.displayName = 'KeyboardSpacer';

export default withWindowDimensions(KeyboardSpacer);
export default KeyboardSpacer;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove this file.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Ollyws Now that this file is removed, we may need to change comment in index.js
On non native platforms we do not need to implement a keyboard spacer, so we return a null component.
to something like this:
On non iOS platforms we do not need to implement a keyboard spacer, so we return a null component.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aimane-chnaif All done.

2 changes: 1 addition & 1 deletion src/components/Modal/BaseModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class BaseModal extends PureComponent {
backdropOpacity={hideBackdrop ? 0 : variables.overlayOpacity}
backdropTransitionOutTiming={0}
hasBackdrop={this.props.fullscreen}
coverScreen={this.props.fullscreen}
coverScreen={this.props.disableCoverScreen ? false : this.props.fullscreen}
style={modalStyle}
deviceHeight={this.props.windowHeight}
deviceWidth={this.props.windowWidth}
Expand Down
1 change: 1 addition & 0 deletions src/components/PasswordPopover/BasePasswordPopover.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class BasePasswordPopover extends Component {
render() {
return (
<Popover
disableCoverScreen={this.props.disableCoverScreen}
isVisible={this.props.isVisible}
onClose={this.props.onClose}
anchorPosition={this.props.anchorPosition}
Expand Down
69 changes: 69 additions & 0 deletions src/components/withViewportOffsetTop.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import lodashGet from 'lodash/get';
import getComponentDisplayName from '../libs/getComponentDisplayName';
import addViewportResizeListener from '../libs/VisualViewport';

const viewportOffsetTopPropTypes = {
viewportOffsetTop: PropTypes.number.isRequired,
jasperhuangg marked this conversation as resolved.
Show resolved Hide resolved
};

export default function (WrappedComponent) {
class WithViewportOffsetTop extends Component {
constructor(props) {
super(props);

this.updateDimensions = this.updateDimensions.bind(this);

this.state = {
viewportOffsetTop: 0,
};
}

componentDidMount() {
this.removeViewportResizeListener = addViewportResizeListener(this.updateDimensions);
}

componentWillUnmount() {
this.removeViewportResizeListener();
}

/**
* @param {SyntheticEvent} e
*/
updateDimensions(e) {
const viewportOffsetTop = lodashGet(e, 'target.offsetTop', 0);
this.setState({viewportOffsetTop});
}

render() {
return (
<WrappedComponent
// eslint-disable-next-line react/jsx-props-no-spreading
{...this.props}
ref={this.props.forwardedRef}
viewportOffsetTop={this.state.viewportOffsetTop}
/>
);
}
}

WithViewportOffsetTop.displayName = `WithViewportOffsetTop(${getComponentDisplayName(WrappedComponent)})`;
WithViewportOffsetTop.propTypes = {
forwardedRef: PropTypes.oneOfType([
PropTypes.func,
PropTypes.shape({current: PropTypes.instanceOf(React.Component)}),
]),
};
WithViewportOffsetTop.defaultProps = {
forwardedRef: undefined,
};
return React.forwardRef((props, ref) => (
// eslint-disable-next-line react/jsx-props-no-spreading
<WithViewportOffsetTop {...props} forwardedRef={ref} />
));
}

export {
viewportOffsetTopPropTypes,
};
22 changes: 4 additions & 18 deletions src/pages/home/ReportScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import CONST from '../../CONST';
import ReportActionsSkeletonView from '../../components/ReportActionsSkeletonView';
import reportActionPropTypes from './report/reportActionPropTypes';
import toggleReportActionComposeView from '../../libs/toggleReportActionComposeView';
import addViewportResizeListener from '../../libs/VisualViewport';
import {withNetwork} from '../../components/OnyxProvider';
import compose from '../../libs/compose';
import networkPropTypes from '../../components/networkPropTypes';
Expand All @@ -33,6 +32,7 @@ import withLocalize from '../../components/withLocalize';
import reportPropTypes from '../reportPropTypes';
import FullPageNotFoundView from '../../components/BlockingViews/FullPageNotFoundView';
import ReportHeaderSkeletonView from '../../components/ReportHeaderSkeletonView';
import withViewportOffsetTop, {viewportOffsetTopPropTypes} from '../../components/withViewportOffsetTop';

const propTypes = {
/** Navigation route context info provided by react navigation */
Expand Down Expand Up @@ -73,6 +73,7 @@ const propTypes = {

...windowDimensionsPropTypes,
...withDrawerPropTypes,
...viewportOffsetTopPropTypes,
};

const defaultProps = {
Expand Down Expand Up @@ -107,22 +108,18 @@ class ReportScreen extends React.Component {
super(props);

this.onSubmitComment = this.onSubmitComment.bind(this);
this.updateViewportOffsetTop = this.updateViewportOffsetTop.bind(this);
this.chatWithAccountManager = this.chatWithAccountManager.bind(this);
this.dismissBanner = this.dismissBanner.bind(this);
this.removeViewportResizeListener = () => {};

this.state = {
skeletonViewContainerHeight: reportActionsListViewHeight,
viewportOffsetTop: 0,
isBannerVisible: true,
};
}

componentDidMount() {
this.fetchReportIfNeeded();
toggleReportActionComposeView(true);
this.removeViewportResizeListener = addViewportResizeListener(this.updateViewportOffsetTop);
}

componentDidUpdate(prevProps) {
Expand All @@ -134,10 +131,6 @@ class ReportScreen extends React.Component {
toggleReportActionComposeView(true);
}

componentWillUnmount() {
this.removeViewportResizeListener();
}

/**
* @param {String} text
*/
Expand Down Expand Up @@ -171,14 +164,6 @@ class ReportScreen extends React.Component {
Report.openReport(reportIDFromPath);
}

/**
* @param {SyntheticEvent} e
*/
updateViewportOffsetTop(e) {
const viewportOffsetTop = lodashGet(e, 'target.offsetTop', 0);
this.setState({viewportOffsetTop});
}

dismissBanner() {
this.setState({isBannerVisible: false});
}
Expand Down Expand Up @@ -214,7 +199,7 @@ class ReportScreen extends React.Component {
const reportID = getReportID(this.props.route);
const addWorkspaceRoomOrChatPendingAction = lodashGet(this.props.report, 'pendingFields.addWorkspaceRoom') || lodashGet(this.props.report, 'pendingFields.createChat');
const addWorkspaceRoomOrChatErrors = lodashGet(this.props.report, 'errorFields.addWorkspaceRoom') || lodashGet(this.props.report, 'errorFields.createChat');
const screenWrapperStyle = [styles.appContent, styles.flex1, {marginTop: this.state.viewportOffsetTop}];
const screenWrapperStyle = [styles.appContent, styles.flex1, {marginTop: this.props.viewportOffsetTop}];

// There are no reportActions at all to display and we are still in the process of loading the next set of actions.
const isLoadingInitialReportActions = _.isEmpty(this.props.reportActions) && this.props.report.isLoadingReportActions;
Expand Down Expand Up @@ -332,6 +317,7 @@ ReportScreen.propTypes = propTypes;
ReportScreen.defaultProps = defaultProps;

export default compose(
withViewportOffsetTop,
withLocalize,
withWindowDimensions,
withDrawerState,
Expand Down
6 changes: 5 additions & 1 deletion src/pages/settings/Payments/PaymentsPage/BasePaymentsPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import OfflineWithFeedback from '../../../../components/OfflineWithFeedback';
import ConfirmContent from '../../../../components/ConfirmContent';
import Button from '../../../../components/Button';
import themeColors from '../../../../styles/themes/default';
import withViewportOffsetTop from '../../../../components/withViewportOffsetTop';

class BasePaymentsPage extends React.Component {
constructor(props) {
Expand Down Expand Up @@ -341,8 +342,9 @@ class BasePaymentsPage extends React.Component {

// Determines whether or not the modal popup is mounted from the bottom of the screen instead of the side mount on Web or Desktop screens
const isPopoverBottomMount = this.state.anchorPositionTop === 0 || this.props.isSmallScreenWidth;
const screenWrapperStyle = [{marginTop: this.props.viewportOffsetTop}];
return (
<ScreenWrapper>
<ScreenWrapper style={screenWrapperStyle}>
<HeaderWithCloseButton
title={this.props.translate('common.payments')}
shouldShowBackButton
Expand Down Expand Up @@ -478,6 +480,7 @@ class BasePaymentsPage extends React.Component {
)}
</Popover>
<PasswordPopover
disableCoverScreen
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's add comment what this prop is for

isVisible={this.state.shouldShowPasswordPrompt}
onClose={this.hidePasswordPrompt}
anchorPosition={{
Expand All @@ -499,6 +502,7 @@ BasePaymentsPage.propTypes = propTypes;
BasePaymentsPage.defaultProps = defaultProps;

export default compose(
withViewportOffsetTop,
withWindowDimensions,
withLocalize,
withNetwork(),
Expand Down