diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js index 489e860d7102..1586c2fb7e07 100755 --- a/src/components/MoneyRequestConfirmationList.js +++ b/src/components/MoneyRequestConfirmationList.js @@ -97,6 +97,9 @@ const propTypes = { /** File source of the receipt */ receiptSource: PropTypes.string, + /** List styles for OptionsSelector */ + listStyles: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), + /* Onyx Props */ /** Collection of categories attached to a policy */ policyCategories: PropTypes.objectOf(categoryPropTypes), @@ -120,6 +123,7 @@ const defaultProps = { ...withCurrentUserPersonalDetailsDefaultProps, receiptPath: '', receiptSource: '', + listStyles: [], policyCategories: {}, }; @@ -344,6 +348,7 @@ function MoneyRequestConfirmationList(props) { shouldUseStyleForChildren={false} optionHoveredStyle={canModifyParticipants ? styles.hoveredComponentBG : {}} footerContent={footerContent} + listStyles={props.listStyles} > {!_.isEmpty(props.receiptPath) ? ( {}, onScroll: () => {}, + listStyles: [], ...optionsListDefaultProps, }; @@ -35,6 +39,7 @@ function BaseOptionsList({ keyboardDismissMode, onScrollBeginDrag, onScroll, + listStyles, focusedIndex, selectedOptions, headerMessage, @@ -219,6 +224,8 @@ function BaseOptionsList({ ) : null} diff --git a/src/pages/iou/steps/MoneyRequestAmountForm.js b/src/pages/iou/steps/MoneyRequestAmountForm.js index 1d7444397c0e..1ea0b002b235 100644 --- a/src/pages/iou/steps/MoneyRequestAmountForm.js +++ b/src/pages/iou/steps/MoneyRequestAmountForm.js @@ -1,5 +1,5 @@ import React, {useEffect, useState, useCallback, useRef} from 'react'; -import {View} from 'react-native'; +import {ScrollView, View} from 'react-native'; import PropTypes from 'prop-types'; import lodashGet from 'lodash/get'; import _ from 'underscore'; @@ -200,7 +200,7 @@ function MoneyRequestAmountForm({amount, currency, isEditing, forwardedRef, onCu const buttonText = isEditing ? translate('common.save') : translate('common.next'); return ( - <> + onMouseDown(event, [AMOUNT_VIEW_ID])} @@ -253,7 +253,7 @@ function MoneyRequestAmountForm({amount, currency, isEditing, forwardedRef, onCu text={buttonText} /> - + ); } diff --git a/src/pages/iou/steps/MoneyRequestConfirmPage.js b/src/pages/iou/steps/MoneyRequestConfirmPage.js index e41b2c6057a7..42ae312ec8a2 100644 --- a/src/pages/iou/steps/MoneyRequestConfirmPage.js +++ b/src/pages/iou/steps/MoneyRequestConfirmPage.js @@ -1,5 +1,5 @@ import React, {useCallback, useEffect, useMemo, useRef} from 'react'; -import {View} from 'react-native'; +import {ScrollView, View} from 'react-native'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; @@ -22,6 +22,8 @@ import reportPropTypes from '../../reportPropTypes'; import personalDetailsPropType from '../../personalDetailsPropType'; import * as FileUtils from '../../../libs/fileDownload/FileUtils'; import * as Policy from '../../../libs/actions/Policy'; +import useWindowDimensions from '../../../hooks/useWindowDimensions'; +import * as StyleUtils from '../../../styles/StyleUtils'; import {iouPropTypes, iouDefaultProps} from '../propTypes'; const propTypes = { @@ -56,6 +58,7 @@ const defaultProps = { }; function MoneyRequestConfirmPage(props) { + const {windowHeight} = useWindowDimensions(); const prevMoneyRequestId = useRef(props.iou.id); const iouType = useRef(lodashGet(props.route, 'params.iouType', '')); const reportID = useRef(lodashGet(props.route, 'params.reportID', '')); @@ -223,38 +226,51 @@ function MoneyRequestConfirmPage(props) { title={props.translate('iou.cash')} onBackButtonPress={navigateBack} /> - { - const newParticipants = _.map(props.iou.participants, (participant) => { - if (participant.accountID === option.accountID) { - return {...participant, selected: !participant.selected}; - } - return participant; - }); - IOU.setMoneyRequestParticipants(newParticipants); - }} - receiptPath={props.iou.receiptPath} - receiptSource={props.iou.receiptSource} - iouType={iouType.current} - reportID={reportID.current} - // The participants can only be modified when the action is initiated from directly within a group chat and not the floating-action-button. - // This is because when there is a group of people, say they are on a trip, and you have some shared expenses with some of the people, - // but not all of them (maybe someone skipped out on dinner). Then it's nice to be able to select/deselect people from the group chat bill - // split rather than forcing the user to create a new group, just for that expense. The reportID is empty, when the action was initiated from - // the floating-action-button (since it is something that exists outside the context of a report). - canModifyParticipants={!_.isEmpty(reportID.current)} - policyID={props.report.policyID} - bankAccountRoute={ReportUtils.getBankAccountRoute(props.report)} - iouMerchant={props.iou.merchant} - iouCreated={props.iou.created} - /> + {/* + * The MoneyRequestConfirmationList component uses a SectionList which uses a VirtualizedList internally. + * VirtualizedList cannot be directly nested within ScrollViews of the same orientation. + * To work around this, we wrap the MoneyRequestConfirmationList component with a horizontal ScrollView. + */} + + + { + const newParticipants = _.map(props.iou.participants, (participant) => { + if (participant.accountID === option.accountID) { + return {...participant, selected: !participant.selected}; + } + return participant; + }); + IOU.setMoneyRequestParticipants(newParticipants); + }} + receiptPath={props.iou.receiptPath} + receiptSource={props.iou.receiptSource} + iouType={iouType.current} + reportID={reportID.current} + // The participants can only be modified when the action is initiated from directly within a group chat and not the floating-action-button. + // This is because when there is a group of people, say they are on a trip, and you have some shared expenses with some of the people, + // but not all of them (maybe someone skipped out on dinner). Then it's nice to be able to select/deselect people from the group chat bill + // split rather than forcing the user to create a new group, just for that expense. The reportID is empty, when the action was initiated from + // the floating-action-button (since it is something that exists outside the context of a report). + canModifyParticipants={!_.isEmpty(reportID.current)} + policyID={props.report.policyID} + bankAccountRoute={ReportUtils.getBankAccountRoute(props.report)} + iouMerchant={props.iou.merchant} + iouCreated={props.iou.created} + listStyles={[StyleUtils.getMaximumHeight(windowHeight / 3)]} + /> + + )} diff --git a/src/styles/StyleUtils.js b/src/styles/StyleUtils.js index 9dcf954e84fd..da9c77ac9fe7 100644 --- a/src/styles/StyleUtils.js +++ b/src/styles/StyleUtils.js @@ -833,6 +833,17 @@ function getMinimumHeight(minHeight) { }; } +/** + * Get maximum height as style + * @param {Number} maxHeight + * @returns {Object} + */ +function getMaximumHeight(maxHeight) { + return { + maxHeight, + }; +} + /** * Get maximum width as style * @param {Number} maxWidth @@ -1370,6 +1381,7 @@ export { hasSafeAreas, getHeight, getMinimumHeight, + getMaximumHeight, getMaximumWidth, fade, getHorizontalStackedAvatarBorderStyle,