From 242aca500c964196b20cbc3facf86342faa62f7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Wed, 2 Nov 2022 10:03:58 +0100 Subject: [PATCH 01/14] Revert "revert PR 11907 which introduced missing FAB bug" This reverts commit 830ee4278b7353329c3df4e16d8de8a9357265bb. --- .../ScreenWrapper/BaseScreenWrapper.js | 17 ++ .../SidebarScreen/BaseSidebarScreen.js | 146 ++------------- .../sidebar/SidebarScreen/PopoverModal.js | 170 ++++++++++++++++++ src/pages/home/sidebar/SidebarScreen/index.js | 47 ++--- .../sidebar/SidebarScreen/index.native.js | 33 ++-- .../sidebar/SidebarScreen/sidebarPropTypes.js | 24 +-- 6 files changed, 237 insertions(+), 200 deletions(-) diff --git a/src/components/ScreenWrapper/BaseScreenWrapper.js b/src/components/ScreenWrapper/BaseScreenWrapper.js index a80a013a1c6..56a0c30b2ec 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 6dfb496cb28..2f9eb5c4c2b 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 index e69de29bb2d..6b62f5875dd 100644 --- a/src/pages/home/sidebar/SidebarScreen/PopoverModal.js +++ 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 584bcc49f8e..75b5e07e715 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 e2cb2838efe..cbf0d5c085a 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 996bba9d676..3affaa2d00b 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; From ee417723df404a856099742c3e00e894b24e77b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Wed, 2 Nov 2022 12:51:00 +0100 Subject: [PATCH 02/14] fix floating action button not showing --- src/components/FloatingActionButton.js | 2 +- .../SidebarScreen/BaseSidebarScreen.js | 23 +++++++++++-------- src/pages/home/sidebar/SidebarScreen/index.js | 11 ++++----- .../sidebar/SidebarScreen/index.native.js | 11 ++++----- src/styles/styles.js | 4 ++++ 5 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/components/FloatingActionButton.js b/src/components/FloatingActionButton.js index 5ed29189849..874eab6be6a 100644 --- a/src/components/FloatingActionButton.js +++ b/src/components/FloatingActionButton.js @@ -73,7 +73,7 @@ class FloatingActionButton extends PureComponent { }); return ( - + {({insets}) => ( - - - + <> + + + + {this.props.children} + )} ); diff --git a/src/pages/home/sidebar/SidebarScreen/index.js b/src/pages/home/sidebar/SidebarScreen/index.js index 75b5e07e715..afe4503bd1e 100755 --- a/src/pages/home/sidebar/SidebarScreen/index.js +++ b/src/pages/home/sidebar/SidebarScreen/index.js @@ -21,17 +21,16 @@ const SidebarScreen = (props) => { }; return ( - <> - + popoverModal = el} onShowCreateMenu={createDragoverListener} onHideCreateMenu={removeDragoverListener} /> - + ); }; diff --git a/src/pages/home/sidebar/SidebarScreen/index.native.js b/src/pages/home/sidebar/SidebarScreen/index.native.js index cbf0d5c085a..4145eef5337 100755 --- a/src/pages/home/sidebar/SidebarScreen/index.native.js +++ b/src/pages/home/sidebar/SidebarScreen/index.native.js @@ -4,13 +4,12 @@ import BaseSidebarScreen from './BaseSidebarScreen'; import PopoverModal from './PopoverModal'; const SidebarScreen = props => ( - <> - + - + ); SidebarScreen.propTypes = sidebarPropTypes; diff --git a/src/styles/styles.js b/src/styles/styles.js index 8cd7cbdce07..c196ed0c7b8 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -1027,6 +1027,10 @@ const styles = { }, }, + floatingActionButtonContainer: { + bottom: 0, + }, + floatingActionButton: { backgroundColor: themeColors.buttonSuccessBG, position: 'absolute', From ef9a878a47112fc578076cd0604fea830c8355a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Wed, 2 Nov 2022 21:13:56 +0100 Subject: [PATCH 03/14] remove unused style --- src/styles/styles.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/styles/styles.js b/src/styles/styles.js index c196ed0c7b8..8cd7cbdce07 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -1027,10 +1027,6 @@ const styles = { }, }, - floatingActionButtonContainer: { - bottom: 0, - }, - floatingActionButton: { backgroundColor: themeColors.buttonSuccessBG, position: 'absolute', From bd49a71a243f0cda17e75885788dad6f30b53225 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Wed, 2 Nov 2022 21:14:03 +0100 Subject: [PATCH 04/14] use height behavior --- src/components/FloatingActionButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/FloatingActionButton.js b/src/components/FloatingActionButton.js index 874eab6be6a..419a2749c02 100644 --- a/src/components/FloatingActionButton.js +++ b/src/components/FloatingActionButton.js @@ -73,7 +73,7 @@ class FloatingActionButton extends PureComponent { }); return ( - + Date: Thu, 10 Nov 2022 15:37:48 +0100 Subject: [PATCH 05/14] rename --- .../{PopoverModal.js => FABActionsPopover.js} | 8 ++++---- src/pages/home/sidebar/SidebarScreen/index.js | 4 ++-- src/pages/home/sidebar/SidebarScreen/index.native.js | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) rename src/pages/home/sidebar/SidebarScreen/{PopoverModal.js => FABActionsPopover.js} (97%) diff --git a/src/pages/home/sidebar/SidebarScreen/PopoverModal.js b/src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js similarity index 97% rename from src/pages/home/sidebar/SidebarScreen/PopoverModal.js rename to src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js index 6b62f5875dd..b50cde69840 100644 --- a/src/pages/home/sidebar/SidebarScreen/PopoverModal.js +++ b/src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js @@ -45,7 +45,7 @@ const defaultProps = { * Responsible for rendering the {@link PopoverMenu}, and the accompanying * FAB that can open or close the menu. */ -class PopoverModal extends React.Component { +class FABActionsPopover extends React.Component { constructor(props) { super(props); @@ -153,8 +153,8 @@ class PopoverModal extends React.Component { } } -PopoverModal.propTypes = propTypes; -PopoverModal.defaultProps = defaultProps; +FABActionsPopover.propTypes = propTypes; +FABActionsPopover.defaultProps = defaultProps; export default compose( withLocalize, @@ -167,4 +167,4 @@ export default compose( key: ONYXKEYS.BETAS, }, }), -)(PopoverModal); +)(FABActionsPopover); diff --git a/src/pages/home/sidebar/SidebarScreen/index.js b/src/pages/home/sidebar/SidebarScreen/index.js index afe4503bd1e..0b4b132294d 100755 --- a/src/pages/home/sidebar/SidebarScreen/index.js +++ b/src/pages/home/sidebar/SidebarScreen/index.js @@ -1,7 +1,7 @@ import React from 'react'; import sidebarPropTypes from './sidebarPropTypes'; import BaseSidebarScreen from './BaseSidebarScreen'; -import PopoverModal from './PopoverModal'; +import FABActionsPopover from './FABActionsPopover'; const SidebarScreen = (props) => { let popoverModal = null; @@ -25,7 +25,7 @@ const SidebarScreen = (props) => { // eslint-disable-next-line react/jsx-props-no-spreading {...props} > - popoverModal = el} onShowCreateMenu={createDragoverListener} onHideCreateMenu={removeDragoverListener} diff --git a/src/pages/home/sidebar/SidebarScreen/index.native.js b/src/pages/home/sidebar/SidebarScreen/index.native.js index 4145eef5337..cbada61b11c 100755 --- a/src/pages/home/sidebar/SidebarScreen/index.native.js +++ b/src/pages/home/sidebar/SidebarScreen/index.native.js @@ -1,14 +1,14 @@ import React from 'react'; import sidebarPropTypes from './sidebarPropTypes'; import BaseSidebarScreen from './BaseSidebarScreen'; -import PopoverModal from './PopoverModal'; +import FABActionsPopover from './FABActionsPopover'; const SidebarScreen = props => ( - + ); From 2f6133431d5ed1a1cbf3d45733213541812358f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Fri, 11 Nov 2022 16:45:00 +0100 Subject: [PATCH 06/14] fix welcome open FAB actions --- .../home/sidebar/SidebarScreen/BaseSidebarScreen.js | 5 ----- .../home/sidebar/SidebarScreen/FABActionsPopover.js | 9 +++++++++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js b/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js index 916c3abb9e3..14ca7bc531e 100644 --- a/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js +++ b/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js @@ -1,4 +1,3 @@ -import lodashGet from 'lodash/get'; import React, {Component} from 'react'; import {View} from 'react-native'; import styles from '../../../../styles/styles'; @@ -9,7 +8,6 @@ import ROUTES from '../../../../ROUTES'; import Timing from '../../../../libs/actions/Timing'; import CONST from '../../../../CONST'; import Performance from '../../../../libs/Performance'; -import * as Welcome from '../../../../libs/actions/Welcome'; import withDrawerState from '../../../../components/withDrawerState'; import KeyboardShortcutsModal from '../../../../components/KeyboardShortcutsModal'; import withWindowDimensions, {windowDimensionsPropTypes} from '../../../../components/withWindowDimensions'; @@ -32,9 +30,6 @@ class BaseSidebarScreen extends Component { componentDidMount() { Performance.markStart(CONST.TIMING.SIDEBAR_LOADED); Timing.start(CONST.TIMING.SIDEBAR_LOADED, true); - - const routes = lodashGet(this.props.navigation.getState(), 'routes', []); - Welcome.show({routes, showCreateMenu: this.showCreateMenu}); } /** diff --git a/src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js b/src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js index b50cde69840..f40dd2b9baa 100644 --- a/src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js +++ b/src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js @@ -2,6 +2,7 @@ import React from 'react'; import _ from 'underscore'; import {withOnyx} from 'react-native-onyx'; import PropTypes from 'prop-types'; +import lodashGet from 'lodash/get'; import styles from '../../../../styles/styles'; import * as Expensicons from '../../../../components/Icon/Expensicons'; import Navigation from '../../../../libs/Navigation/Navigation'; @@ -15,6 +16,8 @@ import compose from '../../../../libs/compose'; import withLocalize, {withLocalizePropTypes} from '../../../../components/withLocalize'; import withWindowDimensions from '../../../../components/withWindowDimensions'; import ONYXKEYS from '../../../../ONYXKEYS'; +import withNavigation from '../../../../components/withNavigation'; +import * as Welcome from '../../../../libs/actions/Welcome'; const propTypes = { /* Callback function when the menu is shown */ @@ -57,6 +60,11 @@ class FABActionsPopover extends React.Component { }; } + componentDidMount() { + const routes = lodashGet(this.props.navigation.getState(), 'routes', []); + Welcome.show({routes, showCreateMenu: this.showCreateMenu}); + } + /** * Method called when we click the floating action button */ @@ -158,6 +166,7 @@ FABActionsPopover.defaultProps = defaultProps; export default compose( withLocalize, + withNavigation, withWindowDimensions, withOnyx({ allPolicies: { From 38c1f3e219ac9c25d59c31e51b98ca18d49fa5fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Fri, 11 Nov 2022 17:42:25 +0100 Subject: [PATCH 07/14] beautify --- src/components/ScreenWrapper/BaseScreenWrapper.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/components/ScreenWrapper/BaseScreenWrapper.js b/src/components/ScreenWrapper/BaseScreenWrapper.js index e97ea784813..93c98414def 100644 --- a/src/components/ScreenWrapper/BaseScreenWrapper.js +++ b/src/components/ScreenWrapper/BaseScreenWrapper.js @@ -51,13 +51,8 @@ class BaseScreenWrapper extends React.Component { * @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; + return !_.isEqual(this.state, nextState) + || !_.isEqual(_.omit(this.props, 'modal'), _.omit(nextProps, 'modal')) } componentWillUnmount() { From 9cad0d446a3dc42fb31d6411541853b3f526e774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Fri, 11 Nov 2022 17:51:15 +0100 Subject: [PATCH 08/14] add missing semicolon --- src/components/ScreenWrapper/BaseScreenWrapper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ScreenWrapper/BaseScreenWrapper.js b/src/components/ScreenWrapper/BaseScreenWrapper.js index 93c98414def..83408e6a36f 100644 --- a/src/components/ScreenWrapper/BaseScreenWrapper.js +++ b/src/components/ScreenWrapper/BaseScreenWrapper.js @@ -52,7 +52,7 @@ class BaseScreenWrapper extends React.Component { */ shouldComponentUpdate(nextProps, nextState) { return !_.isEqual(this.state, nextState) - || !_.isEqual(_.omit(this.props, 'modal'), _.omit(nextProps, 'modal')) + || !_.isEqual(_.omit(this.props, 'modal'), _.omit(nextProps, 'modal')); } componentWillUnmount() { From 34354e0908c7ce805aa9fee1dc88dd8121681a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Fri, 11 Nov 2022 17:51:54 +0100 Subject: [PATCH 09/14] Update src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js Co-authored-by: Santhoshkumar Sellavel <85645967+Santhosh-Sellavel@users.noreply.github.com> --- src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js b/src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js index f40dd2b9baa..c3ba1b17073 100644 --- a/src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js +++ b/src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js @@ -138,7 +138,7 @@ class FABActionsPopover extends React.Component { onSelected: () => Navigation.navigate(ROUTES.IOU_BILL), }, ] : []), - ...(!Policy.isAdminOfFreePolicy(this.props.allPolicies) ? [ + ...(!Policy.hasActiveFreePolicy(this.props.allPolicies) ? [ { icon: Expensicons.NewWorkspace, iconWidth: 46, From 71c83ed634f2db131c4d09c03c7ccbe09f8f40d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Tue, 15 Nov 2022 16:08:13 +0100 Subject: [PATCH 10/14] fix use View instead of fragment --- src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js b/src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js index c3ba1b17073..1847f35f512 100644 --- a/src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js +++ b/src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js @@ -3,6 +3,7 @@ import _ from 'underscore'; import {withOnyx} from 'react-native-onyx'; import PropTypes from 'prop-types'; import lodashGet from 'lodash/get'; +import {View} from 'react-native'; import styles from '../../../../styles/styles'; import * as Expensicons from '../../../../components/Icon/Expensicons'; import Navigation from '../../../../libs/Navigation/Navigation'; @@ -92,7 +93,7 @@ class FABActionsPopover extends React.Component { const workspaces = _.filter(this.props.allPolicies, policy => policy && policy.type === CONST.POLICY.TYPE.FREE); return ( - <> + - + ); } } From 564fd4250dc487ff8f1d50978dd3516f1981fb76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Wed, 16 Nov 2022 22:23:48 +0100 Subject: [PATCH 11/14] rename to FloatingActionButtonAndPopover --- ...ctionsPopover.js => FloatingActionButtonAndPopover.js} | 8 ++++---- src/pages/home/sidebar/SidebarScreen/index.js | 4 ++-- src/pages/home/sidebar/SidebarScreen/index.native.js | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) rename src/pages/home/sidebar/SidebarScreen/{FABActionsPopover.js => FloatingActionButtonAndPopover.js} (97%) diff --git a/src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js similarity index 97% rename from src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js rename to src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js index 1847f35f512..f1e00704792 100644 --- a/src/pages/home/sidebar/SidebarScreen/FABActionsPopover.js +++ b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js @@ -49,7 +49,7 @@ const defaultProps = { * Responsible for rendering the {@link PopoverMenu}, and the accompanying * FAB that can open or close the menu. */ -class FABActionsPopover extends React.Component { +class FloatingActionButtonAndPopover extends React.Component { constructor(props) { super(props); @@ -162,8 +162,8 @@ class FABActionsPopover extends React.Component { } } -FABActionsPopover.propTypes = propTypes; -FABActionsPopover.defaultProps = defaultProps; +FloatingActionButtonAndPopover.propTypes = propTypes; +FloatingActionButtonAndPopover.defaultProps = defaultProps; export default compose( withLocalize, @@ -177,4 +177,4 @@ export default compose( key: ONYXKEYS.BETAS, }, }), -)(FABActionsPopover); +)(FloatingActionButtonAndPopover); diff --git a/src/pages/home/sidebar/SidebarScreen/index.js b/src/pages/home/sidebar/SidebarScreen/index.js index 0b4b132294d..a24122cec86 100755 --- a/src/pages/home/sidebar/SidebarScreen/index.js +++ b/src/pages/home/sidebar/SidebarScreen/index.js @@ -1,7 +1,7 @@ import React from 'react'; import sidebarPropTypes from './sidebarPropTypes'; import BaseSidebarScreen from './BaseSidebarScreen'; -import FABActionsPopover from './FABActionsPopover'; +import FloatingActionButtonAndPopover from './FloatingActionButtonAndPopover'; const SidebarScreen = (props) => { let popoverModal = null; @@ -25,7 +25,7 @@ const SidebarScreen = (props) => { // eslint-disable-next-line react/jsx-props-no-spreading {...props} > - popoverModal = el} onShowCreateMenu={createDragoverListener} onHideCreateMenu={removeDragoverListener} diff --git a/src/pages/home/sidebar/SidebarScreen/index.native.js b/src/pages/home/sidebar/SidebarScreen/index.native.js index cbada61b11c..145c841b1d2 100755 --- a/src/pages/home/sidebar/SidebarScreen/index.native.js +++ b/src/pages/home/sidebar/SidebarScreen/index.native.js @@ -1,14 +1,14 @@ import React from 'react'; import sidebarPropTypes from './sidebarPropTypes'; import BaseSidebarScreen from './BaseSidebarScreen'; -import FABActionsPopover from './FABActionsPopover'; +import FloatingActionButtonAndPopover from './FloatingActionButtonAndPopover'; const SidebarScreen = props => ( - + ); From ab2a4cba9c2ea5e6ed6c0c4ef7cea6f04433a440 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Wed, 16 Nov 2022 22:38:58 +0100 Subject: [PATCH 12/14] moved code from main/BaseSidebarScreen to own component --- .../FloatingActionButtonAndPopover.js | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js index f1e00704792..4c90f96b69c 100644 --- a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js +++ b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js @@ -19,6 +19,8 @@ import withWindowDimensions from '../../../../components/withWindowDimensions'; import ONYXKEYS from '../../../../ONYXKEYS'; import withNavigation from '../../../../components/withNavigation'; import * as Welcome from '../../../../libs/actions/Welcome'; +import withNavigationFocus from '../../../../components/withNavigationFocus'; +import withDrawerState from '../../../../components/withDrawerState'; const propTypes = { /* Callback function when the menu is shown */ @@ -66,10 +68,64 @@ class FloatingActionButtonAndPopover extends React.Component { Welcome.show({routes, showCreateMenu: this.showCreateMenu}); } + componentDidUpdate(prevProps) { + if (!this.didScreenBecomeInactive(prevProps)) { + return; + } + + // Hide menu manually when other pages are opened using shortcut key + this.hideCreateMenu(); + } + + /** + * Check if LHN status changed from active to inactive. + * Used to close already opened FAB menu when open any other pages (i.e. Press Command + K on web). + * + * @param {Object} prevProps + * @return {Boolean} + */ + didScreenBecomeInactive(prevProps) { + // When the Drawer gets closed and ReportScreen is shown + if (!this.props.isDrawerOpen && prevProps.isDrawerOpen) { + return true; + } + + // When any other page is opened over LHN + if (!this.props.isFocused && prevProps.isFocused) { + return true; + } + + return false; + } + + /** + * Check if LHN is inactive. + * Used to prevent FAB menu showing after opening any other pages. + * + * @return {Boolean} + */ + isScreenInactive() { + // When drawer is closed and Report page is open + if (this.props.isSmallScreenWidth && !this.props.isDrawerOpen) { + return true; + } + + // When any other page is open + if (!this.props.isFocused) { + return true; + } + + return false; + } + /** * Method called when we click the floating action button */ showCreateMenu() { + if (this.isScreenInactive()) { + // Prevent showing menu when click FAB icon quickly after opening other pages + return; + } this.setState({ isCreateMenuActive: true, }); @@ -82,6 +138,10 @@ class FloatingActionButtonAndPopover extends React.Component { * - Selecting an item on CreateMenu or closing it by clicking outside of the modal component */ hideCreateMenu() { + if (this.isScreenInactive()) { + // Prevent showing menu when click FAB icon quickly after opening other pages + return; + } this.props.onHideCreateMenu(); this.setState({ isCreateMenuActive: false, @@ -168,6 +228,8 @@ FloatingActionButtonAndPopover.defaultProps = defaultProps; export default compose( withLocalize, withNavigation, + withNavigationFocus, + withDrawerState, withWindowDimensions, withOnyx({ allPolicies: { From f25c19840d57b957bd36dd83313a9fe9dd60e5c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Wed, 16 Nov 2022 22:42:27 +0100 Subject: [PATCH 13/14] use selector --- .../SidebarScreen/FloatingActionButtonAndPopover.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js index 4c90f96b69c..465902df23d 100644 --- a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js +++ b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.js @@ -22,6 +22,15 @@ import * as Welcome from '../../../../libs/actions/Welcome'; import withNavigationFocus from '../../../../components/withNavigationFocus'; import withDrawerState from '../../../../components/withDrawerState'; +/** + * @param {Object} [policy] + * @returns {Object|undefined} + */ +const policySelector = policy => policy && ({ + type: policy.type, + role: policy.role, +}); + const propTypes = { /* Callback function when the menu is shown */ onShowCreateMenu: PropTypes.func, @@ -234,6 +243,7 @@ export default compose( withOnyx({ allPolicies: { key: ONYXKEYS.COLLECTION.POLICY, + selector: policySelector, }, betas: { key: ONYXKEYS.BETAS, From b654006297228816a924d1e0ebc13ee0da04a23e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Thu, 17 Nov 2022 19:54:10 +0100 Subject: [PATCH 14/14] fix crash --- src/pages/home/sidebar/SidebarScreen/index.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pages/home/sidebar/SidebarScreen/index.js b/src/pages/home/sidebar/SidebarScreen/index.js index a24122cec86..552b0e2dc18 100755 --- a/src/pages/home/sidebar/SidebarScreen/index.js +++ b/src/pages/home/sidebar/SidebarScreen/index.js @@ -1,23 +1,23 @@ -import React from 'react'; +import React, {useRef} from 'react'; import sidebarPropTypes from './sidebarPropTypes'; import BaseSidebarScreen from './BaseSidebarScreen'; import FloatingActionButtonAndPopover from './FloatingActionButtonAndPopover'; const SidebarScreen = (props) => { - let popoverModal = null; + const popoverModal = useRef(null); /** * Method create event listener */ const createDragoverListener = () => { - document.addEventListener('dragover', popoverModal.hideCreateMenu); + document.addEventListener('dragover', popoverModal.current.hideCreateMenu); }; /** * Method remove event listener. */ const removeDragoverListener = () => { - document.removeEventListener('dragover', popoverModal.hideCreateMenu); + document.removeEventListener('dragover', popoverModal.current.hideCreateMenu); }; return ( @@ -26,7 +26,7 @@ const SidebarScreen = (props) => { {...props} > popoverModal = el} + ref={popoverModal} onShowCreateMenu={createDragoverListener} onHideCreateMenu={removeDragoverListener} />