diff --git a/src/components/ScreenWrapper/BaseScreenWrapper.js b/src/components/ScreenWrapper/BaseScreenWrapper.js
index a80a013a1c66..56a0c30b2ecf 100644
--- a/src/components/ScreenWrapper/BaseScreenWrapper.js
+++ b/src/components/ScreenWrapper/BaseScreenWrapper.js
@@ -44,6 +44,23 @@ class BaseScreenWrapper extends React.Component {
});
}
+ /**
+ * We explicitly want to ignore if props.modal changes, and only want to rerender if
+ * any of the other props **used for the rendering output** is changed.
+ * @param {Object} nextProps
+ * @param {Object} nextState
+ * @returns {boolean}
+ */
+ shouldComponentUpdate(nextProps, nextState) {
+ return this.state !== nextState
+ || this.props.children !== nextProps.children
+ || this.props.network.isOffline !== nextProps.network.isOffline
+ || this.props.includePaddingBottom !== nextProps.includePaddingBottom
+ || this.props.includePaddingTop !== nextProps.includePaddingTop
+ || this.props.isSmallScreenWidth !== nextProps.isSmallScreenWidth
+ || this.props.keyboardAvoidingViewBehavior !== nextProps.keyboardAvoidingViewBehavior;
+ }
+
componentWillUnmount() {
if (this.unsubscribeEscapeKey) {
this.unsubscribeEscapeKey();
diff --git a/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js b/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js
index 6dfb496cb28f..2f9eb5c4c2bc 100644
--- a/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js
+++ b/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js
@@ -1,56 +1,31 @@
import lodashGet from 'lodash/get';
-import _ from 'underscore';
import React, {Component} from 'react';
import {View} from 'react-native';
-import PropTypes from 'prop-types';
import styles from '../../../../styles/styles';
import SidebarLinks from '../SidebarLinks';
-import PopoverMenu from '../../../../components/PopoverMenu';
-import FloatingActionButton from '../../../../components/FloatingActionButton';
import ScreenWrapper from '../../../../components/ScreenWrapper';
import Navigation from '../../../../libs/Navigation/Navigation';
import ROUTES from '../../../../ROUTES';
import Timing from '../../../../libs/actions/Timing';
import CONST from '../../../../CONST';
-import * as Expensicons from '../../../../components/Icon/Expensicons';
-import Permissions from '../../../../libs/Permissions';
-import * as Policy from '../../../../libs/actions/Policy';
import Performance from '../../../../libs/Performance';
import * as Welcome from '../../../../libs/actions/Welcome';
-import {sidebarPropTypes, sidebarDefaultProps} from './sidebarPropTypes';
import withDrawerState from '../../../../components/withDrawerState';
+import withWindowDimensions, {windowDimensionsPropTypes} from '../../../../components/withWindowDimensions';
+import compose from '../../../../libs/compose';
+import sidebarPropTypes from './sidebarPropTypes';
const propTypes = {
-
- /** Callback function when the menu is shown */
- onShowCreateMenu: PropTypes.func,
-
- /** Callback function before the menu is hidden */
- onHideCreateMenu: PropTypes.func,
-
- /** reportID in the current navigation state */
- reportIDFromRoute: PropTypes.string,
-
...sidebarPropTypes,
-};
-const defaultProps = {
- onHideCreateMenu: () => {},
- onShowCreateMenu: () => {},
- ...sidebarDefaultProps,
+ ...windowDimensionsPropTypes,
};
class BaseSidebarScreen extends Component {
constructor(props) {
super(props);
- this.hideCreateMenu = this.hideCreateMenu.bind(this);
this.startTimer = this.startTimer.bind(this);
this.navigateToSettings = this.navigateToSettings.bind(this);
- this.showCreateMenu = this.showCreateMenu.bind(this);
-
- this.state = {
- isCreateMenuActive: false,
- };
}
componentDidMount() {
@@ -61,16 +36,6 @@ class BaseSidebarScreen extends Component {
Welcome.show({routes, showCreateMenu: this.showCreateMenu});
}
- /**
- * Method called when we click the floating action button
- */
- showCreateMenu() {
- this.setState({
- isCreateMenuActive: true,
- });
- this.props.onShowCreateMenu();
- }
-
/**
* Method called when avatar is clicked
*/
@@ -78,18 +43,6 @@ class BaseSidebarScreen extends Component {
Navigation.navigate(ROUTES.SETTINGS);
}
- /**
- * Method called either when:
- * Pressing the floating action button to open the CreateMenu modal
- * Selecting an item on CreateMenu or closing it by clicking outside of the modal component
- */
- hideCreateMenu() {
- this.props.onHideCreateMenu();
- this.setState({
- isCreateMenuActive: false,
- });
- }
-
/**
* Method called when a pinned chat is selected.
*/
@@ -99,89 +52,22 @@ class BaseSidebarScreen extends Component {
}
render() {
- // Workspaces are policies with type === 'free'
- const workspaces = _.filter(this.props.allPolicies, policy => policy && policy.type === CONST.POLICY.TYPE.FREE);
return (
{({insets}) => (
- <>
-
-
-
-
- Navigation.navigate(ROUTES.NEW_CHAT),
- },
- {
- icon: Expensicons.Users,
- text: this.props.translate('sidebarScreen.newGroup'),
- onSelected: () => Navigation.navigate(ROUTES.NEW_GROUP),
- },
- ...(Permissions.canUsePolicyRooms(this.props.betas) && workspaces.length ? [
- {
- icon: Expensicons.Hashtag,
- text: this.props.translate('sidebarScreen.newRoom'),
- onSelected: () => Navigation.navigate(ROUTES.WORKSPACE_NEW_ROOM),
- },
- ] : []),
- ...(Permissions.canUseIOUSend(this.props.betas) ? [
- {
- icon: Expensicons.Send,
- text: this.props.translate('iou.sendMoney'),
- onSelected: () => Navigation.navigate(ROUTES.IOU_SEND),
- },
- ] : []),
- ...(Permissions.canUseIOU(this.props.betas) ? [
- {
- icon: Expensicons.MoneyCircle,
- text: this.props.translate('iou.requestMoney'),
- onSelected: () => Navigation.navigate(ROUTES.IOU_REQUEST),
- },
- ] : []),
- ...(Permissions.canUseIOU(this.props.betas) ? [
- {
- icon: Expensicons.Receipt,
- text: this.props.translate('iou.splitBill'),
- onSelected: () => Navigation.navigate(ROUTES.IOU_BILL),
- },
- ] : []),
- ...(!Policy.isAdminOfFreePolicy(this.props.allPolicies) ? [
- {
- icon: Expensicons.NewWorkspace,
- iconWidth: 46,
- iconHeight: 40,
- text: this.props.translate('workspace.new.newWorkspace'),
- description: this.props.translate('workspace.new.getTheExpensifyCardAndMore'),
- onSelected: () => Policy.createWorkspace(),
- },
- ] : []),
- ]}
+
+
- >
+
)}
);
@@ -189,6 +75,8 @@ class BaseSidebarScreen extends Component {
}
BaseSidebarScreen.propTypes = propTypes;
-BaseSidebarScreen.defaultProps = defaultProps;
-export default withDrawerState(BaseSidebarScreen);
+export default compose(
+ withWindowDimensions,
+ withDrawerState,
+)(BaseSidebarScreen);
diff --git a/src/pages/home/sidebar/SidebarScreen/PopoverModal.js b/src/pages/home/sidebar/SidebarScreen/PopoverModal.js
new file mode 100644
index 000000000000..6b62f5875dd2
--- /dev/null
+++ b/src/pages/home/sidebar/SidebarScreen/PopoverModal.js
@@ -0,0 +1,170 @@
+import React from 'react';
+import _ from 'underscore';
+import {withOnyx} from 'react-native-onyx';
+import PropTypes from 'prop-types';
+import styles from '../../../../styles/styles';
+import * as Expensicons from '../../../../components/Icon/Expensicons';
+import Navigation from '../../../../libs/Navigation/Navigation';
+import ROUTES from '../../../../ROUTES';
+import Permissions from '../../../../libs/Permissions';
+import * as Policy from '../../../../libs/actions/Policy';
+import PopoverMenu from '../../../../components/PopoverMenu';
+import CONST from '../../../../CONST';
+import FloatingActionButton from '../../../../components/FloatingActionButton';
+import compose from '../../../../libs/compose';
+import withLocalize, {withLocalizePropTypes} from '../../../../components/withLocalize';
+import withWindowDimensions from '../../../../components/withWindowDimensions';
+import ONYXKEYS from '../../../../ONYXKEYS';
+
+const propTypes = {
+ /* Callback function when the menu is shown */
+ onShowCreateMenu: PropTypes.func,
+
+ /* Callback function before the menu is hidden */
+ onHideCreateMenu: PropTypes.func,
+
+ /** The list of policies the user has access to. */
+ allPolicies: PropTypes.shape({
+ /** The policy name */
+ name: PropTypes.string,
+ }),
+
+ /* Beta features list */
+ betas: PropTypes.arrayOf(PropTypes.string),
+
+ ...withLocalizePropTypes,
+};
+const defaultProps = {
+ onHideCreateMenu: () => {},
+ onShowCreateMenu: () => {},
+ allPolicies: {},
+ betas: [],
+};
+
+/**
+ * Responsible for rendering the {@link PopoverMenu}, and the accompanying
+ * FAB that can open or close the menu.
+ */
+class PopoverModal extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.showCreateMenu = this.showCreateMenu.bind(this);
+ this.hideCreateMenu = this.hideCreateMenu.bind(this);
+
+ this.state = {
+ isCreateMenuActive: false,
+ };
+ }
+
+ /**
+ * Method called when we click the floating action button
+ */
+ showCreateMenu() {
+ this.setState({
+ isCreateMenuActive: true,
+ });
+ this.props.onShowCreateMenu();
+ }
+
+ /**
+ * Method called either when:
+ * - Pressing the floating action button to open the CreateMenu modal
+ * - Selecting an item on CreateMenu or closing it by clicking outside of the modal component
+ */
+ hideCreateMenu() {
+ this.props.onHideCreateMenu();
+ this.setState({
+ isCreateMenuActive: false,
+ });
+ }
+
+ render() {
+ // Workspaces are policies with type === 'free'
+ const workspaces = _.filter(this.props.allPolicies, policy => policy && policy.type === CONST.POLICY.TYPE.FREE);
+
+ return (
+ <>
+ Navigation.navigate(ROUTES.NEW_CHAT),
+ },
+ {
+ icon: Expensicons.Users,
+ text: this.props.translate('sidebarScreen.newGroup'),
+ onSelected: () => Navigation.navigate(ROUTES.NEW_GROUP),
+ },
+ ...(Permissions.canUsePolicyRooms(this.props.betas) && workspaces.length ? [
+ {
+ icon: Expensicons.Hashtag,
+ text: this.props.translate('sidebarScreen.newRoom'),
+ onSelected: () => Navigation.navigate(ROUTES.WORKSPACE_NEW_ROOM),
+ },
+ ] : []),
+ ...(Permissions.canUseIOUSend(this.props.betas) ? [
+ {
+ icon: Expensicons.Send,
+ text: this.props.translate('iou.sendMoney'),
+ onSelected: () => Navigation.navigate(ROUTES.IOU_SEND),
+ },
+ ] : []),
+ ...(Permissions.canUseIOU(this.props.betas) ? [
+ {
+ icon: Expensicons.MoneyCircle,
+ text: this.props.translate('iou.requestMoney'),
+ onSelected: () => Navigation.navigate(ROUTES.IOU_REQUEST),
+ },
+ ] : []),
+ ...(Permissions.canUseIOU(this.props.betas) ? [
+ {
+ icon: Expensicons.Receipt,
+ text: this.props.translate('iou.splitBill'),
+ onSelected: () => Navigation.navigate(ROUTES.IOU_BILL),
+ },
+ ] : []),
+ ...(!Policy.isAdminOfFreePolicy(this.props.allPolicies) ? [
+ {
+ icon: Expensicons.NewWorkspace,
+ iconWidth: 46,
+ iconHeight: 40,
+ text: this.props.translate('workspace.new.newWorkspace'),
+ description: this.props.translate('workspace.new.getTheExpensifyCardAndMore'),
+ onSelected: () => Policy.createWorkspace(),
+ },
+ ] : []),
+ ]}
+ />
+
+ >
+ );
+ }
+}
+
+PopoverModal.propTypes = propTypes;
+PopoverModal.defaultProps = defaultProps;
+
+export default compose(
+ withLocalize,
+ withWindowDimensions,
+ withOnyx({
+ allPolicies: {
+ key: ONYXKEYS.COLLECTION.POLICY,
+ },
+ betas: {
+ key: ONYXKEYS.BETAS,
+ },
+ }),
+)(PopoverModal);
diff --git a/src/pages/home/sidebar/SidebarScreen/index.js b/src/pages/home/sidebar/SidebarScreen/index.js
index 584bcc49f8e4..75b5e07e7150 100755
--- a/src/pages/home/sidebar/SidebarScreen/index.js
+++ b/src/pages/home/sidebar/SidebarScreen/index.js
@@ -1,52 +1,41 @@
import React from 'react';
-import {withOnyx} from 'react-native-onyx';
-import compose from '../../../../libs/compose';
-import withWindowDimensions from '../../../../components/withWindowDimensions';
-import withLocalize from '../../../../components/withLocalize';
-import ONYXKEYS from '../../../../ONYXKEYS';
-import {sidebarPropTypes, sidebarDefaultProps} from './sidebarPropTypes';
+import sidebarPropTypes from './sidebarPropTypes';
import BaseSidebarScreen from './BaseSidebarScreen';
+import PopoverModal from './PopoverModal';
const SidebarScreen = (props) => {
- let baseSidebarScreen = null;
+ let popoverModal = null;
/**
* Method create event listener
*/
const createDragoverListener = () => {
- document.addEventListener('dragover', baseSidebarScreen.hideCreateMenu);
+ document.addEventListener('dragover', popoverModal.hideCreateMenu);
};
/**
* Method remove event listener.
*/
const removeDragoverListener = () => {
- document.removeEventListener('dragover', baseSidebarScreen.hideCreateMenu);
+ document.removeEventListener('dragover', popoverModal.hideCreateMenu);
};
+
return (
- baseSidebarScreen = el}
- onShowCreateMenu={createDragoverListener}
- onHideCreateMenu={removeDragoverListener}
- // eslint-disable-next-line react/jsx-props-no-spreading
- {...props}
- />
+ <>
+
+ popoverModal = el}
+ onShowCreateMenu={createDragoverListener}
+ onHideCreateMenu={removeDragoverListener}
+ />
+ >
);
};
SidebarScreen.propTypes = sidebarPropTypes;
-SidebarScreen.defaultProps = sidebarDefaultProps;
SidebarScreen.displayName = 'SidebarScreen';
-export default compose(
- withLocalize,
- withWindowDimensions,
- withOnyx({
- allPolicies: {
- key: ONYXKEYS.COLLECTION.POLICY,
- },
- betas: {
- key: ONYXKEYS.BETAS,
- },
- }),
-)(SidebarScreen);
+export default SidebarScreen;
diff --git a/src/pages/home/sidebar/SidebarScreen/index.native.js b/src/pages/home/sidebar/SidebarScreen/index.native.js
index e2cb2838efe8..cbf0d5c085a0 100755
--- a/src/pages/home/sidebar/SidebarScreen/index.native.js
+++ b/src/pages/home/sidebar/SidebarScreen/index.native.js
@@ -1,28 +1,19 @@
import React from 'react';
-import {withOnyx} from 'react-native-onyx';
-import compose from '../../../../libs/compose';
-import withWindowDimensions from '../../../../components/withWindowDimensions';
-import withLocalize from '../../../../components/withLocalize';
-import ONYXKEYS from '../../../../ONYXKEYS';
-import {sidebarPropTypes, sidebarDefaultProps} from './sidebarPropTypes';
+import sidebarPropTypes from './sidebarPropTypes';
import BaseSidebarScreen from './BaseSidebarScreen';
+import PopoverModal from './PopoverModal';
-// eslint-disable-next-line react/jsx-props-no-spreading
-const SidebarScreen = props => ;
+const SidebarScreen = props => (
+ <>
+
+
+ >
+);
SidebarScreen.propTypes = sidebarPropTypes;
-SidebarScreen.defaultProps = sidebarDefaultProps;
SidebarScreen.displayName = 'SidebarScreen';
-export default compose(
- withLocalize,
- withWindowDimensions,
- withOnyx({
- allPolicies: {
- key: ONYXKEYS.COLLECTION.POLICY,
- },
- betas: {
- key: ONYXKEYS.BETAS,
- },
- }),
-)(SidebarScreen);
+export default SidebarScreen;
diff --git a/src/pages/home/sidebar/SidebarScreen/sidebarPropTypes.js b/src/pages/home/sidebar/SidebarScreen/sidebarPropTypes.js
index 996bba9d676b..3affaa2d00be 100644
--- a/src/pages/home/sidebar/SidebarScreen/sidebarPropTypes.js
+++ b/src/pages/home/sidebar/SidebarScreen/sidebarPropTypes.js
@@ -1,26 +1,8 @@
import PropTypes from 'prop-types';
-import {windowDimensionsPropTypes} from '../../../../components/withWindowDimensions';
-import {withLocalizePropTypes} from '../../../../components/withLocalize';
const sidebarPropTypes = {
- /** The list of policies the user has access to. */
- allPolicies: PropTypes.shape({
- /** The policy name */
- name: PropTypes.string,
- }),
-
- /* Beta features list */
- betas: PropTypes.arrayOf(PropTypes.string),
-
- ...windowDimensionsPropTypes,
-
- ...withLocalizePropTypes,
+ /** reportID in the current navigation state */
+ reportIDFromRoute: PropTypes.string,
};
-
-const sidebarDefaultProps = {
- allPolicies: {},
- betas: [],
-};
-
-export {sidebarPropTypes, sidebarDefaultProps};
+export default sidebarPropTypes;