Skip to content

Commit

Permalink
Merge pull request #2222 from npsedhain/npsedhain-create-menu
Browse files Browse the repository at this point in the history
Display create menu within the chat area and add bottom up transition.
  • Loading branch information
tgolen authored Apr 15, 2021
2 parents a8006fe + 4bcd10f commit e7330c4
Show file tree
Hide file tree
Showing 10 changed files with 202 additions and 19 deletions.
3 changes: 3 additions & 0 deletions src/CONST.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ const CONST = {
CENTERED: 'centered',
BOTTOM_DOCKED: 'bottom_docked',
POPOVER: 'popover',
POPOVER_LEFT_DOCKED: 'popover_left_docked',
POPOVER_RIGHT_DOCKED: 'popover_right_docked',
POPOVER_CENTER_BOTTOM: 'popover_center_bottom',
RIGHT_DOCKED: 'right_docked',
},
ANCHOR_ORIGIN_VERTICAL: {
Expand Down
99 changes: 99 additions & 0 deletions src/components/CreateMenu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import React, {PureComponent} from 'react';
import {View} from 'react-native';
import PropTypes from 'prop-types';
import Popover from './Popover';
import styles from '../styles/styles';
import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimensions';
import MenuItem from './MenuItem';
import CONST from '../CONST';
import {propTypes as ModalPropTypes} from './Modal/ModalPropTypes';

const propTypes = {
// Callback to fire on request to modal close
onClose: PropTypes.func.isRequired,

// State that determines whether to display the create menu or not
isVisible: PropTypes.bool.isRequired,

// Callback to fire when a CreateMenu item is selected
onItemSelected: PropTypes.func.isRequired,

// Gives the type of the modal
popOverType: ModalPropTypes.type,

// Menu items to be rendered on the list
menuItems: PropTypes.arrayOf(
PropTypes.shape({
icon: PropTypes.func.isRequired,
text: PropTypes.string.isRequired,
onSelected: PropTypes.func.isRequired,
}),
).isRequired,

...windowDimensionsPropTypes,
};

const defaultProps = {
popOverType: CONST.MODAL.MODAL_TYPE.POPOVER_LEFT_DOCKED,
};

class CreateMenu extends PureComponent {
constructor(props) {
super(props);
this.onModalHide = () => {};
this.setOnModalHide = this.setOnModalHide.bind(this);
this.resetOnModalHide = this.resetOnModalHide.bind(this);
}

/**
* Sets a new function to execute when the modal hides
* @param {Function} callback The function to be called on modal hide
*/
setOnModalHide(callback) {
this.onModalHide = callback;
}

/**
* After the modal hides, reset the onModalHide to an empty function
*/
resetOnModalHide() {
this.onModalHide = () => {};
}

render() {
return (
<Popover
onClose={this.props.onClose}
isVisible={this.props.isVisible}
onModalHide={() => {
this.onModalHide();
this.resetOnModalHide();
}}
popOverType={this.props.popOverType}
>
<View style={this.props.isSmallScreenWidth ? {} : styles.createMenuContainer}>
{this.props.menuItems.map(({
icon,
text,
onSelected = () => {},
}) => (
<MenuItem
key={text}
icon={icon}
title={text}
onPress={() => {
this.props.onItemSelected();
this.setOnModalHide(onSelected);
}}
/>
))}
</View>
</Popover>
);
}
}

CreateMenu.propTypes = propTypes;
CreateMenu.defaultProps = defaultProps;
CreateMenu.displayName = 'CreateMenu';
export default withWindowDimensions(CreateMenu);
9 changes: 2 additions & 7 deletions src/components/Modal/ModalPropTypes.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import PropTypes from 'prop-types';
import _ from 'underscore';
import CONST from '../../CONST';
import {windowDimensionsPropTypes} from '../withWindowDimensions';

Expand All @@ -19,13 +20,7 @@ const propTypes = {
onModalHide: PropTypes.func,

// Style of modal to display
type: PropTypes.oneOf([
CONST.MODAL.MODAL_TYPE.CONFIRM,
CONST.MODAL.MODAL_TYPE.CENTERED,
CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED,
CONST.MODAL.MODAL_TYPE.POPOVER,
CONST.MODAL.MODAL_TYPE.RIGHT_DOCKED,
]),
type: PropTypes.oneOf(_.values(CONST.MODAL.MODAL_TYPE)),

// A react-native-animatable animation definition for the modal display animation.
animationIn: PropTypes.oneOfType([
Expand Down
3 changes: 3 additions & 0 deletions src/components/Popover/PopoverPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ const propTypes = {
bottom: PropTypes.number,
left: PropTypes.number,
}).isRequired,

// Describes what type of pop over is it - based on the position
popOverType: modalPropTypes.type,
};

const defaultProps = {
Expand Down
41 changes: 31 additions & 10 deletions src/components/Popover/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,42 @@ import {propTypes, defaultProps} from './PopoverPropTypes';
import CONST from '../../CONST';
import Modal from '../Modal';
import withWindowDimensions from '../withWindowDimensions';
import styles from '../../styles/styles';

/*
* This is a convenience wrapper around the Modal component for a responsive Popover.
* On small screen widths, it uses BottomDocked modal type, and a Popover on wide screen widths.
* On small screen widths, it uses BottomDocked modal type, and a Popover type on wide screen widths.
*/
const Popover = props => (
<Modal
type={props.isSmallScreenWidth ? CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED : CONST.MODAL.MODAL_TYPE.POPOVER}
popoverAnchorPosition={props.anchorPosition}
const Popover = (props) => {
/**
* Get the anchor position using the type of the modal into account
* @param {String} type
* @returns {Object}
*/
function getAnchorPosition(type) {
switch (type) {
case CONST.MODAL.MODAL_TYPE.POPOVER_LEFT_DOCKED:
return styles.createMenuPositionSidebar;
case CONST.MODAL.MODAL_TYPE.POPOVER_CENTER_BOTTOM:
return styles.createMenuPositionReportCompose;
case CONST.MODAL.MODAL_TYPE.POPOVER_RIGHT_DOCKED:
return styles.createMenuPositionProfile;
default:
return styles.createMenuPositionSidebar;
}
}

return (
<Modal
type={props.isSmallScreenWidth ? CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED : props.popOverType}
popoverAnchorPosition={getAnchorPosition(props.popOverType)}
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
animationIn={props.isSmallScreenWidth ? undefined : props.animationIn}
animationOut={props.isSmallScreenWidth ? undefined : props.animationOut}
/>
);
{...props}
animationIn={props.isSmallScreenWidth ? undefined : props.animationIn}
animationOut={props.isSmallScreenWidth ? undefined : props.animationOut}
/>
);
};

Popover.propTypes = propTypes;
Popover.defaultProps = defaultProps;
Expand Down
2 changes: 2 additions & 0 deletions src/pages/home/report/ReportActionCompose.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import ReportTypingIndicator from './ReportTypingIndicator';
import AttachmentModal from '../../../components/AttachmentModal';
import compose from '../../../libs/compose';
import CreateMenu from '../../../components/CreateMenu';
import CONST from '../../../CONST';
import withWindowDimensions from '../../../components/withWindowDimensions';
import withDrawerState from '../../../components/withDrawerState';
import canFocusInputOnScreenFocus from '../../../libs/canFocusInputOnScreenFocus';
Expand Down Expand Up @@ -247,6 +248,7 @@ class ReportActionCompose extends React.Component {
isVisible={this.state.isMenuVisible}
onClose={() => this.setMenuVisibility(false)}
onItemSelected={() => this.setMenuVisibility(false)}
popOverType={CONST.MODAL.MODAL_TYPE.POPOVER_CENTER_BOTTOM}
menuItems={[
{
icon: Paperclip,
Expand Down
1 change: 1 addition & 0 deletions src/pages/home/sidebar/SidebarScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class SidebarScreen extends Component {
<CreateMenu
onClose={this.toggleCreateMenu}
isVisible={this.state.isCreateMenuActive}
popOverType={CONST.MODAL.MODAL_TYPE.POPOVER_LEFT_DOCKED}
onItemSelected={this.onCreateMenuItemSelected}
menuItems={[
{
Expand Down
1 change: 1 addition & 0 deletions src/pages/settings/Profile/ProfilePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ class ProfilePage extends Component {
onClose={() => this.setState({isEditPhotoMenuVisible: false})}
onItemSelected={() => this.setState({isEditPhotoMenuVisible: false})}
menuItems={this.createMenuItems(openPicker)}
popOverType={CONST.MODAL.MODAL_TYPE.POPOVER_RIGHT_DOCKED}
/>
</>
)}
Expand Down
50 changes: 49 additions & 1 deletion src/styles/getModalStyles.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export default (type, windowDimensions, popoverAnchorPosition = {}) => {
animationIn = 'slideInUp';
animationOut = 'slideOutDown';
break;
case CONST.MODAL.MODAL_TYPE.POPOVER:
case CONST.MODAL.MODAL_TYPE.POPOVER_LEFT_DOCKED:
modalStyle = {
...modalStyle,
...popoverAnchorPosition,
Expand All @@ -134,6 +134,54 @@ export default (type, windowDimensions, popoverAnchorPosition = {}) => {
animationIn = 'fadeInLeft';
animationOut = 'fadeOutLeft';
break;
case CONST.MODAL.MODAL_TYPE.POPOVER_RIGHT_DOCKED:
modalStyle = {
...modalStyle,
...popoverAnchorPosition,
...{
position: 'absolute',
alignItems: 'center',
justifyContent: 'flex-end',
},
};
modalContainerStyle = {
borderRadius: 12,
borderWidth: 1,
borderColor: themeColors.border,
justifyContent: 'center',
overflow: 'hidden',
boxShadow: '0px 0px 10px 0px rgba(0, 0, 0, 0.025)',
};

hideBackdrop = true;
swipeDirection = undefined;
animationIn = 'fadeInRight';
animationOut = 'fadeOutRight';
break;
case CONST.MODAL.MODAL_TYPE.POPOVER_CENTER_BOTTOM:
modalStyle = {
...modalStyle,
...popoverAnchorPosition,
...{
position: 'absolute',
alignItems: 'center',
justifyContent: 'flex-end',
},
};
modalContainerStyle = {
borderRadius: 12,
borderWidth: 1,
borderColor: themeColors.border,
justifyContent: 'center',
overflow: 'hidden',
boxShadow: '0px 0px 10px 0px rgba(0, 0, 0, 0.025)',
};

hideBackdrop = true;
swipeDirection = undefined;
animationIn = 'fadeInUp';
animationOut = 'fadeOutDown';
break;
case CONST.MODAL.MODAL_TYPE.RIGHT_DOCKED:
modalStyle = {
...modalStyle,
Expand Down
12 changes: 11 additions & 1 deletion src/styles/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -494,11 +494,21 @@ const styles = {
textDecorationLine: 'none',
},

createMenuPosition: {
createMenuPositionSidebar: {
left: 18,
bottom: 100,
},

createMenuPositionProfile: {
right: 18,
top: 100,
},

createMenuPositionReportCompose: {
left: 18 + variables.sideBarWidth,
bottom: 75,
},

createMenuContainer: {
width: variables.sideBarWidth - 40,
paddingVertical: 12,
Expand Down

0 comments on commit e7330c4

Please sign in to comment.