From aacb4a6fa453eeef480fdf409f85a06bea5971af Mon Sep 17 00:00:00 2001 From: Wojciech Lewicki Date: Mon, 11 Sep 2023 18:10:06 +0200 Subject: [PATCH 01/27] feat: first look at adding global nav menu --- src/pages/home/sidebar/GlobalNavigation.js | 52 ++++++++ .../home/sidebar/GlobalNavigationMenuItem.js | 119 ++++++++++++++++++ .../sidebar/GlobalNavigationMenuItemList.js | 60 +++++++++ src/pages/home/sidebar/SidebarLinksData.js | 6 +- src/styles/variables.ts | 3 +- 5 files changed, 237 insertions(+), 3 deletions(-) create mode 100644 src/pages/home/sidebar/GlobalNavigation.js create mode 100644 src/pages/home/sidebar/GlobalNavigationMenuItem.js create mode 100644 src/pages/home/sidebar/GlobalNavigationMenuItemList.js diff --git a/src/pages/home/sidebar/GlobalNavigation.js b/src/pages/home/sidebar/GlobalNavigation.js new file mode 100644 index 000000000000..c00ae62fa25e --- /dev/null +++ b/src/pages/home/sidebar/GlobalNavigation.js @@ -0,0 +1,52 @@ +import React from 'react'; +import {View} from 'react-native'; +import PropTypes from 'prop-types'; +import PressableAvatarWithIndicator from './PressableAvatarWithIndicator'; +import styles from '../../../styles/styles'; +import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; +import * as Expensicons from '../../../components/Icon/Expensicons'; +import GlobalNavigationMenuItemList from './GlobalNavigationMenuItemList'; +import Logo from '../../../../assets/images/new-expensify.svg'; +import variables from '../../../styles/variables'; + +const propTypes = { + isSmallScreenWidth: PropTypes.bool.isRequired, + isCreateMenuOpen: PropTypes.bool.isRequired, + ...withLocalizePropTypes, +}; + +function GlobalNavigation({isSmallScreenWidth, isCreateMenuOpen, translate}) { + if (isSmallScreenWidth) { + return null; + } + + return ( + + + + console.log('clicked'), + }, + { + icon: Expensicons.Receipt, + text: 'Expenses', + onSelected: () => console.log('clicked'), + }, + ]} + /> + + + ); +}; + +GlobalNavigation.propTypes = propTypes; +GlobalNavigation.displayName = 'GlobalNavigation'; + +export default withLocalize(GlobalNavigation); diff --git a/src/pages/home/sidebar/GlobalNavigationMenuItem.js b/src/pages/home/sidebar/GlobalNavigationMenuItem.js new file mode 100644 index 000000000000..6c30dbe87850 --- /dev/null +++ b/src/pages/home/sidebar/GlobalNavigationMenuItem.js @@ -0,0 +1,119 @@ +import _ from 'underscore'; +import React from 'react'; +import {View} from 'react-native'; +import Text from '../../../components/Text'; +import styles from '../../../styles/styles'; +import * as StyleUtils from '../../../styles/StyleUtils'; +import Icon from '../../../components/Icon'; +import getButtonState from '../../../libs/getButtonState'; +import CONST from '../../../CONST'; +import PressableWithSecondaryInteraction from '../../../components/PressableWithSecondaryInteraction'; +import * as DeviceCapabilities from '../../../libs/DeviceCapabilities'; +import ControlSelection from '../../../libs/ControlSelection'; +import Hoverable from '../../../components/Hoverable'; +import variables from '../../../styles/variables'; + +const propTypes = {}; + +const defaultProps = { + badgeText: undefined, + shouldShowRightIcon: false, + shouldShowSelectedState: false, + shouldShowBasicTitle: false, + shouldShowDescriptionOnTop: false, + shouldShowHeaderTitle: false, + wrapperStyle: [], + style: styles.popoverMenuItem, + titleStyle: {}, + shouldShowTitleIcon: false, + titleIcon: () => {}, + descriptionTextStyle: styles.breakWord, + success: false, + icon: undefined, + secondaryIcon: undefined, + iconWidth: undefined, + iconHeight: undefined, + description: undefined, + iconStyles: [], + iconFill: undefined, + secondaryIconFill: undefined, + focused: false, + disabled: false, + isSelected: false, + subtitle: undefined, + subtitleTextStyle: {}, + iconType: CONST.ICON_TYPE_ICON, + onPress: () => {}, + onSecondaryInteraction: undefined, + interactive: true, + brickRoadIndicator: '', + floatRightAvatars: [], + shouldStackHorizontally: false, + floatRightAvatarSize: undefined, + shouldBlockSelection: false, + hoverAndPressStyle: [], + furtherDetails: '', + furtherDetailsIcon: undefined, + isAnonymousAction: false, + isSmallAvatarSubscriptMenu: false, + title: '', + numberOfLinesTitle: 1, + shouldGreyOutWhenDisabled: true, +}; + +const GlobalNavigationMenuItem = React.forwardRef((props, ref) => ( + + {(isHovered) => ( + props.onPress(e)} + onPressIn={() => DeviceCapabilities.canUseTouchScreen() && ControlSelection.block()} + onPressOut={ControlSelection.unblock} + onSecondaryInteraction={props.onSecondaryInteraction} + style={({pressed}) => [ + props.style, + !props.interactive && styles.cursorDefault, + StyleUtils.getButtonBackgroundColorStyle(getButtonState(props.focused || isHovered, pressed), true), + (isHovered || pressed) && props.hoverAndPressStyle, + ]} + disabled={props.disabled} + ref={ref} + accessibilityRole={CONST.ACCESSIBILITY_ROLE.MENUITEM} + accessibilityLabel={props.title ? props.title.toString() : ''} + > + {({pressed}) => ( + <> + + + + + + + {props.title} + + + + + )} + + )} + + )); + +GlobalNavigationMenuItem.propTypes = propTypes; +GlobalNavigationMenuItem.defaultProps = defaultProps; +GlobalNavigationMenuItem.displayName = 'GlobalNavigationMenuItem'; + +export default GlobalNavigationMenuItem; diff --git a/src/pages/home/sidebar/GlobalNavigationMenuItemList.js b/src/pages/home/sidebar/GlobalNavigationMenuItemList.js new file mode 100644 index 000000000000..42f4facd98ce --- /dev/null +++ b/src/pages/home/sidebar/GlobalNavigationMenuItemList.js @@ -0,0 +1,60 @@ +import _ from 'underscore'; +import React, {useState} from 'react'; +import PropTypes from 'prop-types'; +import {View} from 'react-native'; +import useArrowKeyFocusManager from '../../../hooks/useArrowKeyFocusManager'; +import GlobalNavigationMenuItem from './GlobalNavigationMenuItem'; + +const propTypes = { + /** Menu items to be rendered on the list */ + menuItems: PropTypes.arrayOf( + PropTypes.shape({ + /** An icon element displayed on the left side */ + icon: PropTypes.elementType, + + /** Text label */ + text: PropTypes.string.isRequired, + + /** A callback triggered when this item is selected */ + onSelected: PropTypes.func.isRequired, + }), + ).isRequired, +}; + +const defaultProps = { +}; + +function GlobalNavigationMenuItemList(props) { + const [selectedItemIndex, setSelectedItemIndex] = useState(null); + const [focusedIndex, setFocusedIndex] = useArrowKeyFocusManager({initialFocusedIndex: -1, maxIndex: props.menuItems.length - 1, isActive: props.isVisible}); + + const selectItem = (index) => { + console.log('clicked he'); + const selectedItem = props.menuItems[index]; + props.onSelected(selectedItem, index); + setSelectedItemIndex(index); + }; + + return ( + + {_.map(props.menuItems, (item, menuIndex) => ( + selectItem(menuIndex)} + focused={focusedIndex === menuIndex} + /> + ))} + + ); +} + +GlobalNavigationMenuItemList.propTypes = propTypes; +GlobalNavigationMenuItemList.defaultProps = defaultProps; +GlobalNavigationMenuItemList.displayName = 'GlobalNavigationMenuItemList'; + +export default GlobalNavigationMenuItemList; diff --git a/src/pages/home/sidebar/SidebarLinksData.js b/src/pages/home/sidebar/SidebarLinksData.js index 243ba24cdd00..a2105cd8688f 100644 --- a/src/pages/home/sidebar/SidebarLinksData.js +++ b/src/pages/home/sidebar/SidebarLinksData.js @@ -16,6 +16,7 @@ import useLocalize from '../../../hooks/useLocalize'; import styles from '../../../styles/styles'; import withNavigationFocus from '../../../components/withNavigationFocus'; import * as SessionUtils from '../../../libs/SessionUtils'; +import GlobalNavigation from './GlobalNavigation'; const propTypes = { ...basePropTypes, @@ -63,7 +64,7 @@ const defaultProps = { policies: [], }; -function SidebarLinksData({isFocused, allReportActions, betas, chatReports, currentReportID, insets, isLoadingReportData, isSmallScreenWidth, onLinkClick, policies, priorityMode}) { +function SidebarLinksData({isFocused, allReportActions, betas, chatReports, currentReportID, insets, isLoadingReportData, isSmallScreenWidth, onLinkClick, policies, priorityMode, isCreateMenuOpen}) { const {translate} = useLocalize(); const reportIDsRef = useRef(null); @@ -101,8 +102,9 @@ function SidebarLinksData({isFocused, allReportActions, betas, chatReports, curr + Date: Tue, 12 Sep 2023 14:29:43 +0200 Subject: [PATCH 02/27] feat: remove unused onLayout and move globalNavigation higher --- src/pages/home/sidebar/GlobalNavigation.js | 2 +- src/pages/home/sidebar/GlobalNavigationMenuItemList.js | 5 +++-- src/pages/home/sidebar/SidebarLinksData.js | 4 +--- src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js | 5 +++-- src/pages/home/sidebar/SidebarScreen/sidebarPropTypes.js | 3 --- 5 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/pages/home/sidebar/GlobalNavigation.js b/src/pages/home/sidebar/GlobalNavigation.js index c00ae62fa25e..f83f5645ba49 100644 --- a/src/pages/home/sidebar/GlobalNavigation.js +++ b/src/pages/home/sidebar/GlobalNavigation.js @@ -11,7 +11,7 @@ import variables from '../../../styles/variables'; const propTypes = { isSmallScreenWidth: PropTypes.bool.isRequired, - isCreateMenuOpen: PropTypes.bool.isRequired, + isCreateMenuOpen: PropTypes.bool, ...withLocalizePropTypes, }; diff --git a/src/pages/home/sidebar/GlobalNavigationMenuItemList.js b/src/pages/home/sidebar/GlobalNavigationMenuItemList.js index 42f4facd98ce..63a22403b02f 100644 --- a/src/pages/home/sidebar/GlobalNavigationMenuItemList.js +++ b/src/pages/home/sidebar/GlobalNavigationMenuItemList.js @@ -28,8 +28,9 @@ function GlobalNavigationMenuItemList(props) { const [selectedItemIndex, setSelectedItemIndex] = useState(null); const [focusedIndex, setFocusedIndex] = useArrowKeyFocusManager({initialFocusedIndex: -1, maxIndex: props.menuItems.length - 1, isActive: props.isVisible}); - const selectItem = (index) => { + const selectItem = (index, onSelected) => { console.log('clicked he'); + onSelected(); const selectedItem = props.menuItems[index]; props.onSelected(selectedItem, index); setSelectedItemIndex(index); @@ -45,7 +46,7 @@ function GlobalNavigationMenuItemList(props) { iconHeight={item.iconHeight} title={item.text} description={item.description} - onPress={() => selectItem(menuIndex)} + onPress={() => selectItem(menuIndex, item.onSelected)} focused={focusedIndex === menuIndex} /> ))} diff --git a/src/pages/home/sidebar/SidebarLinksData.js b/src/pages/home/sidebar/SidebarLinksData.js index a2105cd8688f..bb549cd62667 100644 --- a/src/pages/home/sidebar/SidebarLinksData.js +++ b/src/pages/home/sidebar/SidebarLinksData.js @@ -16,7 +16,6 @@ import useLocalize from '../../../hooks/useLocalize'; import styles from '../../../styles/styles'; import withNavigationFocus from '../../../components/withNavigationFocus'; import * as SessionUtils from '../../../libs/SessionUtils'; -import GlobalNavigation from './GlobalNavigation'; const propTypes = { ...basePropTypes, @@ -64,7 +63,7 @@ const defaultProps = { policies: [], }; -function SidebarLinksData({isFocused, allReportActions, betas, chatReports, currentReportID, insets, isLoadingReportData, isSmallScreenWidth, onLinkClick, policies, priorityMode, isCreateMenuOpen}) { +function SidebarLinksData({isFocused, allReportActions, betas, chatReports, currentReportID, insets, isLoadingReportData, isSmallScreenWidth, onLinkClick, policies, priorityMode}) { const {translate} = useLocalize(); const reportIDsRef = useRef(null); @@ -104,7 +103,6 @@ function SidebarLinksData({isFocused, allReportActions, betas, chatReports, curr accessibilityLabel={translate('sidebarScreen.listOfChats')} style={[styles.flex1, styles.h100, styles.flexRow]} > - {({insets}) => ( <> - + + {props.children} diff --git a/src/pages/home/sidebar/SidebarScreen/sidebarPropTypes.js b/src/pages/home/sidebar/SidebarScreen/sidebarPropTypes.js index 5269765dc753..aac797b08876 100644 --- a/src/pages/home/sidebar/SidebarScreen/sidebarPropTypes.js +++ b/src/pages/home/sidebar/SidebarScreen/sidebarPropTypes.js @@ -1,9 +1,6 @@ -import PropTypes from 'prop-types'; import {windowDimensionsPropTypes} from '../../../../components/withWindowDimensions'; const sidebarPropTypes = { - /** Callback when onLayout of sidebar is called */ - onLayout: PropTypes.func, ...windowDimensionsPropTypes, }; export default sidebarPropTypes; From 5bc0dec94eb62d73d2de0ec185ae5f4f86c44544 Mon Sep 17 00:00:00 2001 From: Wojciech Lewicki Date: Tue, 12 Sep 2023 15:35:34 +0200 Subject: [PATCH 03/27] feat: prepare app for different menus --- src/CONST.ts | 8 + src/pages/home/sidebar/GlobalNavigation.js | 28 ++- .../home/sidebar/GlobalNavigationMenuItem.js | 163 +++++++++--------- .../sidebar/GlobalNavigationMenuItemList.js | 34 ++-- src/pages/home/sidebar/SidebarLinksData.js | 2 +- .../SidebarScreen/BaseSidebarScreen.js | 50 +++--- .../home/sidebar/SidebarScreen/SidebarMenu.js | 59 +++++++ 7 files changed, 204 insertions(+), 140 deletions(-) create mode 100644 src/pages/home/sidebar/SidebarScreen/SidebarMenu.js diff --git a/src/CONST.ts b/src/CONST.ts index c6ae9cc5928d..7870c777fad3 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -2652,19 +2652,27 @@ const CONST = { DEFAULT_COORDINATE: [-122.4021, 37.7911], STYLE_URL: 'mapbox://styles/expensify/cllcoiqds00cs01r80kp34tmq', }, + ONYX_UPDATE_TYPES: { HTTPS: 'https', PUSHER: 'pusher', }, + EVENTS: { SCROLLING: 'scrolling', }, + HORIZONTAL_SPACER: { DEFAULT_BORDER_BOTTOM_WIDTH: 1, DEFAULT_MARGIN_VERTICAL: 8, HIDDEN_MARGIN_VERTICAL: 0, HIDDEN_BORDER_BOTTOM_WIDTH: 0, }, + + SIDEBAR_MENU_OPTIONS: { + CHATS: 'chats', + EXPENSES: 'expenses', + }, } as const; export default CONST; diff --git a/src/pages/home/sidebar/GlobalNavigation.js b/src/pages/home/sidebar/GlobalNavigation.js index f83f5645ba49..fcb08ba57721 100644 --- a/src/pages/home/sidebar/GlobalNavigation.js +++ b/src/pages/home/sidebar/GlobalNavigation.js @@ -8,20 +8,35 @@ import * as Expensicons from '../../../components/Icon/Expensicons'; import GlobalNavigationMenuItemList from './GlobalNavigationMenuItemList'; import Logo from '../../../../assets/images/new-expensify.svg'; import variables from '../../../styles/variables'; +import CONST from '../../../CONST'; const propTypes = { isSmallScreenWidth: PropTypes.bool.isRequired, isCreateMenuOpen: PropTypes.bool, + switchSidebarMenu: PropTypes.func.isRequired, ...withLocalizePropTypes, }; -function GlobalNavigation({isSmallScreenWidth, isCreateMenuOpen, translate}) { - if (isSmallScreenWidth) { +const defaultProps = { + isCreateMenuOpen: false, +}; + +function GlobalNavigation({isSmallScreenWidth, isCreateMenuOpen, switchSidebarMenu}) { + if (isSmallScreenWidth) { return null; } return ( - + console.log('clicked'), + onSelected: () => switchSidebarMenu(CONST.SIDEBAR_MENU_OPTIONS.CHATS), }, { icon: Expensicons.Receipt, text: 'Expenses', - onSelected: () => console.log('clicked'), + onSelected: () => switchSidebarMenu(CONST.SIDEBAR_MENU_OPTIONS.EXPENSES), }, ]} /> @@ -44,9 +59,10 @@ function GlobalNavigation({isSmallScreenWidth, isCreateMenuOpen, translate}) { /> ); -}; +} GlobalNavigation.propTypes = propTypes; +GlobalNavigation.defaultProps = defaultProps; GlobalNavigation.displayName = 'GlobalNavigation'; export default withLocalize(GlobalNavigation); diff --git a/src/pages/home/sidebar/GlobalNavigationMenuItem.js b/src/pages/home/sidebar/GlobalNavigationMenuItem.js index 6c30dbe87850..090472160d92 100644 --- a/src/pages/home/sidebar/GlobalNavigationMenuItem.js +++ b/src/pages/home/sidebar/GlobalNavigationMenuItem.js @@ -1,6 +1,6 @@ -import _ from 'underscore'; import React from 'react'; import {View} from 'react-native'; +import PropTypes from 'prop-types'; import Text from '../../../components/Text'; import styles from '../../../styles/styles'; import * as StyleUtils from '../../../styles/StyleUtils'; @@ -8,109 +8,104 @@ import Icon from '../../../components/Icon'; import getButtonState from '../../../libs/getButtonState'; import CONST from '../../../CONST'; import PressableWithSecondaryInteraction from '../../../components/PressableWithSecondaryInteraction'; -import * as DeviceCapabilities from '../../../libs/DeviceCapabilities'; -import ControlSelection from '../../../libs/ControlSelection'; import Hoverable from '../../../components/Hoverable'; import variables from '../../../styles/variables'; +import stylePropTypes from '../../../styles/stylePropTypes'; -const propTypes = {}; +const propTypes = { + /** Used to apply offline styles to child text components */ + style: stylePropTypes, + + /** Function to fire when component is pressed */ + onPress: PropTypes.func, + + /** Icon to display */ + icon: PropTypes.elementType, + + /** Icon Width */ + iconWidth: PropTypes.number, + + /** Icon Height */ + iconHeight: PropTypes.number, + + /** Text to display for the item */ + title: PropTypes.string, + + /** Any additional styles to pass to the icon container. */ + iconStyles: stylePropTypes, + + /** The fill color to pass into the icon. */ + iconFill: PropTypes.string, + + /** Whether item is focused or active */ + focused: PropTypes.bool, + + /** Whether the menu item should be interactive at all */ + interactive: PropTypes.bool, + + /** Any adjustments to style when menu item is hovered or pressed */ + hoverAndPressStyle: stylePropTypes, + + /** Prop to represent the size of the avatar images to be shown */ + avatarSize: PropTypes.oneOf(_.values(CONST.AVATAR_SIZE)), +}; const defaultProps = { - badgeText: undefined, - shouldShowRightIcon: false, - shouldShowSelectedState: false, - shouldShowBasicTitle: false, - shouldShowDescriptionOnTop: false, - shouldShowHeaderTitle: false, - wrapperStyle: [], style: styles.popoverMenuItem, - titleStyle: {}, - shouldShowTitleIcon: false, - titleIcon: () => {}, - descriptionTextStyle: styles.breakWord, - success: false, icon: undefined, - secondaryIcon: undefined, iconWidth: undefined, iconHeight: undefined, - description: undefined, iconStyles: [], iconFill: undefined, - secondaryIconFill: undefined, focused: false, - disabled: false, - isSelected: false, - subtitle: undefined, - subtitleTextStyle: {}, - iconType: CONST.ICON_TYPE_ICON, onPress: () => {}, - onSecondaryInteraction: undefined, interactive: true, - brickRoadIndicator: '', - floatRightAvatars: [], - shouldStackHorizontally: false, - floatRightAvatarSize: undefined, - shouldBlockSelection: false, hoverAndPressStyle: [], - furtherDetails: '', - furtherDetailsIcon: undefined, - isAnonymousAction: false, - isSmallAvatarSubscriptMenu: false, title: '', - numberOfLinesTitle: 1, - shouldGreyOutWhenDisabled: true, + avatarSize: CONST.AVATAR_SIZE.DEFAULT, }; const GlobalNavigationMenuItem = React.forwardRef((props, ref) => ( - - {(isHovered) => ( - props.onPress(e)} - onPressIn={() => DeviceCapabilities.canUseTouchScreen() && ControlSelection.block()} - onPressOut={ControlSelection.unblock} - onSecondaryInteraction={props.onSecondaryInteraction} - style={({pressed}) => [ - props.style, - !props.interactive && styles.cursorDefault, - StyleUtils.getButtonBackgroundColorStyle(getButtonState(props.focused || isHovered, pressed), true), - (isHovered || pressed) && props.hoverAndPressStyle, - ]} - disabled={props.disabled} - ref={ref} - accessibilityRole={CONST.ACCESSIBILITY_ROLE.MENUITEM} - accessibilityLabel={props.title ? props.title.toString() : ''} - > - {({pressed}) => ( - <> - - - - - - - {props.title} - - + + {(isHovered) => ( + [ + props.style, + !props.interactive && styles.cursorDefault, + StyleUtils.getButtonBackgroundColorStyle(getButtonState(props.focused || isHovered, pressed), true), + (isHovered || pressed) && props.hoverAndPressStyle, + ]} + ref={ref} + accessibilityRole={CONST.ACCESSIBILITY_ROLE.MENUITEM} + accessibilityLabel={props.title ? props.title.toString() : ''} + > + {({pressed}) => ( + <> + + + + + + {props.title} - - )} - - )} - - )); + + + )} + + )} + +)); GlobalNavigationMenuItem.propTypes = propTypes; GlobalNavigationMenuItem.defaultProps = defaultProps; diff --git a/src/pages/home/sidebar/GlobalNavigationMenuItemList.js b/src/pages/home/sidebar/GlobalNavigationMenuItemList.js index 63a22403b02f..8e391c7e0883 100644 --- a/src/pages/home/sidebar/GlobalNavigationMenuItemList.js +++ b/src/pages/home/sidebar/GlobalNavigationMenuItemList.js @@ -21,36 +21,32 @@ const propTypes = { ).isRequired, }; -const defaultProps = { -}; +const defaultProps = {}; function GlobalNavigationMenuItemList(props) { const [selectedItemIndex, setSelectedItemIndex] = useState(null); const [focusedIndex, setFocusedIndex] = useArrowKeyFocusManager({initialFocusedIndex: -1, maxIndex: props.menuItems.length - 1, isActive: props.isVisible}); const selectItem = (index, onSelected) => { - console.log('clicked he'); onSelected(); - const selectedItem = props.menuItems[index]; - props.onSelected(selectedItem, index); setSelectedItemIndex(index); }; return ( - - {_.map(props.menuItems, (item, menuIndex) => ( - selectItem(menuIndex, item.onSelected)} - focused={focusedIndex === menuIndex} - /> - ))} - + + {_.map(props.menuItems, (item, menuIndex) => ( + selectItem(menuIndex, item.onSelected)} + focused={focusedIndex === menuIndex} + /> + ))} + ); } diff --git a/src/pages/home/sidebar/SidebarLinksData.js b/src/pages/home/sidebar/SidebarLinksData.js index bb549cd62667..243ba24cdd00 100644 --- a/src/pages/home/sidebar/SidebarLinksData.js +++ b/src/pages/home/sidebar/SidebarLinksData.js @@ -101,7 +101,7 @@ function SidebarLinksData({isFocused, allReportActions, betas, chatReports, curr { - Timing.start(CONST.TIMING.SWITCH_REPORT); - Performance.markStart(CONST.TIMING.SWITCH_REPORT); -}; - function BaseSidebarScreen(props) { - useEffect(() => { - Performance.markStart(CONST.TIMING.SIDEBAR_LOADED); - Timing.start(CONST.TIMING.SIDEBAR_LOADED, true); - }, []); + const [shownSidebarMenu, setShownSidebarMenu] = React.useState(CONST.SIDEBAR_MENU_OPTIONS.CHATS); + + const switchSidebarMenu = (sidebarOption) => { + setShownSidebarMenu(sidebarOption); + }; return ( - {({insets}) => ( - <> - - - - - {props.children} - - )} + + + + + {props.children} ); } diff --git a/src/pages/home/sidebar/SidebarScreen/SidebarMenu.js b/src/pages/home/sidebar/SidebarScreen/SidebarMenu.js new file mode 100644 index 000000000000..c45945039ca9 --- /dev/null +++ b/src/pages/home/sidebar/SidebarScreen/SidebarMenu.js @@ -0,0 +1,59 @@ +import React, {useEffect} from 'react'; +import {View} from 'react-native'; +import PropTypes from 'prop-types'; +import styles from '../../../../styles/styles'; +import SidebarLinksData from '../SidebarLinksData'; +import ScreenWrapper from '../../../../components/ScreenWrapper'; +import Timing from '../../../../libs/actions/Timing'; +import CONST from '../../../../CONST'; +import Performance from '../../../../libs/Performance'; +import * as Browser from '../../../../libs/Browser'; + +const propTypes = { + isSmallScreenWidth: PropTypes.bool.isRequired, + shownSidebarMenu: PropTypes.string.isRequired, +}; + +/** + * Function called when a pinned chat is selected. + */ +const startTimer = () => { + Timing.start(CONST.TIMING.SWITCH_REPORT); + Performance.markStart(CONST.TIMING.SWITCH_REPORT); +}; + +function SidebarMenu(props) { + useEffect(() => { + Performance.markStart(CONST.TIMING.SIDEBAR_LOADED); + Timing.start(CONST.TIMING.SIDEBAR_LOADED, true); + }, []); + + return ( + + {({insets}) => { + if (props.shownSidebarMenu === CONST.SIDEBAR_MENU_OPTIONS.CHATS) { + return ( + + ); + } + if (props.shownSidebarMenu === CONST.SIDEBAR_MENU_OPTIONS.EXPENSES) { + // TODO: Add all other sidebar menus + return null; + } + }} + + ); +} + +SidebarMenu.propTypes = propTypes; +SidebarMenu.displayName = 'SidebarMenu'; + +export default SidebarMenu; From b1af947e84f3ad74ef3d08fb318774e2501e863a Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Tue, 26 Sep 2023 18:25:20 +0200 Subject: [PATCH 04/27] add first global navigation option --- src/App.js | 2 + src/CONST.ts | 6 +- src/GLOBAL_NAVIGATION_MAPPING.ts | 9 +++ src/ROUTES.ts | 13 ++++ src/SCREENS.ts | 13 ++++ src/libs/Navigation/Navigation.js | 5 ++ src/libs/Navigation/NavigationRoot.js | 7 +- .../getTopMostCentralPaneRouteName.js | 32 +++++++++ src/libs/Navigation/linkTo.js | 7 +- src/pages/home/sidebar/GlobalNavigation.js | 68 ------------------- .../GlobalNavigation/GlobalNavigation.js | 50 ++++++++++++++ .../GlobalNavigationMenuItem.js | 28 ++++---- .../GlobalNavigationMenuItemList.js | 21 +++--- src/pages/home/sidebar/SidebarLinks.js | 4 +- .../home/sidebar/SidebarNavigationContext.js | 59 ++++++++++++++++ .../SidebarScreen/BaseSidebarScreen.js | 17 +---- .../SubNavigation.js} | 33 ++++----- 17 files changed, 236 insertions(+), 138 deletions(-) create mode 100644 src/GLOBAL_NAVIGATION_MAPPING.ts create mode 100644 src/libs/Navigation/getTopMostCentralPaneRouteName.js delete mode 100644 src/pages/home/sidebar/GlobalNavigation.js create mode 100644 src/pages/home/sidebar/GlobalNavigation/GlobalNavigation.js rename src/pages/home/sidebar/{ => GlobalNavigation}/GlobalNavigationMenuItem.js (79%) rename src/pages/home/sidebar/{ => GlobalNavigation}/GlobalNavigationMenuItemList.js (63%) create mode 100644 src/pages/home/sidebar/SidebarNavigationContext.js rename src/pages/home/sidebar/{SidebarScreen/SidebarMenu.js => SubNavigation/SubNavigation.js} (57%) diff --git a/src/App.js b/src/App.js index 284c6115d7b8..14a33dd617c1 100644 --- a/src/App.js +++ b/src/App.js @@ -26,6 +26,7 @@ import {ReportAttachmentsProvider} from './pages/home/report/ReportAttachmentsCo import * as Session from './libs/actions/Session'; import useDefaultDragAndDrop from './hooks/useDefaultDragAndDrop'; import OnyxUpdateManager from './libs/actions/OnyxUpdateManager'; +import {SidebarNavigationContextProvider} from './pages/home/sidebar/SidebarNavigationContext'; // For easier debugging and development, when we are in web we expose Onyx to the window, so you can more easily set data into Onyx if (window && Environment.isDevelopment()) { @@ -64,6 +65,7 @@ function App() { EnvironmentProvider, ThemeProvider, ThemeStylesProvider, + SidebarNavigationContextProvider, ]} > diff --git a/src/CONST.ts b/src/CONST.ts index 7870c777fad3..64a072938a4a 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -2669,9 +2669,11 @@ const CONST = { HIDDEN_BORDER_BOTTOM_WIDTH: 0, }, - SIDEBAR_MENU_OPTIONS: { + GLOBAL_NAVIGATION_OPTION: { + HOME: 'home', CHATS: 'chats', - EXPENSES: 'expenses', + SPEND: 'spend', + WORKSPACES: 'workspaces', }, } as const; diff --git a/src/GLOBAL_NAVIGATION_MAPPING.ts b/src/GLOBAL_NAVIGATION_MAPPING.ts new file mode 100644 index 000000000000..77d79b67b995 --- /dev/null +++ b/src/GLOBAL_NAVIGATION_MAPPING.ts @@ -0,0 +1,9 @@ +import CONST from './CONST'; +import SCREENS from './SCREENS'; + +export default { + [CONST.GLOBAL_NAVIGATION_OPTION.HOME]: [SCREENS.HOME_OD], + [CONST.GLOBAL_NAVIGATION_OPTION.CHATS]: [SCREENS.REPORT], + [CONST.GLOBAL_NAVIGATION_OPTION.SPEND]: [SCREENS.EXPENSES_OD, SCREENS.REPORTS_OD, SCREENS.INSIGHTS_OD], + [CONST.GLOBAL_NAVIGATION_OPTION.WORKSPACES]: [SCREENS.INDIVIDUALS_OD, SCREENS.GROUPS_OD, SCREENS.CARDS_AND_DOMAINS_OD], +} as const; diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 1065b525f83a..02cd00a63939 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -152,4 +152,17 @@ export default { // These are some on-off routes that will be removed once they're no longer needed (see GH issues for details) SAASTR: 'saastr', SBE: 'sbe', + + // Iframe screens from olddot + HOME_OD: 'home', + + // Spend tab + EXPENSES_OD: 'expenses', + REPORTS_OD: 'reports', + INSIGHTS_OD: 'insights', + + // Workspaces tab + INDIVIDUALS_OD: 'individuals', + GROUPS_OD: 'groups', + CARDS_AND_DOMAINS_OD: 'cards-and-domains', } as const; diff --git a/src/SCREENS.ts b/src/SCREENS.ts index eb125a43c239..de32edd1469c 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -24,4 +24,17 @@ export default { SIGN_IN_WITH_APPLE_DESKTOP: 'AppleSignInDesktop', SIGN_IN_WITH_GOOGLE_DESKTOP: 'GoogleSignInDesktop', DESKTOP_SIGN_IN_REDIRECT: 'DesktopSignInRedirect', + + // Iframe screens from olddot + HOME_OD: 'Home_OD', + + // Spend tab + EXPENSES_OD: 'Expenses_OD', + REPORTS_OD: 'Reports_OD', + INSIGHTS_OD: 'INSIGHTS_OD', + + // Workspaces tab + INDIVIDUALS_OD: 'Individuals_OD', + GROUPS_OD: 'Groups_OD', + CARDS_AND_DOMAINS_OD: 'CardsAndDomains_OD', } as const; diff --git a/src/libs/Navigation/Navigation.js b/src/libs/Navigation/Navigation.js index dc4f35a59cba..44a534d1a548 100644 --- a/src/libs/Navigation/Navigation.js +++ b/src/libs/Navigation/Navigation.js @@ -10,6 +10,7 @@ import linkingConfig from './linkingConfig'; import navigationRef from './navigationRef'; import NAVIGATORS from '../../NAVIGATORS'; import originalGetTopmostReportId from './getTopmostReportId'; +import originalGetTopMostCentralPaneRouteName from './getTopMostCentralPaneRouteName'; import getStateFromPath from './getStateFromPath'; import SCREENS from '../../SCREENS'; import CONST from '../../CONST'; @@ -46,6 +47,9 @@ function canNavigate(methodName, params = {}) { // Re-exporting the getTopmostReportId here to fill in default value for state. The getTopmostReportId isn't defined in this file to avoid cyclic dependencies. const getTopmostReportId = (state = navigationRef.getState()) => originalGetTopmostReportId(state); +// Re-exporting the getTopMostCentralPaneRouteName here to fill in default value for state. The getTopMostCentralPaneRouteName isn't defined in this file to avoid cyclic dependencies. +const getTopMostCentralPaneRouteName = (state = navigationRef.getState()) => originalGetTopMostCentralPaneRouteName(state); + /** * Method for finding on which index in stack we are. * @param {Object} route @@ -268,6 +272,7 @@ export default { setIsNavigationReady, getTopmostReportId, getRouteNameFromStateEvent, + getTopMostCentralPaneRouteName, }; export {navigationRef}; diff --git a/src/libs/Navigation/NavigationRoot.js b/src/libs/Navigation/NavigationRoot.js index 4d50a1cd6a68..615aadcef691 100644 --- a/src/libs/Navigation/NavigationRoot.js +++ b/src/libs/Navigation/NavigationRoot.js @@ -1,4 +1,4 @@ -import React, {useRef, useEffect} from 'react'; +import React, {useRef, useEffect, useContext} from 'react'; import PropTypes from 'prop-types'; import {NavigationContainer, DefaultTheme, getPathFromState} from '@react-navigation/native'; import {useFlipper} from '@react-navigation/devtools'; @@ -11,6 +11,7 @@ import Log from '../Log'; import StatusBar from '../StatusBar'; import useCurrentReportID from '../../hooks/useCurrentReportID'; import useWindowDimensions from '../../hooks/useWindowDimensions'; +import {SidebarNavigationContext} from '../../pages/home/sidebar/SidebarNavigationContext'; // https://reactnavigation.org/docs/themes const navigationTheme = { @@ -53,6 +54,7 @@ function parseAndLogRoute(state) { function NavigationRoot(props) { useFlipper(navigationRef); const firstRenderRef = useRef(true); + const globalNavigation = useContext(SidebarNavigationContext); const {updateCurrentReportID} = useCurrentReportID(); const {isSmallScreenWidth} = useWindowDimensions(); @@ -125,6 +127,9 @@ function NavigationRoot(props) { updateCurrentReportID(state); parseAndLogRoute(state); animateStatusBarBackgroundColor(); + + // Update the global navigation to show the correct selected menu items. + globalNavigation.updateFromNavigationState(state); }; return ( diff --git a/src/libs/Navigation/getTopMostCentralPaneRouteName.js b/src/libs/Navigation/getTopMostCentralPaneRouteName.js new file mode 100644 index 000000000000..31d646baa2bd --- /dev/null +++ b/src/libs/Navigation/getTopMostCentralPaneRouteName.js @@ -0,0 +1,32 @@ +import lodashFindLast from 'lodash/findLast'; + +/** + * Find the name of top most central pane route. + * + * @param {Object} state - The react-navigation state + * @returns {String | undefined} - It's possible that there is no central pane in the state. + */ +function getTopMostCentralPaneRouteName(state) { + if (!state) { + return; + } + const topmostCentralPane = lodashFindLast(state.routes, (route) => route.name === 'CentralPaneNavigator'); + + if (!topmostCentralPane) { + return; + } + + if (topmostCentralPane.state && topmostCentralPane.state.routes) { + // State may don't have index in some cases. But in this case there will be only one route in state. + return topmostCentralPane.state.routes[topmostCentralPane.state.index || 0].name; + } + + if (topmostCentralPane.params) { + // State may don't have inner state in some cases (e.g generating actions from path). But in this case there will be params available. + return topmostCentralPane.screen; + } + + return undefined; +} + +export default getTopMostCentralPaneRouteName; diff --git a/src/libs/Navigation/linkTo.js b/src/libs/Navigation/linkTo.js index 884a8aa02190..23dbf322fd78 100644 --- a/src/libs/Navigation/linkTo.js +++ b/src/libs/Navigation/linkTo.js @@ -5,6 +5,7 @@ import linkingConfig from './linkingConfig'; import getTopmostReportId from './getTopmostReportId'; import getStateFromPath from './getStateFromPath'; import CONST from '../../CONST'; +import getTopMostCentralPaneRouteName from './getTopMostCentralPaneRouteName'; /** * Motivation for this function is described in NAVIGATION.md @@ -66,7 +67,11 @@ export default function linkTo(navigation, path, type) { action.type = CONST.NAVIGATION.ACTION_TYPE.REPLACE; // If this action is navigating to the report screen and the top most navigator is different from the one we want to navigate - PUSH the new screen to the top of the stack - } else if (action.payload.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR && getTopmostReportId(root.getState()) !== getTopmostReportId(state)) { + } else if ( + action.payload.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR && + (getTopmostReportId(root.getState()) !== getTopmostReportId(state) || getTopMostCentralPaneRouteName(root.getState()) !== getTopMostCentralPaneRouteName(state)) + // getTopmostReportId(root.getState()) !== getTopmostReportId(state) + ) { action.type = CONST.NAVIGATION.ACTION_TYPE.PUSH; // If the type is UP, we deeplinked into one of the RHP flows and we want to replace the current screen with the previous one in the flow diff --git a/src/pages/home/sidebar/GlobalNavigation.js b/src/pages/home/sidebar/GlobalNavigation.js deleted file mode 100644 index fcb08ba57721..000000000000 --- a/src/pages/home/sidebar/GlobalNavigation.js +++ /dev/null @@ -1,68 +0,0 @@ -import React from 'react'; -import {View} from 'react-native'; -import PropTypes from 'prop-types'; -import PressableAvatarWithIndicator from './PressableAvatarWithIndicator'; -import styles from '../../../styles/styles'; -import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; -import * as Expensicons from '../../../components/Icon/Expensicons'; -import GlobalNavigationMenuItemList from './GlobalNavigationMenuItemList'; -import Logo from '../../../../assets/images/new-expensify.svg'; -import variables from '../../../styles/variables'; -import CONST from '../../../CONST'; - -const propTypes = { - isSmallScreenWidth: PropTypes.bool.isRequired, - isCreateMenuOpen: PropTypes.bool, - switchSidebarMenu: PropTypes.func.isRequired, - ...withLocalizePropTypes, -}; - -const defaultProps = { - isCreateMenuOpen: false, -}; - -function GlobalNavigation({isSmallScreenWidth, isCreateMenuOpen, switchSidebarMenu}) { - if (isSmallScreenWidth) { - return null; - } - - return ( - - - - switchSidebarMenu(CONST.SIDEBAR_MENU_OPTIONS.CHATS), - }, - { - icon: Expensicons.Receipt, - text: 'Expenses', - onSelected: () => switchSidebarMenu(CONST.SIDEBAR_MENU_OPTIONS.EXPENSES), - }, - ]} - /> - - - ); -} - -GlobalNavigation.propTypes = propTypes; -GlobalNavigation.defaultProps = defaultProps; -GlobalNavigation.displayName = 'GlobalNavigation'; - -export default withLocalize(GlobalNavigation); diff --git a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigation.js b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigation.js new file mode 100644 index 000000000000..c20e7d7b3f34 --- /dev/null +++ b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigation.js @@ -0,0 +1,50 @@ +import React, {useMemo} from 'react'; +import {View} from 'react-native'; +import PropTypes from 'prop-types'; +import PressableAvatarWithIndicator from '../PressableAvatarWithIndicator'; +import styles from '../../../../styles/styles'; +import withLocalize, {withLocalizePropTypes} from '../../../../components/withLocalize'; +import * as Expensicons from '../../../../components/Icon/Expensicons'; +import GlobalNavigationMenuItemList from './GlobalNavigationMenuItemList'; +import variables from '../../../../styles/variables'; +import CONST from '../../../../CONST'; +import Navigation from '../../../../libs/Navigation/Navigation'; +import ROUTES from '../../../../ROUTES'; + +const propTypes = { + isCreateMenuOpen: PropTypes.bool, + ...withLocalizePropTypes, +}; + +const defaultProps = { + isCreateMenuOpen: false, +}; + +function GlobalNavigation({isCreateMenuOpen}) { + const items = useMemo( + () => [ + { + icon: Expensicons.ChatBubble, + text: 'Chats', + value: CONST.GLOBAL_NAVIGATION_OPTION.CHATS, + onSelected: () => { + Navigation.navigate(ROUTES.REPORT); + }, + }, + ], + [], + ); + + return ( + + + + + ); +} + +GlobalNavigation.propTypes = propTypes; +GlobalNavigation.defaultProps = defaultProps; +GlobalNavigation.displayName = 'GlobalNavigation'; + +export default withLocalize(GlobalNavigation); diff --git a/src/pages/home/sidebar/GlobalNavigationMenuItem.js b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js similarity index 79% rename from src/pages/home/sidebar/GlobalNavigationMenuItem.js rename to src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js index 090472160d92..addfa5b871d2 100644 --- a/src/pages/home/sidebar/GlobalNavigationMenuItem.js +++ b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js @@ -1,16 +1,17 @@ import React from 'react'; import {View} from 'react-native'; import PropTypes from 'prop-types'; -import Text from '../../../components/Text'; -import styles from '../../../styles/styles'; -import * as StyleUtils from '../../../styles/StyleUtils'; -import Icon from '../../../components/Icon'; -import getButtonState from '../../../libs/getButtonState'; -import CONST from '../../../CONST'; -import PressableWithSecondaryInteraction from '../../../components/PressableWithSecondaryInteraction'; -import Hoverable from '../../../components/Hoverable'; -import variables from '../../../styles/variables'; -import stylePropTypes from '../../../styles/stylePropTypes'; +import _ from 'underscore'; +import Text from '../../../../components/Text'; +import styles from '../../../../styles/styles'; +import * as StyleUtils from '../../../../styles/StyleUtils'; +import Icon from '../../../../components/Icon'; +import getButtonState from '../../../../libs/getButtonState'; +import CONST from '../../../../CONST'; +import PressableWithSecondaryInteraction from '../../../../components/PressableWithSecondaryInteraction'; +import Hoverable from '../../../../components/Hoverable'; +import variables from '../../../../styles/variables'; +import stylePropTypes from '../../../../styles/stylePropTypes'; const propTypes = { /** Used to apply offline styles to child text components */ @@ -69,7 +70,7 @@ const GlobalNavigationMenuItem = React.forwardRef((props, ref) => ( {(isHovered) => ( {} : props.onPress} style={({pressed}) => [ props.style, !props.interactive && styles.cursorDefault, @@ -90,10 +91,7 @@ const GlobalNavigationMenuItem = React.forwardRef((props, ref) => ( src={props.icon} width={props.iconWidth} height={props.iconHeight} - fill={ - props.iconFill || - StyleUtils.getIconFillColor(getButtonState(props.focused || isHovered, pressed), true) - } + fill={props.iconFill || StyleUtils.getIconFillColor(getButtonState(props.focused || isHovered, pressed), true)} /> diff --git a/src/pages/home/sidebar/GlobalNavigationMenuItemList.js b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItemList.js similarity index 63% rename from src/pages/home/sidebar/GlobalNavigationMenuItemList.js rename to src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItemList.js index 8e391c7e0883..b03e11c83619 100644 --- a/src/pages/home/sidebar/GlobalNavigationMenuItemList.js +++ b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItemList.js @@ -1,9 +1,9 @@ import _ from 'underscore'; -import React, {useState} from 'react'; +import React, {useContext} from 'react'; import PropTypes from 'prop-types'; import {View} from 'react-native'; -import useArrowKeyFocusManager from '../../../hooks/useArrowKeyFocusManager'; import GlobalNavigationMenuItem from './GlobalNavigationMenuItem'; +import {SidebarNavigationContext} from '../SidebarNavigationContext'; const propTypes = { /** Menu items to be rendered on the list */ @@ -21,20 +21,16 @@ const propTypes = { ).isRequired, }; -const defaultProps = {}; - function GlobalNavigationMenuItemList(props) { - const [selectedItemIndex, setSelectedItemIndex] = useState(null); - const [focusedIndex, setFocusedIndex] = useArrowKeyFocusManager({initialFocusedIndex: -1, maxIndex: props.menuItems.length - 1, isActive: props.isVisible}); + const sidebarNavigation = useContext(SidebarNavigationContext); - const selectItem = (index, onSelected) => { - onSelected(); - setSelectedItemIndex(index); + const selectItem = (value, onSelected) => { + onSelected(value); }; return ( - {_.map(props.menuItems, (item, menuIndex) => ( + {_.map(props.menuItems, (item) => ( selectItem(menuIndex, item.onSelected)} - focused={focusedIndex === menuIndex} + onPress={() => selectItem(item.value, item.onSelected)} + focused={sidebarNavigation.selectedGlobalNavigationOption === item.value} /> ))} @@ -51,7 +47,6 @@ function GlobalNavigationMenuItemList(props) { } GlobalNavigationMenuItemList.propTypes = propTypes; -GlobalNavigationMenuItemList.defaultProps = defaultProps; GlobalNavigationMenuItemList.displayName = 'GlobalNavigationMenuItemList'; export default GlobalNavigationMenuItemList; diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 9ff9cc261af4..a6bd5eff05b7 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -29,7 +29,6 @@ import * as Session from '../../../libs/actions/Session'; import KeyboardShortcut from '../../../libs/KeyboardShortcut'; import onyxSubscribe from '../../../libs/onyxSubscribe'; import * as ReportActionContextMenu from '../report/ContextMenu/ReportActionContextMenu'; -import SignInOrAvatarWithOptionalStatus from './SignInOrAvatarWithOptionalStatus'; const basePropTypes = { /** Toggles the navigation menu open and closed */ @@ -169,13 +168,12 @@ class SidebarLinks extends React.PureComponent { - {}, +}); + +function mapSubNavigationOptionToGlobalNavigationOption(SubNavigationOption) { + // eslint-disable-next-line no-restricted-syntax + for (const [key] of Object.entries(GLOBAL_NAVIGATION_MAPPING)) { + if (GLOBAL_NAVIGATION_MAPPING[key].includes(SubNavigationOption)) { + return key; + } + } + return undefined; +} + +function SidebarNavigationContextProvider({children}) { + const [selectedGlobalNavigationOption, setSelectedGlobalNavigationOption] = useState(CONST.GLOBAL_NAVIGATION_OPTION.SPEND); + const [selectedSubNavigationOption, setSelectedSubNavigationOption] = useState(ROUTES.EXPENSES_OD); + + const updateFromNavigationState = useCallback( + (navigationState) => { + const topmostCentralPaneRouteName = Navigation.getTopMostCentralPaneRouteName(navigationState); + if (!topmostCentralPaneRouteName) { + return; + } + + setSelectedSubNavigationOption(topmostCentralPaneRouteName); + setSelectedGlobalNavigationOption(mapSubNavigationOptionToGlobalNavigationOption(topmostCentralPaneRouteName)); + }, + [setSelectedGlobalNavigationOption, setSelectedSubNavigationOption], + ); + + const contextValue = useMemo( + () => ({ + selectedGlobalNavigationOption, + selectedSubNavigationOption, + updateFromNavigationState, + }), + [selectedGlobalNavigationOption, selectedSubNavigationOption, updateFromNavigationState], + ); + + return {children}; +} + +SidebarNavigationContextProvider.propTypes = propTypes; + +export {SidebarNavigationContextProvider, SidebarNavigationContext}; diff --git a/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js b/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js index c8e53f3794e6..08783cd922a8 100644 --- a/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js +++ b/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js @@ -2,12 +2,11 @@ import React from 'react'; import {View} from 'react-native'; import styles from '../../../../styles/styles'; import ScreenWrapper from '../../../../components/ScreenWrapper'; -import CONST from '../../../../CONST'; import sidebarPropTypes from './sidebarPropTypes'; import * as Browser from '../../../../libs/Browser'; -import GlobalNavigation from '../GlobalNavigation'; +import GlobalNavigation from '../GlobalNavigation/GlobalNavigation'; import withWindowDimensions, {windowDimensionsPropTypes} from '../../../../components/withWindowDimensions'; -import SidebarMenu from './SidebarMenu'; +import SubNavigation from '../SubNavigation/SubNavigation'; const propTypes = { ...sidebarPropTypes, @@ -15,12 +14,6 @@ const propTypes = { }; function BaseSidebarScreen(props) { - const [shownSidebarMenu, setShownSidebarMenu] = React.useState(CONST.SIDEBAR_MENU_OPTIONS.CHATS); - - const switchSidebarMenu = (sidebarOption) => { - setShownSidebarMenu(sidebarOption); - }; - return ( - + {props.children} diff --git a/src/pages/home/sidebar/SidebarScreen/SidebarMenu.js b/src/pages/home/sidebar/SubNavigation/SubNavigation.js similarity index 57% rename from src/pages/home/sidebar/SidebarScreen/SidebarMenu.js rename to src/pages/home/sidebar/SubNavigation/SubNavigation.js index c45945039ca9..9bc6d356e621 100644 --- a/src/pages/home/sidebar/SidebarScreen/SidebarMenu.js +++ b/src/pages/home/sidebar/SubNavigation/SubNavigation.js @@ -1,5 +1,4 @@ import React, {useEffect} from 'react'; -import {View} from 'react-native'; import PropTypes from 'prop-types'; import styles from '../../../../styles/styles'; import SidebarLinksData from '../SidebarLinksData'; @@ -11,7 +10,6 @@ import * as Browser from '../../../../libs/Browser'; const propTypes = { isSmallScreenWidth: PropTypes.bool.isRequired, - shownSidebarMenu: PropTypes.string.isRequired, }; /** @@ -22,7 +20,7 @@ const startTimer = () => { Performance.markStart(CONST.TIMING.SWITCH_REPORT); }; -function SidebarMenu(props) { +function SubNavigation(props) { useEffect(() => { Performance.markStart(CONST.TIMING.SIDEBAR_LOADED); Timing.start(CONST.TIMING.SIDEBAR_LOADED, true); @@ -33,27 +31,20 @@ function SidebarMenu(props) { includeSafeAreaPaddingBottom={false} shouldEnableKeyboardAvoidingView={false} style={[styles.sidebar, Browser.isMobile() ? styles.userSelectNone : {}]} + testID={SubNavigation.displayName} > - {({insets}) => { - if (props.shownSidebarMenu === CONST.SIDEBAR_MENU_OPTIONS.CHATS) { - return ( - - ); - } - if (props.shownSidebarMenu === CONST.SIDEBAR_MENU_OPTIONS.EXPENSES) { - // TODO: Add all other sidebar menus - return null; - } - }} + {({insets}) => ( + + )} ); } -SidebarMenu.propTypes = propTypes; -SidebarMenu.displayName = 'SidebarMenu'; +SubNavigation.propTypes = propTypes; +SubNavigation.displayName = 'SubNavigation'; -export default SidebarMenu; +export default SubNavigation; From 2344abc0cd92ffda9b7efcfe78d5b9d791ecaef7 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Tue, 26 Sep 2023 20:27:33 +0200 Subject: [PATCH 05/27] style changes --- .../sidebar/GlobalNavigation/GlobalNavigation.js | 8 +++++--- .../GlobalNavigationMenuItemList.js | 10 +++++++++- src/styles/styles.js | 13 ++++++++++--- src/styles/themes/default.js | 2 +- src/styles/variables.ts | 4 ++-- 5 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigation.js b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigation.js index c20e7d7b3f34..be2496ee633f 100644 --- a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigation.js +++ b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigation.js @@ -6,7 +6,6 @@ import styles from '../../../../styles/styles'; import withLocalize, {withLocalizePropTypes} from '../../../../components/withLocalize'; import * as Expensicons from '../../../../components/Icon/Expensicons'; import GlobalNavigationMenuItemList from './GlobalNavigationMenuItemList'; -import variables from '../../../../styles/variables'; import CONST from '../../../../CONST'; import Navigation from '../../../../libs/Navigation/Navigation'; import ROUTES from '../../../../ROUTES'; @@ -36,9 +35,12 @@ function GlobalNavigation({isCreateMenuOpen}) { ); return ( - + - + ); } diff --git a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItemList.js b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItemList.js index b03e11c83619..026f323c9569 100644 --- a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItemList.js +++ b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItemList.js @@ -19,6 +19,13 @@ const propTypes = { onSelected: PropTypes.func.isRequired, }), ).isRequired, + + /* Styles for the menu items list */ + style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), +}; + +const defaultProps = { + style: {}, }; function GlobalNavigationMenuItemList(props) { @@ -29,7 +36,7 @@ function GlobalNavigationMenuItemList(props) { }; return ( - + {_.map(props.menuItems, (item) => ( ({ sidebarLink: { textDecorationLine: 'none', + marginLeft: 12, + marginRight: 12, + borderRadius: 12, }, sidebarLinkInner: { alignItems: 'center', flexDirection: 'row', - paddingLeft: 20, - paddingRight: 20, + paddingLeft: 8, + paddingRight: 8, }, sidebarLinkText: { @@ -1414,7 +1417,7 @@ const styles = (theme) => ({ }, sidebarLinkActive: { - backgroundColor: theme.border, + backgroundColor: theme.highlightBG, textDecorationLine: 'none', }, @@ -3672,6 +3675,10 @@ const styles = (theme) => ({ height: 30, width: '100%', }, + globalNavigation: { + width: variables.globalNavigationWidth, + backgroundColor: theme.highlightBG, + }, }); // For now we need to export the styles function that takes the theme as an argument diff --git a/src/styles/themes/default.js b/src/styles/themes/default.js index ffa34132c081..c596ec660e37 100644 --- a/src/styles/themes/default.js +++ b/src/styles/themes/default.js @@ -43,7 +43,7 @@ const darkTheme = { hoverComponentBG: colors.darkHighlightBackground, activeComponentBG: colors.darkBorders, signInSidebar: colors.green800, - sidebar: colors.darkHighlightBackground, + sidebar: colors.darkAppBackground, sidebarHover: colors.darkAppBackground, heading: colors.darkPrimaryText, textLight: colors.darkPrimaryText, diff --git a/src/styles/variables.ts b/src/styles/variables.ts index 2024ef31fdc7..46d933d160f0 100644 --- a/src/styles/variables.ts +++ b/src/styles/variables.ts @@ -81,8 +81,8 @@ export default { modalFullscreenBackdropOpacity: 0.5, tabletResponsiveWidthBreakpoint: 1024, safeInsertPercentage: 0.7, - globalNavigationWidth: 64, - sideBarWidth: 375 + 64, + globalNavigationWidth: 72, + sideBarWidth: 303 + 72, pdfPageMaxWidth: 992, tooltipzIndex: 10050, gutterWidth: 12, From a966c89c5dd9839427f381527f4f6073889010f9 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Thu, 28 Sep 2023 18:47:24 +0200 Subject: [PATCH 06/27] style changes v2 --- src/components/FloatingActionButton.js | 3 ++ .../GlobalNavigation/GlobalNavigation.js | 3 +- .../GlobalNavigationMenuItem.js | 40 ++++++++----------- .../GlobalNavigationMenuItemList.js | 2 + src/pages/home/sidebar/SidebarLinks.js | 14 ++----- .../SidebarScreen/BaseSidebarScreen.js | 2 +- src/styles/styles.js | 25 ++++++++++-- src/styles/utilities/spacing.ts | 4 ++ 8 files changed, 52 insertions(+), 41 deletions(-) diff --git a/src/components/FloatingActionButton.js b/src/components/FloatingActionButton.js index f1174988e955..d6f5b907ace0 100644 --- a/src/components/FloatingActionButton.js +++ b/src/components/FloatingActionButton.js @@ -9,6 +9,7 @@ import themeColors from '../styles/themes/default'; import Tooltip from './Tooltip'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; import PressableWithFeedback from './Pressable/PressableWithFeedback'; +import variables from '../styles/variables'; const AnimatedIcon = Animated.createAnimatedComponent(Icon); AnimatedIcon.displayName = 'AnimatedIcon'; @@ -100,6 +101,8 @@ class FloatingActionButton extends PureComponent { style={[styles.floatingActionButton, StyleUtils.getAnimatedFABStyle(rotate, backgroundColor)]} > diff --git a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigation.js b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigation.js index be2496ee633f..aa4a7239a214 100644 --- a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigation.js +++ b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigation.js @@ -19,7 +19,7 @@ const defaultProps = { isCreateMenuOpen: false, }; -function GlobalNavigation({isCreateMenuOpen}) { +function GlobalNavigation({isCreateMenuOpen, children}) { const items = useMemo( () => [ { @@ -41,6 +41,7 @@ function GlobalNavigation({isCreateMenuOpen}) { menuItems={items} style={styles.mt4} /> + {children} ); } diff --git a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js index addfa5b871d2..fd4712de1cd4 100644 --- a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js +++ b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js @@ -6,17 +6,15 @@ import Text from '../../../../components/Text'; import styles from '../../../../styles/styles'; import * as StyleUtils from '../../../../styles/StyleUtils'; import Icon from '../../../../components/Icon'; -import getButtonState from '../../../../libs/getButtonState'; import CONST from '../../../../CONST'; import PressableWithSecondaryInteraction from '../../../../components/PressableWithSecondaryInteraction'; import Hoverable from '../../../../components/Hoverable'; import variables from '../../../../styles/variables'; import stylePropTypes from '../../../../styles/stylePropTypes'; +import defaultTheme from '../../../../styles/themes/default'; +import fontWeightBold from '../../../../styles/fontWeight/bold'; const propTypes = { - /** Used to apply offline styles to child text components */ - style: stylePropTypes, - /** Function to fire when component is pressed */ onPress: PropTypes.func, @@ -41,18 +39,11 @@ const propTypes = { /** Whether item is focused or active */ focused: PropTypes.bool, - /** Whether the menu item should be interactive at all */ - interactive: PropTypes.bool, - - /** Any adjustments to style when menu item is hovered or pressed */ - hoverAndPressStyle: stylePropTypes, - /** Prop to represent the size of the avatar images to be shown */ avatarSize: PropTypes.oneOf(_.values(CONST.AVATAR_SIZE)), }; const defaultProps = { - style: styles.popoverMenuItem, icon: undefined, iconWidth: undefined, iconHeight: undefined, @@ -60,8 +51,6 @@ const defaultProps = { iconFill: undefined, focused: false, onPress: () => {}, - interactive: true, - hoverAndPressStyle: [], title: '', avatarSize: CONST.AVATAR_SIZE.DEFAULT, }; @@ -71,19 +60,15 @@ const GlobalNavigationMenuItem = React.forwardRef((props, ref) => ( {(isHovered) => ( {} : props.onPress} - style={({pressed}) => [ - props.style, - !props.interactive && styles.cursorDefault, - StyleUtils.getButtonBackgroundColorStyle(getButtonState(props.focused || isHovered, pressed), true), - (isHovered || pressed) && props.hoverAndPressStyle, - ]} + style={styles.globalNavigationItemContainer} ref={ref} accessibilityRole={CONST.ACCESSIBILITY_ROLE.MENUITEM} accessibilityLabel={props.title ? props.title.toString() : ''} > {({pressed}) => ( - <> - + + + ( src={props.icon} width={props.iconWidth} height={props.iconHeight} - fill={props.iconFill || StyleUtils.getIconFillColor(getButtonState(props.focused || isHovered, pressed), true)} + fill={props.focused ? defaultTheme.iconMenu : props.iconFill} /> - {props.title} + + {props.title} + - + )} )} diff --git a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItemList.js b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItemList.js index 026f323c9569..ea49871435c1 100644 --- a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItemList.js +++ b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItemList.js @@ -4,6 +4,7 @@ import PropTypes from 'prop-types'; import {View} from 'react-native'; import GlobalNavigationMenuItem from './GlobalNavigationMenuItem'; import {SidebarNavigationContext} from '../SidebarNavigationContext'; +import defaultTheme from '../../../../styles/themes/default'; const propTypes = { /** Menu items to be rendered on the list */ @@ -40,6 +41,7 @@ function GlobalNavigationMenuItemList(props) { {_.map(props.menuItems, (item) => (
- } + title={Chats} accessibilityRole={CONST.ACCESSIBILITY_ROLE.TEXT} shouldShowEnvironmentBadge /> diff --git a/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js b/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js index 08783cd922a8..6b13558a4181 100644 --- a/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js +++ b/src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.js @@ -21,7 +21,7 @@ function BaseSidebarScreen(props) { style={[styles.sidebar, Browser.isMobile() ? styles.userSelectNone : {}]} testID={BaseSidebarScreen.displayName} > - + ({ // Sidebar Styles sidebar: { backgroundColor: theme.sidebar, + borderTopLeftRadius: variables.componentBorderRadiusRounded, height: '100%', }, @@ -1265,8 +1266,7 @@ const styles = (theme) => ({ floatingActionButtonContainer: { position: 'absolute', - right: 20, - + left: 16, // The bottom of the floating action button should align with the bottom of the compose box. // The value should be equal to the height + marginBottom + marginTop of chatItemComposeSecondaryRow bottom: 25, @@ -1274,8 +1274,8 @@ const styles = (theme) => ({ floatingActionButton: { backgroundColor: theme.success, - height: variables.componentSizeLarge, - width: variables.componentSizeLarge, + height: variables.componentSizeNormal, + width: variables.componentSizeNormal, borderRadius: 999, alignItems: 'center', justifyContent: 'center', @@ -3675,10 +3675,27 @@ const styles = (theme) => ({ height: 30, width: '100%', }, + globalNavigation: { width: variables.globalNavigationWidth, backgroundColor: theme.highlightBG, }, + + globalAndSubNavigationContainer: { + backgroundColor: theme.highlightBG, + }, + + globalNavigationSelectionIndicator: { + width: 4, + height: 52, + borderTopRightRadius: variables.componentBorderRadiusRounded, + borderBottomRightRadius: variables.componentBorderRadiusRounded, + }, + + globalNavigationItemContainer: { + width: variables.globalNavigationWidth, + height: variables.globalNavigationWidth, + }, }); // For now we need to export the styles function that takes the theme as an argument diff --git a/src/styles/utilities/spacing.ts b/src/styles/utilities/spacing.ts index a3667f05ac06..7dc7bd7484af 100644 --- a/src/styles/utilities/spacing.ts +++ b/src/styles/utilities/spacing.ts @@ -445,6 +445,10 @@ export default { paddingTop: 20, }, + pt6: { + paddingTop: 24, + }, + pt10: { paddingTop: 40, }, From f8784a0de7b10f34eb09bbff8c6592dc51ae3425 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Fri, 29 Sep 2023 16:37:32 +0200 Subject: [PATCH 07/27] fix initial global navigation option on small screen --- src/pages/home/sidebar/SidebarNavigationContext.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/sidebar/SidebarNavigationContext.js b/src/pages/home/sidebar/SidebarNavigationContext.js index d0af4a029cd6..62710190d82b 100644 --- a/src/pages/home/sidebar/SidebarNavigationContext.js +++ b/src/pages/home/sidebar/SidebarNavigationContext.js @@ -26,7 +26,7 @@ function mapSubNavigationOptionToGlobalNavigationOption(SubNavigationOption) { } function SidebarNavigationContextProvider({children}) { - const [selectedGlobalNavigationOption, setSelectedGlobalNavigationOption] = useState(CONST.GLOBAL_NAVIGATION_OPTION.SPEND); + const [selectedGlobalNavigationOption, setSelectedGlobalNavigationOption] = useState(CONST.GLOBAL_NAVIGATION_OPTION.CHATS); const [selectedSubNavigationOption, setSelectedSubNavigationOption] = useState(ROUTES.EXPENSES_OD); const updateFromNavigationState = useCallback( From 3c0295e84f27be0fbfc7288fec6ffe7c516a4845 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Fri, 29 Sep 2023 18:20:44 +0200 Subject: [PATCH 08/27] adjustments --- src/libs/Navigation/linkTo.js | 1 - .../GlobalNavigation/GlobalNavigation.js | 7 +-- .../GlobalNavigationMenuItem.js | 52 ++++++------------- .../GlobalNavigationMenuItemList.js | 9 +--- 4 files changed, 19 insertions(+), 50 deletions(-) diff --git a/src/libs/Navigation/linkTo.js b/src/libs/Navigation/linkTo.js index 23dbf322fd78..601f213e9f9f 100644 --- a/src/libs/Navigation/linkTo.js +++ b/src/libs/Navigation/linkTo.js @@ -70,7 +70,6 @@ export default function linkTo(navigation, path, type) { } else if ( action.payload.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR && (getTopmostReportId(root.getState()) !== getTopmostReportId(state) || getTopMostCentralPaneRouteName(root.getState()) !== getTopMostCentralPaneRouteName(state)) - // getTopmostReportId(root.getState()) !== getTopmostReportId(state) ) { action.type = CONST.NAVIGATION.ACTION_TYPE.PUSH; diff --git a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigation.js b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigation.js index aa4a7239a214..11b86920b784 100644 --- a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigation.js +++ b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigation.js @@ -3,7 +3,6 @@ import {View} from 'react-native'; import PropTypes from 'prop-types'; import PressableAvatarWithIndicator from '../PressableAvatarWithIndicator'; import styles from '../../../../styles/styles'; -import withLocalize, {withLocalizePropTypes} from '../../../../components/withLocalize'; import * as Expensicons from '../../../../components/Icon/Expensicons'; import GlobalNavigationMenuItemList from './GlobalNavigationMenuItemList'; import CONST from '../../../../CONST'; @@ -12,14 +11,13 @@ import ROUTES from '../../../../ROUTES'; const propTypes = { isCreateMenuOpen: PropTypes.bool, - ...withLocalizePropTypes, }; const defaultProps = { isCreateMenuOpen: false, }; -function GlobalNavigation({isCreateMenuOpen, children}) { +function GlobalNavigation({isCreateMenuOpen}) { const items = useMemo( () => [ { @@ -41,7 +39,6 @@ function GlobalNavigation({isCreateMenuOpen, children}) { menuItems={items} style={styles.mt4} /> - {children} ); } @@ -50,4 +47,4 @@ GlobalNavigation.propTypes = propTypes; GlobalNavigation.defaultProps = defaultProps; GlobalNavigation.displayName = 'GlobalNavigation'; -export default withLocalize(GlobalNavigation); +export default GlobalNavigation; diff --git a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js index fd4712de1cd4..9231501f17b2 100644 --- a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js +++ b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js @@ -1,98 +1,78 @@ import React from 'react'; import {View} from 'react-native'; import PropTypes from 'prop-types'; -import _ from 'underscore'; import Text from '../../../../components/Text'; import styles from '../../../../styles/styles'; import * as StyleUtils from '../../../../styles/StyleUtils'; import Icon from '../../../../components/Icon'; import CONST from '../../../../CONST'; -import PressableWithSecondaryInteraction from '../../../../components/PressableWithSecondaryInteraction'; import Hoverable from '../../../../components/Hoverable'; import variables from '../../../../styles/variables'; -import stylePropTypes from '../../../../styles/stylePropTypes'; import defaultTheme from '../../../../styles/themes/default'; import fontWeightBold from '../../../../styles/fontWeight/bold'; +import PressableWithFeedback from '../../../../components/Pressable/PressableWithFeedback'; const propTypes = { - /** Function to fire when component is pressed */ - onPress: PropTypes.func, - /** Icon to display */ icon: PropTypes.elementType, - /** Icon Width */ - iconWidth: PropTypes.number, - - /** Icon Height */ - iconHeight: PropTypes.number, + /** The fill color to pass into the icon. */ + iconFill: PropTypes.string, /** Text to display for the item */ title: PropTypes.string, - /** Any additional styles to pass to the icon container. */ - iconStyles: stylePropTypes, - - /** The fill color to pass into the icon. */ - iconFill: PropTypes.string, + /** Function to fire when component is pressed */ + onPress: PropTypes.func, /** Whether item is focused or active */ focused: PropTypes.bool, - - /** Prop to represent the size of the avatar images to be shown */ - avatarSize: PropTypes.oneOf(_.values(CONST.AVATAR_SIZE)), }; const defaultProps = { icon: undefined, - iconWidth: undefined, - iconHeight: undefined, - iconStyles: [], iconFill: undefined, focused: false, onPress: () => {}, title: '', - avatarSize: CONST.AVATAR_SIZE.DEFAULT, }; -const GlobalNavigationMenuItem = React.forwardRef((props, ref) => ( +const GlobalNavigationMenuItem = React.forwardRef(({icon, iconFill, title, focused, onPress}, ref) => ( {(isHovered) => ( - {} : props.onPress} + {} : onPress} style={styles.globalNavigationItemContainer} ref={ref} accessibilityRole={CONST.ACCESSIBILITY_ROLE.MENUITEM} - accessibilityLabel={props.title ? props.title.toString() : ''} + accessibilityLabel={title ? title.toString() : ''} > {({pressed}) => ( - + - + - {props.title} + {title} )} - + )} )); diff --git a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItemList.js b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItemList.js index ea49871435c1..3e848c7a4024 100644 --- a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItemList.js +++ b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItemList.js @@ -32,10 +32,6 @@ const defaultProps = { function GlobalNavigationMenuItemList(props) { const sidebarNavigation = useContext(SidebarNavigationContext); - const selectItem = (value, onSelected) => { - onSelected(value); - }; - return ( {_.map(props.menuItems, (item) => ( @@ -43,11 +39,8 @@ function GlobalNavigationMenuItemList(props) { key={item.text} iconFill={defaultTheme.icon} icon={item.icon} - iconWidth={item.iconWidth} - iconHeight={item.iconHeight} title={item.text} - description={item.description} - onPress={() => selectItem(item.value, item.onSelected)} + onPress={() => item.onSelected(item.value)} focused={sidebarNavigation.selectedGlobalNavigationOption === item.value} /> ))} From c83bad0f6aae43189579b60ea0a620640367c510 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Fri, 29 Sep 2023 18:48:06 +0200 Subject: [PATCH 09/27] change OD to OLDDOT --- src/GLOBAL_NAVIGATION_MAPPING.ts | 6 +++--- src/ROUTES.ts | 14 +++++++------- src/SCREENS.ts | 14 +++++++------- src/pages/home/sidebar/SidebarNavigationContext.js | 3 +-- 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/GLOBAL_NAVIGATION_MAPPING.ts b/src/GLOBAL_NAVIGATION_MAPPING.ts index 77d79b67b995..f40e8770e69b 100644 --- a/src/GLOBAL_NAVIGATION_MAPPING.ts +++ b/src/GLOBAL_NAVIGATION_MAPPING.ts @@ -2,8 +2,8 @@ import CONST from './CONST'; import SCREENS from './SCREENS'; export default { - [CONST.GLOBAL_NAVIGATION_OPTION.HOME]: [SCREENS.HOME_OD], + [CONST.GLOBAL_NAVIGATION_OPTION.HOME]: [SCREENS.HOME_OLDDOT], [CONST.GLOBAL_NAVIGATION_OPTION.CHATS]: [SCREENS.REPORT], - [CONST.GLOBAL_NAVIGATION_OPTION.SPEND]: [SCREENS.EXPENSES_OD, SCREENS.REPORTS_OD, SCREENS.INSIGHTS_OD], - [CONST.GLOBAL_NAVIGATION_OPTION.WORKSPACES]: [SCREENS.INDIVIDUALS_OD, SCREENS.GROUPS_OD, SCREENS.CARDS_AND_DOMAINS_OD], + [CONST.GLOBAL_NAVIGATION_OPTION.SPEND]: [SCREENS.EXPENSES_OLDDOT, SCREENS.REPORTS_OLDDOT, SCREENS.INSIGHTS_OLDDOT], + [CONST.GLOBAL_NAVIGATION_OPTION.WORKSPACES]: [SCREENS.INDIVIDUALS_OLDDOT, SCREENS.GROUPS_OLDDOT, SCREENS.CARDS_AND_DOMAINS_OLDDOT], } as const; diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 4364eafb7540..e8318a13b5e2 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -320,15 +320,15 @@ export default { SBE: 'sbe', // Iframe screens from olddot - HOME_OD: 'home', + HOME_OLDDOT: 'home', // Spend tab - EXPENSES_OD: 'expenses', - REPORTS_OD: 'reports', - INSIGHTS_OD: 'insights', + EXPENSES_OLDDOT: 'expenses', + REPORTS_OLDDOT: 'reports', + INSIGHTS_OLDDOT: 'insights', // Workspaces tab - INDIVIDUALS_OD: 'individuals', - GROUPS_OD: 'groups', - CARDS_AND_DOMAINS_OD: 'cards-and-domains', + INDIVIDUALS_OLDDOT: 'individuals', + GROUPS_OLDDOT: 'groups', + CARDS_AND_DOMAINS_OLDDOT: 'cards-and-domains', } as const; diff --git a/src/SCREENS.ts b/src/SCREENS.ts index de32edd1469c..c1236263f871 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -26,15 +26,15 @@ export default { DESKTOP_SIGN_IN_REDIRECT: 'DesktopSignInRedirect', // Iframe screens from olddot - HOME_OD: 'Home_OD', + HOME_OLDDOT: 'Home_OLDDOT', // Spend tab - EXPENSES_OD: 'Expenses_OD', - REPORTS_OD: 'Reports_OD', - INSIGHTS_OD: 'INSIGHTS_OD', + EXPENSES_OLDDOT: 'Expenses_OLDDOT', + REPORTS_OLDDOT: 'Reports_OLDDOT', + INSIGHTS_OLDDOT: 'Insights_OLDDOT', // Workspaces tab - INDIVIDUALS_OD: 'Individuals_OD', - GROUPS_OD: 'Groups_OD', - CARDS_AND_DOMAINS_OD: 'CardsAndDomains_OD', + INDIVIDUALS_OLDDOT: 'Individuals_OLDDOT', + GROUPS_OLDDOT: 'Groups_OLDDOT', + CARDS_AND_DOMAINS_OLDDOT: 'CardsAndDomains_OLDDOT', } as const; diff --git a/src/pages/home/sidebar/SidebarNavigationContext.js b/src/pages/home/sidebar/SidebarNavigationContext.js index 62710190d82b..61bc99ecd914 100644 --- a/src/pages/home/sidebar/SidebarNavigationContext.js +++ b/src/pages/home/sidebar/SidebarNavigationContext.js @@ -1,7 +1,6 @@ import React, {useMemo, useCallback, useState} from 'react'; import PropTypes from 'prop-types'; import CONST from '../../../CONST'; -import ROUTES from '../../../ROUTES'; import Navigation from '../../../libs/Navigation/Navigation'; import GLOBAL_NAVIGATION_MAPPING from '../../../GLOBAL_NAVIGATION_MAPPING'; @@ -27,7 +26,7 @@ function mapSubNavigationOptionToGlobalNavigationOption(SubNavigationOption) { function SidebarNavigationContextProvider({children}) { const [selectedGlobalNavigationOption, setSelectedGlobalNavigationOption] = useState(CONST.GLOBAL_NAVIGATION_OPTION.CHATS); - const [selectedSubNavigationOption, setSelectedSubNavigationOption] = useState(ROUTES.EXPENSES_OD); + const [selectedSubNavigationOption, setSelectedSubNavigationOption] = useState(); const updateFromNavigationState = useCallback( (navigationState) => { From 1c8c9db2ddbf3a8ed487095ac4a83f73466ce99c Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Mon, 2 Oct 2023 13:27:19 +0200 Subject: [PATCH 10/27] set includePaddingTop to false --- src/pages/home/sidebar/SubNavigation/SubNavigation.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/home/sidebar/SubNavigation/SubNavigation.js b/src/pages/home/sidebar/SubNavigation/SubNavigation.js index 9bc6d356e621..043a4533bcf0 100644 --- a/src/pages/home/sidebar/SubNavigation/SubNavigation.js +++ b/src/pages/home/sidebar/SubNavigation/SubNavigation.js @@ -29,6 +29,7 @@ function SubNavigation(props) { return ( Date: Mon, 2 Oct 2023 16:50:28 +0200 Subject: [PATCH 11/27] Update src/ROUTES.ts Co-authored-by: Hayata Suenaga --- src/ROUTES.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ROUTES.ts b/src/ROUTES.ts index e8318a13b5e2..2b64dd9c5465 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -328,7 +328,7 @@ export default { INSIGHTS_OLDDOT: 'insights', // Workspaces tab - INDIVIDUALS_OLDDOT: 'individuals', - GROUPS_OLDDOT: 'groups', + INDIVIDUALS_OLDDOT: 'individual_workspaces', + GROUPS_OLDDOT: 'group_workspaces', CARDS_AND_DOMAINS_OLDDOT: 'cards-and-domains', } as const; From a2c65dbebb1941556d84ff1d444b6b94c9f50908 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski <67908363+adamgrzybowski@users.noreply.github.com> Date: Mon, 2 Oct 2023 17:06:51 +0200 Subject: [PATCH 12/27] Update src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js Co-authored-by: Hayata Suenaga --- .../home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js index 9231501f17b2..99c3e156022f 100644 --- a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js +++ b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js @@ -41,7 +41,7 @@ const GlobalNavigationMenuItem = React.forwardRef(({icon, iconFill, title, focus {(isHovered) => ( {} : onPress} + onPress={() => focused && onPress()} style={styles.globalNavigationItemContainer} ref={ref} accessibilityRole={CONST.ACCESSIBILITY_ROLE.MENUITEM} From ce4f9074eead4965a4b9018e0db94a82eb464c11 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Mon, 2 Oct 2023 19:20:01 +0200 Subject: [PATCH 13/27] adjustments v2 --- src/languages/en.ts | 3 + src/languages/es.ts | 3 + .../getTopMostCentralPaneRouteName.js | 4 +- src/libs/Navigation/linkTo.js | 10 ++-- .../GlobalNavigation/GlobalNavigation.js | 50 ----------------- .../GlobalNavigationMenuItem.js | 2 +- .../GlobalNavigationMenuItemList.js | 55 ------------------ .../home/sidebar/GlobalNavigation/index.js | 56 +++++++++++++++++++ src/pages/home/sidebar/SidebarLinks.js | 9 +-- src/pages/home/sidebar/SidebarLinksData.js | 3 +- .../home/sidebar/SidebarNavigationContext.js | 1 + .../SidebarScreen/BaseSidebarScreen.js | 18 +++--- .../sidebar/SubNavigation/SubNavigation.js | 19 ++----- tests/utils/LHNTestUtils.js | 1 - 14 files changed, 90 insertions(+), 144 deletions(-) delete mode 100644 src/pages/home/sidebar/GlobalNavigation/GlobalNavigation.js delete mode 100644 src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItemList.js create mode 100644 src/pages/home/sidebar/GlobalNavigation/index.js diff --git a/src/languages/en.ts b/src/languages/en.ts index abba4cfd71a3..ee29af37135e 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1788,4 +1788,7 @@ export default { selectSuggestedAddress: 'Please select a suggested address', }, }, + globalNavigationOptions: { + chats: 'Chats', + }, } satisfies TranslationBase; diff --git a/src/languages/es.ts b/src/languages/es.ts index fde0d22f6ec2..f4615950870b 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2271,4 +2271,7 @@ export default { selectSuggestedAddress: 'Por favor, selecciona una dirección sugerida', }, }, + globalNavigationOptions: { + chats: 'Chats', + }, } satisfies EnglishTranslation; diff --git a/src/libs/Navigation/getTopMostCentralPaneRouteName.js b/src/libs/Navigation/getTopMostCentralPaneRouteName.js index 31d646baa2bd..36cd7eae0356 100644 --- a/src/libs/Navigation/getTopMostCentralPaneRouteName.js +++ b/src/libs/Navigation/getTopMostCentralPaneRouteName.js @@ -8,12 +8,12 @@ import lodashFindLast from 'lodash/findLast'; */ function getTopMostCentralPaneRouteName(state) { if (!state) { - return; + return undefined; } const topmostCentralPane = lodashFindLast(state.routes, (route) => route.name === 'CentralPaneNavigator'); if (!topmostCentralPane) { - return; + return undefined; } if (topmostCentralPane.state && topmostCentralPane.state.routes) { diff --git a/src/libs/Navigation/linkTo.js b/src/libs/Navigation/linkTo.js index 601f213e9f9f..c0f0301a49d0 100644 --- a/src/libs/Navigation/linkTo.js +++ b/src/libs/Navigation/linkTo.js @@ -62,15 +62,17 @@ export default function linkTo(navigation, path, type) { // If action type is different than NAVIGATE we can't change it to the PUSH safely if (action.type === CONST.NAVIGATION.ACTION_TYPE.NAVIGATE) { + // Make sure that we are pushing a screen that is not currently on top of the stack. + const shouldPushIfCentralPane = + action.payload.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR && + (getTopmostReportId(root.getState()) !== getTopmostReportId(state) || getTopMostCentralPaneRouteName(root.getState()) !== getTopMostCentralPaneRouteName(state)); + // In case if type is 'FORCED_UP' we replace current screen with the provided. This means the current screen no longer exists in the stack if (type === CONST.NAVIGATION.TYPE.FORCED_UP) { action.type = CONST.NAVIGATION.ACTION_TYPE.REPLACE; // If this action is navigating to the report screen and the top most navigator is different from the one we want to navigate - PUSH the new screen to the top of the stack - } else if ( - action.payload.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR && - (getTopmostReportId(root.getState()) !== getTopmostReportId(state) || getTopMostCentralPaneRouteName(root.getState()) !== getTopMostCentralPaneRouteName(state)) - ) { + } else if (shouldPushIfCentralPane) { action.type = CONST.NAVIGATION.ACTION_TYPE.PUSH; // If the type is UP, we deeplinked into one of the RHP flows and we want to replace the current screen with the previous one in the flow diff --git a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigation.js b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigation.js deleted file mode 100644 index 11b86920b784..000000000000 --- a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigation.js +++ /dev/null @@ -1,50 +0,0 @@ -import React, {useMemo} from 'react'; -import {View} from 'react-native'; -import PropTypes from 'prop-types'; -import PressableAvatarWithIndicator from '../PressableAvatarWithIndicator'; -import styles from '../../../../styles/styles'; -import * as Expensicons from '../../../../components/Icon/Expensicons'; -import GlobalNavigationMenuItemList from './GlobalNavigationMenuItemList'; -import CONST from '../../../../CONST'; -import Navigation from '../../../../libs/Navigation/Navigation'; -import ROUTES from '../../../../ROUTES'; - -const propTypes = { - isCreateMenuOpen: PropTypes.bool, -}; - -const defaultProps = { - isCreateMenuOpen: false, -}; - -function GlobalNavigation({isCreateMenuOpen}) { - const items = useMemo( - () => [ - { - icon: Expensicons.ChatBubble, - text: 'Chats', - value: CONST.GLOBAL_NAVIGATION_OPTION.CHATS, - onSelected: () => { - Navigation.navigate(ROUTES.REPORT); - }, - }, - ], - [], - ); - - return ( - - - - - ); -} - -GlobalNavigation.propTypes = propTypes; -GlobalNavigation.defaultProps = defaultProps; -GlobalNavigation.displayName = 'GlobalNavigation'; - -export default GlobalNavigation; diff --git a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js index 99c3e156022f..900e4c47929a 100644 --- a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js +++ b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js @@ -41,7 +41,7 @@ const GlobalNavigationMenuItem = React.forwardRef(({icon, iconFill, title, focus {(isHovered) => ( focused && onPress()} + onPress={() => !focused && onPress()} style={styles.globalNavigationItemContainer} ref={ref} accessibilityRole={CONST.ACCESSIBILITY_ROLE.MENUITEM} diff --git a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItemList.js b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItemList.js deleted file mode 100644 index 3e848c7a4024..000000000000 --- a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItemList.js +++ /dev/null @@ -1,55 +0,0 @@ -import _ from 'underscore'; -import React, {useContext} from 'react'; -import PropTypes from 'prop-types'; -import {View} from 'react-native'; -import GlobalNavigationMenuItem from './GlobalNavigationMenuItem'; -import {SidebarNavigationContext} from '../SidebarNavigationContext'; -import defaultTheme from '../../../../styles/themes/default'; - -const propTypes = { - /** Menu items to be rendered on the list */ - menuItems: PropTypes.arrayOf( - PropTypes.shape({ - /** An icon element displayed on the left side */ - icon: PropTypes.elementType, - - /** Text label */ - text: PropTypes.string.isRequired, - - /** A callback triggered when this item is selected */ - onSelected: PropTypes.func.isRequired, - }), - ).isRequired, - - /* Styles for the menu items list */ - style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), -}; - -const defaultProps = { - style: {}, -}; - -function GlobalNavigationMenuItemList(props) { - const sidebarNavigation = useContext(SidebarNavigationContext); - - return ( - - {_.map(props.menuItems, (item) => ( - item.onSelected(item.value)} - focused={sidebarNavigation.selectedGlobalNavigationOption === item.value} - /> - ))} - - ); -} - -GlobalNavigationMenuItemList.propTypes = propTypes; -GlobalNavigationMenuItemList.defaultProps = defaultProps; -GlobalNavigationMenuItemList.displayName = 'GlobalNavigationMenuItemList'; - -export default GlobalNavigationMenuItemList; diff --git a/src/pages/home/sidebar/GlobalNavigation/index.js b/src/pages/home/sidebar/GlobalNavigation/index.js new file mode 100644 index 000000000000..11a576c6bd4b --- /dev/null +++ b/src/pages/home/sidebar/GlobalNavigation/index.js @@ -0,0 +1,56 @@ +import React, {useMemo, useContext} from 'react'; +import {View} from 'react-native'; +import _ from 'underscore'; +import PressableAvatarWithIndicator from '../PressableAvatarWithIndicator'; +import styles from '../../../../styles/styles'; +import * as Expensicons from '../../../../components/Icon/Expensicons'; +import CONST from '../../../../CONST'; +import Navigation from '../../../../libs/Navigation/Navigation'; +import ROUTES from '../../../../ROUTES'; +import useLocalize from '../../../../hooks/useLocalize'; +import GlobalNavigationMenuItem from './GlobalNavigationMenuItem'; +import defaultTheme from '../../../../styles/themes/default'; +import {SidebarNavigationContext} from '../SidebarNavigationContext'; + +const propTypes = {}; + +function GlobalNavigation() { + const sidebarNavigation = useContext(SidebarNavigationContext); + const {translate} = useLocalize(); + const items = useMemo( + () => [ + { + icon: Expensicons.ChatBubble, + text: translate('globalNavigationOptions.chats'), + value: CONST.GLOBAL_NAVIGATION_OPTION.CHATS, + onSelected: () => { + Navigation.navigate(ROUTES.REPORT); + }, + }, + ], + [translate], + ); + + return ( + + + + {_.map(items, (item) => ( + item.onSelected(item.value)} + focused={sidebarNavigation.selectedGlobalNavigationOption === item.value} + /> + ))} + + + ); +} + +GlobalNavigation.propTypes = propTypes; +GlobalNavigation.displayName = 'GlobalNavigation'; + +export default GlobalNavigation; diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 91e8d4c7eed5..dd1147e68f3e 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -27,11 +27,10 @@ import KeyboardShortcut from '../../../libs/KeyboardShortcut'; import onyxSubscribe from '../../../libs/onyxSubscribe'; import * as ReportActionContextMenu from '../report/ContextMenu/ReportActionContextMenu'; import Text from '../../../components/Text'; +import Performance from '../../../libs/Performance'; +import Timing from '../../../libs/actions/Timing'; const basePropTypes = { - /** Toggles the navigation menu open and closed */ - onLinkClick: PropTypes.func.isRequired, - /** Safe area insets required for mobile devices margins */ insets: safeAreaInsetPropTypes.isRequired, @@ -147,7 +146,9 @@ class SidebarLinks extends React.PureComponent { return; } Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(option.reportID)); - this.props.onLinkClick(); + + Performance.markStart(CONST.TIMING.SIDEBAR_LOADED); + Timing.start(CONST.TIMING.SIDEBAR_LOADED, true); } render() { diff --git a/src/pages/home/sidebar/SidebarLinksData.js b/src/pages/home/sidebar/SidebarLinksData.js index 243ba24cdd00..8e236d3f6f4d 100644 --- a/src/pages/home/sidebar/SidebarLinksData.js +++ b/src/pages/home/sidebar/SidebarLinksData.js @@ -63,7 +63,7 @@ const defaultProps = { policies: [], }; -function SidebarLinksData({isFocused, allReportActions, betas, chatReports, currentReportID, insets, isLoadingReportData, isSmallScreenWidth, onLinkClick, policies, priorityMode}) { +function SidebarLinksData({isFocused, allReportActions, betas, chatReports, currentReportID, insets, isLoadingReportData, isSmallScreenWidth, policies, priorityMode}) { const {translate} = useLocalize(); const reportIDsRef = useRef(null); @@ -105,7 +105,6 @@ function SidebarLinksData({isFocused, allReportActions, betas, chatReports, curr > - - + + {props.children} @@ -36,4 +32,4 @@ function BaseSidebarScreen(props) { BaseSidebarScreen.propTypes = propTypes; BaseSidebarScreen.displayName = 'BaseSidebarScreen'; -export default withWindowDimensions(BaseSidebarScreen); +export default BaseSidebarScreen; diff --git a/src/pages/home/sidebar/SubNavigation/SubNavigation.js b/src/pages/home/sidebar/SubNavigation/SubNavigation.js index 043a4533bcf0..931d6c2b704a 100644 --- a/src/pages/home/sidebar/SubNavigation/SubNavigation.js +++ b/src/pages/home/sidebar/SubNavigation/SubNavigation.js @@ -1,5 +1,4 @@ import React, {useEffect} from 'react'; -import PropTypes from 'prop-types'; import styles from '../../../../styles/styles'; import SidebarLinksData from '../SidebarLinksData'; import ScreenWrapper from '../../../../components/ScreenWrapper'; @@ -7,20 +6,13 @@ import Timing from '../../../../libs/actions/Timing'; import CONST from '../../../../CONST'; import Performance from '../../../../libs/Performance'; import * as Browser from '../../../../libs/Browser'; +import useWindowDimensions from '../../../../hooks/useWindowDimensions'; -const propTypes = { - isSmallScreenWidth: PropTypes.bool.isRequired, -}; +const propTypes = {}; -/** - * Function called when a pinned chat is selected. - */ -const startTimer = () => { - Timing.start(CONST.TIMING.SWITCH_REPORT); - Performance.markStart(CONST.TIMING.SWITCH_REPORT); -}; +function SubNavigation() { + const {isSmallScreenWidth} = useWindowDimensions(); -function SubNavigation(props) { useEffect(() => { Performance.markStart(CONST.TIMING.SIDEBAR_LOADED); Timing.start(CONST.TIMING.SIDEBAR_LOADED, true); @@ -36,9 +28,8 @@ function SubNavigation(props) { > {({insets}) => ( )} diff --git a/tests/utils/LHNTestUtils.js b/tests/utils/LHNTestUtils.js index 7cb69b23a578..037c95b6ccb1 100644 --- a/tests/utils/LHNTestUtils.js +++ b/tests/utils/LHNTestUtils.js @@ -194,7 +194,6 @@ function MockedSidebarLinks({currentReportID}) { return ( {}} insets={{ top: 0, left: 0, From 0f29a3992917d91193d4e64ab6fa2587038f783f Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Tue, 3 Oct 2023 19:07:39 +0200 Subject: [PATCH 14/27] style adjustments --- src/components/EnvironmentBadge.js | 2 +- src/components/LHNOptionsList/OptionRowLHN.js | 6 ++--- src/styles/styles.js | 24 +++++++++++++++++-- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/components/EnvironmentBadge.js b/src/components/EnvironmentBadge.js index af118a37f3b4..a83fcedfabe4 100644 --- a/src/components/EnvironmentBadge.js +++ b/src/components/EnvironmentBadge.js @@ -28,7 +28,7 @@ function EnvironmentBadge() { success={environment === CONST.ENVIRONMENT.STAGING || environment === CONST.ENVIRONMENT.ADHOC} error={environment !== CONST.ENVIRONMENT.STAGING && environment !== CONST.ENVIRONMENT.ADHOC} text={text} - badgeStyles={[styles.alignSelfEnd, styles.headerEnvBadge]} + badgeStyles={[styles.alignSelfEnd, styles.headerEnvBadge, styles.ml1]} textStyles={[styles.headerEnvBadgeText]} environment={environment} /> diff --git a/src/components/LHNOptionsList/OptionRowLHN.js b/src/components/LHNOptionsList/OptionRowLHN.js index 3cfd7c4c4138..04d813dbd8c3 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.js +++ b/src/components/LHNOptionsList/OptionRowLHN.js @@ -54,7 +54,7 @@ const propTypes = { }; const defaultProps = { - hoverStyle: styles.sidebarLinkHover, + hoverStyle: styles.sidebarLinkHoverLHN, viewMode: 'default', onSelectRow: () => {}, style: null, @@ -97,7 +97,7 @@ function OptionRowLHN(props) { : [styles.chatLinkRowPressable, styles.flexGrow1, styles.optionItemAvatarNameWrapper, styles.optionRow, styles.justifyContentCenter], ); const hoveredBackgroundColor = props.hoverStyle && props.hoverStyle.backgroundColor ? props.hoverStyle.backgroundColor : themeColors.sidebar; - const focusedBackgroundColor = styles.sidebarLinkActive.backgroundColor; + const focusedBackgroundColor = styles.sidebarLinkActiveLHN.backgroundColor; const hasBrickError = optionItem.brickRoadIndicator === CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR; const defaultSubscriptSize = optionItem.isExpenseRequest ? CONST.AVATAR_SIZE.SMALL_NORMAL : CONST.AVATAR_SIZE.DEFAULT; @@ -169,7 +169,7 @@ function OptionRowLHN(props) { styles.flexRow, styles.alignItemsCenter, styles.justifyContentBetween, - styles.sidebarLink, + styles.sidebarLinkLHN, styles.sidebarLinkInner, StyleUtils.getBackgroundColorStyle(themeColors.sidebar), props.isFocused ? styles.sidebarLinkActive : null, diff --git a/src/styles/styles.js b/src/styles/styles.js index 5f172554a39e..56263fe8e0cf 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -1332,7 +1332,7 @@ const styles = (theme) => ({ createMenuPositionSidebar: (windowHeight) => ({ horizontal: 18, - vertical: windowHeight - 100, + vertical: windowHeight - 75, }), createMenuPositionProfile: (windowWidth) => ({ @@ -1398,12 +1398,23 @@ const styles = (theme) => ({ sidebarLink: { textDecorationLine: 'none', + }, + + sidebarLinkLHN: { + textDecorationLine: 'none', marginLeft: 12, marginRight: 12, - borderRadius: 12, + borderRadius: 8, }, sidebarLinkInner: { + alignItems: 'center', + flexDirection: 'row', + paddingLeft: 20, + paddingRight: 20, + }, + + sidebarLinkInnerLHN: { alignItems: 'center', flexDirection: 'row', paddingLeft: 8, @@ -1421,7 +1432,16 @@ const styles = (theme) => ({ backgroundColor: theme.sidebarHover, }, + sidebarLinkHoverLHN: { + backgroundColor: theme.highlightBG, + }, + sidebarLinkActive: { + backgroundColor: theme.border, + textDecorationLine: 'none', + }, + + sidebarLinkActiveLHN: { backgroundColor: theme.highlightBG, textDecorationLine: 'none', }, From 95f47b347205d985e7a0c8e452051550a266815f Mon Sep 17 00:00:00 2001 From: Adam Grzybowski <67908363+adamgrzybowski@users.noreply.github.com> Date: Wed, 4 Oct 2023 13:16:40 +0200 Subject: [PATCH 15/27] Update src/SCREENS.ts Co-authored-by: Hayata Suenaga --- src/SCREENS.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SCREENS.ts b/src/SCREENS.ts index c1236263f871..0346168f0407 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -34,7 +34,7 @@ export default { INSIGHTS_OLDDOT: 'Insights_OLDDOT', // Workspaces tab - INDIVIDUALS_OLDDOT: 'Individuals_OLDDOT', - GROUPS_OLDDOT: 'Groups_OLDDOT', + INDIVIDUAL_WORKSPACES_OLDDOT: 'IndividualWorkspaces_OLDDOT', + GROUPS_WORKSPACES_OLDDOT: 'GroupWorkspaces_OLDDOT', CARDS_AND_DOMAINS_OLDDOT: 'CardsAndDomains_OLDDOT', } as const; From dfd2e8226350523cb56530e86be58d135e3e8cf9 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski <67908363+adamgrzybowski@users.noreply.github.com> Date: Wed, 4 Oct 2023 13:17:43 +0200 Subject: [PATCH 16/27] Update src/libs/Navigation/getTopMostCentralPaneRouteName.js Co-authored-by: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> --- src/libs/Navigation/getTopMostCentralPaneRouteName.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/Navigation/getTopMostCentralPaneRouteName.js b/src/libs/Navigation/getTopMostCentralPaneRouteName.js index 36cd7eae0356..d04cf86f220f 100644 --- a/src/libs/Navigation/getTopMostCentralPaneRouteName.js +++ b/src/libs/Navigation/getTopMostCentralPaneRouteName.js @@ -22,7 +22,7 @@ function getTopMostCentralPaneRouteName(state) { } if (topmostCentralPane.params) { - // State may don't have inner state in some cases (e.g generating actions from path). But in this case there will be params available. + // State may not have inner state in some cases (e.g generating actions from path). But in this case there will be params available. return topmostCentralPane.screen; } From 50117d78a9dd0aa866be478efb8d1c2de1e4541a Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Wed, 4 Oct 2023 14:52:33 +0200 Subject: [PATCH 17/27] adjustments v3 --- .../getTopMostCentralPaneRouteName.js | 4 +- src/libs/Navigation/linkTo.js | 4 +- .../GlobalNavigationMenuItem.js | 80 +++++++++---------- .../home/sidebar/GlobalNavigation/index.js | 3 +- .../home/sidebar/SidebarNavigationContext.js | 34 +++----- src/styles/styles.js | 7 +- 6 files changed, 62 insertions(+), 70 deletions(-) diff --git a/src/libs/Navigation/getTopMostCentralPaneRouteName.js b/src/libs/Navigation/getTopMostCentralPaneRouteName.js index d04cf86f220f..f833575a397a 100644 --- a/src/libs/Navigation/getTopMostCentralPaneRouteName.js +++ b/src/libs/Navigation/getTopMostCentralPaneRouteName.js @@ -22,8 +22,8 @@ function getTopMostCentralPaneRouteName(state) { } if (topmostCentralPane.params) { - // State may not have inner state in some cases (e.g generating actions from path). But in this case there will be params available. - return topmostCentralPane.screen; + // State may don't have inner state in some cases (e.g generating actions from path). But in this case there will be params available. + return topmostCentralPane.params.screen; } return undefined; diff --git a/src/libs/Navigation/linkTo.js b/src/libs/Navigation/linkTo.js index c0f0301a49d0..fcb3bd5df9c5 100644 --- a/src/libs/Navigation/linkTo.js +++ b/src/libs/Navigation/linkTo.js @@ -65,13 +65,11 @@ export default function linkTo(navigation, path, type) { // Make sure that we are pushing a screen that is not currently on top of the stack. const shouldPushIfCentralPane = action.payload.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR && - (getTopmostReportId(root.getState()) !== getTopmostReportId(state) || getTopMostCentralPaneRouteName(root.getState()) !== getTopMostCentralPaneRouteName(state)); + (getTopMostCentralPaneRouteName(root.getState()) !== getTopMostCentralPaneRouteName(state) || getTopmostReportId(root.getState()) !== getTopmostReportId(state)); // In case if type is 'FORCED_UP' we replace current screen with the provided. This means the current screen no longer exists in the stack if (type === CONST.NAVIGATION.TYPE.FORCED_UP) { action.type = CONST.NAVIGATION.ACTION_TYPE.REPLACE; - - // If this action is navigating to the report screen and the top most navigator is different from the one we want to navigate - PUSH the new screen to the top of the stack } else if (shouldPushIfCentralPane) { action.type = CONST.NAVIGATION.ACTION_TYPE.PUSH; diff --git a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js index 900e4c47929a..0b93ca7d13bf 100644 --- a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js +++ b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js @@ -9,76 +9,76 @@ import CONST from '../../../../CONST'; import Hoverable from '../../../../components/Hoverable'; import variables from '../../../../styles/variables'; import defaultTheme from '../../../../styles/themes/default'; -import fontWeightBold from '../../../../styles/fontWeight/bold'; import PressableWithFeedback from '../../../../components/Pressable/PressableWithFeedback'; +import refPropTypes from '../../../../components/refPropTypes'; const propTypes = { /** Icon to display */ icon: PropTypes.elementType, - /** The fill color to pass into the icon. */ - iconFill: PropTypes.string, - /** Text to display for the item */ title: PropTypes.string, /** Function to fire when component is pressed */ onPress: PropTypes.func, + /** A ref to forward to PressableWithFeedback */ + forwardedRef: refPropTypes, + /** Whether item is focused or active */ - focused: PropTypes.bool, + isFocused: PropTypes.bool, }; const defaultProps = { icon: undefined, - iconFill: undefined, - focused: false, + isFocused: false, onPress: () => {}, title: '', + forwardedRef: null, }; -const GlobalNavigationMenuItem = React.forwardRef(({icon, iconFill, title, focused, onPress}, ref) => ( - - {(isHovered) => ( - !focused && onPress()} - style={styles.globalNavigationItemContainer} - ref={ref} - accessibilityRole={CONST.ACCESSIBILITY_ROLE.MENUITEM} - accessibilityLabel={title ? title.toString() : ''} - > - {({pressed}) => ( - - - - +function GlobalNavigationMenuItem({icon, title, isFocused, onPress, forwardedRef}) { + return ( + + {(isHovered) => ( + !isFocused && onPress()} + style={styles.globalNavigationItemContainer} + ref={forwardedRef} + accessibilityRole={CONST.ACCESSIBILITY_ROLE.MENUITEM} + accessibilityLabel={title} + > + {({pressed}) => ( + + + - - - - {title} - + + {title} + - - )} - - )} - -)); + )} + + )} + + ); +} GlobalNavigationMenuItem.propTypes = propTypes; GlobalNavigationMenuItem.defaultProps = defaultProps; GlobalNavigationMenuItem.displayName = 'GlobalNavigationMenuItem'; -export default GlobalNavigationMenuItem; +export default React.forwardRef((props, ref) => ( + +)); diff --git a/src/pages/home/sidebar/GlobalNavigation/index.js b/src/pages/home/sidebar/GlobalNavigation/index.js index 11a576c6bd4b..be6752c4e6f2 100644 --- a/src/pages/home/sidebar/GlobalNavigation/index.js +++ b/src/pages/home/sidebar/GlobalNavigation/index.js @@ -38,11 +38,10 @@ function GlobalNavigation() { {_.map(items, (item) => ( item.onSelected(item.value)} - focused={sidebarNavigation.selectedGlobalNavigationOption === item.value} + isFocused={sidebarNavigation.selectedGlobalNavigationOption === item.value} /> ))} diff --git a/src/pages/home/sidebar/SidebarNavigationContext.js b/src/pages/home/sidebar/SidebarNavigationContext.js index f6bdf489dcaf..65898031dd77 100644 --- a/src/pages/home/sidebar/SidebarNavigationContext.js +++ b/src/pages/home/sidebar/SidebarNavigationContext.js @@ -1,5 +1,6 @@ import React, {useMemo, useCallback, useState} from 'react'; import PropTypes from 'prop-types'; +import _ from 'underscore'; import CONST from '../../../CONST'; import Navigation from '../../../libs/Navigation/Navigation'; import GLOBAL_NAVIGATION_MAPPING from '../../../GLOBAL_NAVIGATION_MAPPING'; @@ -15,32 +16,22 @@ const SidebarNavigationContext = React.createContext({ updateFromNavigationState: () => {}, }); -function mapSubNavigationOptionToGlobalNavigationOption(SubNavigationOption) { - // eslint-disable-next-line no-restricted-syntax - for (const [key] of Object.entries(GLOBAL_NAVIGATION_MAPPING)) { - if (GLOBAL_NAVIGATION_MAPPING[key].includes(SubNavigationOption)) { - return key; - } - } - return undefined; -} +const mapSubNavigationOptionToGlobalNavigationOption = (SubNavigationOption) => + _.findKey(GLOBAL_NAVIGATION_MAPPING, (globalNavigationOptions) => globalNavigationOptions.includes(SubNavigationOption)); function SidebarNavigationContextProvider({children}) { const [selectedGlobalNavigationOption, setSelectedGlobalNavigationOption] = useState(CONST.GLOBAL_NAVIGATION_OPTION.CHATS); const [selectedSubNavigationOption, setSelectedSubNavigationOption] = useState(); - const updateFromNavigationState = useCallback( - (navigationState) => { - const topmostCentralPaneRouteName = Navigation.getTopMostCentralPaneRouteName(navigationState); - if (!topmostCentralPaneRouteName) { - return; - } - - setSelectedSubNavigationOption(topmostCentralPaneRouteName); - setSelectedGlobalNavigationOption(mapSubNavigationOptionToGlobalNavigationOption(topmostCentralPaneRouteName)); - }, - [setSelectedGlobalNavigationOption, setSelectedSubNavigationOption], - ); + const updateFromNavigationState = useCallback((navigationState) => { + const topmostCentralPaneRouteName = Navigation.getTopMostCentralPaneRouteName(navigationState); + if (!topmostCentralPaneRouteName) { + return; + } + + setSelectedSubNavigationOption(topmostCentralPaneRouteName); + setSelectedGlobalNavigationOption(mapSubNavigationOptionToGlobalNavigationOption(topmostCentralPaneRouteName)); + }, []); const contextValue = useMemo( () => ({ @@ -48,6 +39,7 @@ function SidebarNavigationContextProvider({children}) { selectedSubNavigationOption, updateFromNavigationState, }), + // eslint-disable-next-line react-hooks/exhaustive-deps [selectedGlobalNavigationOption, selectedSubNavigationOption, updateFromNavigationState], ); diff --git a/src/styles/styles.js b/src/styles/styles.js index 56263fe8e0cf..82cce0c86045 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -3727,12 +3727,15 @@ const styles = (theme) => ({ backgroundColor: theme.highlightBG, }, - globalNavigationSelectionIndicator: { + globalNavigationSelectionIndicator: (isFocused) => ({ width: 4, height: 52, borderTopRightRadius: variables.componentBorderRadiusRounded, borderBottomRightRadius: variables.componentBorderRadiusRounded, - }, + backgroundColor: isFocused ? defaultTheme.iconMenu : defaultTheme.transparent, + }), + + globalNavigationMenuItem: (isFocused) => (isFocused ? {color: defaultTheme.textLight, fontWeight: fontWeightBold} : {color: defaultTheme.icon}), globalNavigationItemContainer: { width: variables.globalNavigationWidth, From 36e6c61f0a0c650e3764c6466338dedc4f40eaf1 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Wed, 4 Oct 2023 15:10:54 +0200 Subject: [PATCH 18/27] adjustments v4 --- .../GlobalNavigationMenuItem.js | 50 ++++++++----------- .../home/sidebar/GlobalNavigation/index.js | 7 +-- src/pages/home/sidebar/SidebarLinks.js | 2 +- 3 files changed, 25 insertions(+), 34 deletions(-) diff --git a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js index 0b93ca7d13bf..4c49edd6ce83 100644 --- a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js +++ b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js @@ -6,7 +6,6 @@ import styles from '../../../../styles/styles'; import * as StyleUtils from '../../../../styles/StyleUtils'; import Icon from '../../../../components/Icon'; import CONST from '../../../../CONST'; -import Hoverable from '../../../../components/Hoverable'; import variables from '../../../../styles/variables'; import defaultTheme from '../../../../styles/themes/default'; import PressableWithFeedback from '../../../../components/Pressable/PressableWithFeedback'; @@ -39,35 +38,30 @@ const defaultProps = { function GlobalNavigationMenuItem({icon, title, isFocused, onPress, forwardedRef}) { return ( - - {(isHovered) => ( - !isFocused && onPress()} - style={styles.globalNavigationItemContainer} - ref={forwardedRef} - accessibilityRole={CONST.ACCESSIBILITY_ROLE.MENUITEM} - accessibilityLabel={title} - > - {({pressed}) => ( - - - - - - {title} - - + !isFocused && onPress()} + style={styles.globalNavigationItemContainer} + ref={forwardedRef} + accessibilityRole={CONST.ACCESSIBILITY_ROLE.MENUITEM} + accessibilityLabel={title} + > + {({pressed}) => ( + + + + + + {title} - )} - + + )} - + ); } diff --git a/src/pages/home/sidebar/GlobalNavigation/index.js b/src/pages/home/sidebar/GlobalNavigation/index.js index be6752c4e6f2..c996e02e63c7 100644 --- a/src/pages/home/sidebar/GlobalNavigation/index.js +++ b/src/pages/home/sidebar/GlobalNavigation/index.js @@ -9,10 +9,8 @@ import Navigation from '../../../../libs/Navigation/Navigation'; import ROUTES from '../../../../ROUTES'; import useLocalize from '../../../../hooks/useLocalize'; import GlobalNavigationMenuItem from './GlobalNavigationMenuItem'; -import defaultTheme from '../../../../styles/themes/default'; import {SidebarNavigationContext} from '../SidebarNavigationContext'; - -const propTypes = {}; +import SignInOrAvatarWithOptionalStatus from '../SignInOrAvatarWithOptionalStatus'; function GlobalNavigation() { const sidebarNavigation = useContext(SidebarNavigationContext); @@ -33,7 +31,7 @@ function GlobalNavigation() { return ( - + {_.map(items, (item) => (
Chats} + title={{this.props.translate('globalNavigationOptions.chats')}} accessibilityRole={CONST.ACCESSIBILITY_ROLE.TEXT} shouldShowEnvironmentBadge /> From c35523c4041601736d1683789186e47d1e7f2aee Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Wed, 4 Oct 2023 17:05:04 +0200 Subject: [PATCH 19/27] remove nested ScreenWrapper --- .../sidebar/SubNavigation/SubNavigation.js | 29 ++++++++----------- src/styles/styles.js | 7 ++++- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/pages/home/sidebar/SubNavigation/SubNavigation.js b/src/pages/home/sidebar/SubNavigation/SubNavigation.js index 7966ee3e53d1..0c893b356099 100644 --- a/src/pages/home/sidebar/SubNavigation/SubNavigation.js +++ b/src/pages/home/sidebar/SubNavigation/SubNavigation.js @@ -1,39 +1,34 @@ import React, {useEffect} from 'react'; import PropTypes from 'prop-types'; +import {View} from 'react-native'; import styles from '../../../../styles/styles'; import SidebarLinksData from '../SidebarLinksData'; -import ScreenWrapper from '../../../../components/ScreenWrapper'; import Timing from '../../../../libs/actions/Timing'; import CONST from '../../../../CONST'; import Performance from '../../../../libs/Performance'; -import * as Browser from '../../../../libs/Browser'; +import safeAreaInsetPropTypes from '../../../safeAreaInsetPropTypes'; const propTypes = { /** Function called when a pinned chat is selected. */ onLinkClick: PropTypes.func.isRequired, + + /** Insets for SidebarLInksData */ + insets: safeAreaInsetPropTypes.isRequired, }; -function SubNavigation({onLinkClick}) { +function SubNavigation({onLinkClick, insets}) { useEffect(() => { Performance.markStart(CONST.TIMING.SIDEBAR_LOADED); Timing.start(CONST.TIMING.SIDEBAR_LOADED, true); }, []); return ( - - {({insets}) => ( - - )} - + + + ); } diff --git a/src/styles/styles.js b/src/styles/styles.js index e28afddfaa0e..68cff99c58bc 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -1232,10 +1232,15 @@ const styles = (theme) => ({ // Sidebar Styles sidebar: { backgroundColor: theme.sidebar, - borderTopLeftRadius: variables.componentBorderRadiusRounded, height: '100%', }, + subNavigationContainer: { + backgroundColor: theme.sidebar, + flex: 1, + borderTopLeftRadius: variables.componentBorderRadiusRounded, + }, + sidebarAnimatedWrapperContainer: { height: '100%', position: 'absolute', From a5ae067d44e5286a29b28b1610ca917c768dced0 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski <67908363+adamgrzybowski@users.noreply.github.com> Date: Wed, 4 Oct 2023 17:06:08 +0200 Subject: [PATCH 20/27] Update src/components/LHNOptionsList/OptionRowLHN.js Co-authored-by: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> --- src/components/LHNOptionsList/OptionRowLHN.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/LHNOptionsList/OptionRowLHN.js b/src/components/LHNOptionsList/OptionRowLHN.js index 328bfe82df0e..91908e4e09d8 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.js +++ b/src/components/LHNOptionsList/OptionRowLHN.js @@ -170,7 +170,7 @@ function OptionRowLHN(props) { onSecondaryInteraction={(e) => showPopover(e)} withoutFocusOnSecondaryInteraction activeOpacity={0.8} - style={[ + styles.sidebarLinkInnerLHN, styles.flexRow, styles.alignItemsCenter, styles.justifyContentBetween, From 1f6da9f4a1b88568219ad495878a77699cd8cc88 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Wed, 4 Oct 2023 17:11:25 +0200 Subject: [PATCH 21/27] Revert "Update src/components/LHNOptionsList/OptionRowLHN.js" This reverts commit a5ae067d44e5286a29b28b1610ca917c768dced0. --- src/components/LHNOptionsList/OptionRowLHN.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/LHNOptionsList/OptionRowLHN.js b/src/components/LHNOptionsList/OptionRowLHN.js index 91908e4e09d8..328bfe82df0e 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.js +++ b/src/components/LHNOptionsList/OptionRowLHN.js @@ -170,7 +170,7 @@ function OptionRowLHN(props) { onSecondaryInteraction={(e) => showPopover(e)} withoutFocusOnSecondaryInteraction activeOpacity={0.8} - styles.sidebarLinkInnerLHN, + style={[ styles.flexRow, styles.alignItemsCenter, styles.justifyContentBetween, From ca9902879b65a68d5f0e246f75b55d20567cdb75 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Wed, 4 Oct 2023 17:13:57 +0200 Subject: [PATCH 22/27] fix styles for OptionRowLHN --- src/components/LHNOptionsList/OptionRowLHN.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/LHNOptionsList/OptionRowLHN.js b/src/components/LHNOptionsList/OptionRowLHN.js index 328bfe82df0e..c49488bda7f3 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.js +++ b/src/components/LHNOptionsList/OptionRowLHN.js @@ -175,7 +175,7 @@ function OptionRowLHN(props) { styles.alignItemsCenter, styles.justifyContentBetween, styles.sidebarLinkLHN, - styles.sidebarLinkInner, + styles.sidebarLinkInnerLHN, StyleUtils.getBackgroundColorStyle(themeColors.sidebar), props.isFocused ? styles.sidebarLinkActive : null, (hovered || isContextMenuActive) && !props.isFocused ? props.hoverStyle : null, From 7250a2f74c2468185df0324ea76db0ea214e6832 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Wed, 4 Oct 2023 17:22:17 +0200 Subject: [PATCH 23/27] fix GLOBAL_NAVIGATION_MAPPING --- src/GLOBAL_NAVIGATION_MAPPING.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GLOBAL_NAVIGATION_MAPPING.ts b/src/GLOBAL_NAVIGATION_MAPPING.ts index f40e8770e69b..f879c508ff31 100644 --- a/src/GLOBAL_NAVIGATION_MAPPING.ts +++ b/src/GLOBAL_NAVIGATION_MAPPING.ts @@ -5,5 +5,5 @@ export default { [CONST.GLOBAL_NAVIGATION_OPTION.HOME]: [SCREENS.HOME_OLDDOT], [CONST.GLOBAL_NAVIGATION_OPTION.CHATS]: [SCREENS.REPORT], [CONST.GLOBAL_NAVIGATION_OPTION.SPEND]: [SCREENS.EXPENSES_OLDDOT, SCREENS.REPORTS_OLDDOT, SCREENS.INSIGHTS_OLDDOT], - [CONST.GLOBAL_NAVIGATION_OPTION.WORKSPACES]: [SCREENS.INDIVIDUALS_OLDDOT, SCREENS.GROUPS_OLDDOT, SCREENS.CARDS_AND_DOMAINS_OLDDOT], + [CONST.GLOBAL_NAVIGATION_OPTION.WORKSPACES]: [SCREENS.INDIVIDUAL_WORKSPACES_OLDDOT, SCREENS.GROUPS_WORKSPACES_OLDDOT, SCREENS.CARDS_AND_DOMAINS_OLDDOT], } as const; From 8bb5406b9ad61eeaf8d7af88b29ffe09ea6ab303 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Thu, 5 Oct 2023 12:51:55 +0200 Subject: [PATCH 24/27] adjustments v5 --- src/pages/home/sidebar/GlobalNavigation/index.js | 2 +- src/pages/home/sidebar/SidebarLinks.js | 2 -- src/pages/home/sidebar/SidebarNavigationContext.js | 1 - .../home/sidebar/SidebarScreen/BaseSidebarScreen.js | 9 +++++++-- src/pages/home/sidebar/SidebarScreen/sidebarPropTypes.js | 7 ------- src/styles/styles.js | 4 ++-- src/styles/themes/light.js | 2 +- 7 files changed, 11 insertions(+), 16 deletions(-) delete mode 100644 src/pages/home/sidebar/SidebarScreen/sidebarPropTypes.js diff --git a/src/pages/home/sidebar/GlobalNavigation/index.js b/src/pages/home/sidebar/GlobalNavigation/index.js index 7b880d3d30e9..e6665930afd8 100644 --- a/src/pages/home/sidebar/GlobalNavigation/index.js +++ b/src/pages/home/sidebar/GlobalNavigation/index.js @@ -34,7 +34,7 @@ function GlobalNavigation() { {_.map(items, (item) => ( item.onSelected(item.value)} diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 15d37854cc75..695e0226142c 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -24,7 +24,6 @@ import KeyboardShortcut from '../../../libs/KeyboardShortcut'; import onyxSubscribe from '../../../libs/onyxSubscribe'; import * as ReportActionContextMenu from '../report/ContextMenu/ReportActionContextMenu'; import Text from '../../../components/Text'; -import SignInOrAvatarWithOptionalStatus from './SignInOrAvatarWithOptionalStatus'; import useLocalize from '../../../hooks/useLocalize'; import useWindowDimensions from '../../../hooks/useWindowDimensions'; @@ -162,7 +161,6 @@ function SidebarLinks({onLinkClick, insets, optionListItems, isLoading, priority - ({ height: 52, borderTopRightRadius: variables.componentBorderRadiusRounded, borderBottomRightRadius: variables.componentBorderRadiusRounded, - backgroundColor: isFocused ? defaultTheme.iconMenu : defaultTheme.transparent, + backgroundColor: isFocused ? theme.iconMenu : theme.transparent, }), - globalNavigationMenuItem: (isFocused) => (isFocused ? {color: defaultTheme.textLight, fontWeight: fontWeightBold} : {color: defaultTheme.icon}), + globalNavigationMenuItem: (isFocused) => (isFocused ? {color: theme.textLight, fontWeight: fontWeightBold, fontFamily: fontFamily.EXP_NEUE_BOLD} : {color: theme.icon}), globalNavigationItemContainer: { width: variables.globalNavigationWidth, diff --git a/src/styles/themes/light.js b/src/styles/themes/light.js index c459f9f10da6..3c80eb589a07 100644 --- a/src/styles/themes/light.js +++ b/src/styles/themes/light.js @@ -41,7 +41,7 @@ const lightTheme = { hoverComponentBG: colors.lightHighlightBackground, activeComponentBG: colors.lightBorders, signInSidebar: colors.green800, - sidebar: colors.lightHighlightBackground, + sidebar: colors.lightAppBackground, sidebarHover: colors.lightBorders, heading: colors.lightPrimaryText, textLight: colors.white, From 4c056fa064b2ddd7a923b2b673f8cef298964511 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Thu, 5 Oct 2023 14:09:41 +0200 Subject: [PATCH 25/27] fix color for focused item in global navigation --- .../home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js | 3 +-- src/styles/styles.js | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js index 4c49edd6ce83..f0eb381de2df 100644 --- a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js +++ b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js @@ -7,7 +7,6 @@ import * as StyleUtils from '../../../../styles/StyleUtils'; import Icon from '../../../../components/Icon'; import CONST from '../../../../CONST'; import variables from '../../../../styles/variables'; -import defaultTheme from '../../../../styles/themes/default'; import PressableWithFeedback from '../../../../components/Pressable/PressableWithFeedback'; import refPropTypes from '../../../../components/refPropTypes'; @@ -53,7 +52,7 @@ function GlobalNavigationMenuItem({icon, title, isFocused, onPress, forwardedRef additionalStyles={[styles.popoverMenuIcon]} pressed={pressed} src={icon} - fill={isFocused ? defaultTheme.iconMenu : defaultTheme.icon} + fill={isFocused ? StyleUtils.getIconFillColor(CONST.BUTTON_STATES.DEFAULT, true) : StyleUtils.getIconFillColor()} /> {title} diff --git a/src/styles/styles.js b/src/styles/styles.js index cd8a324304b0..a95950e4e7ba 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -3734,7 +3734,7 @@ const styles = (theme) => ({ backgroundColor: isFocused ? theme.iconMenu : theme.transparent, }), - globalNavigationMenuItem: (isFocused) => (isFocused ? {color: theme.textLight, fontWeight: fontWeightBold, fontFamily: fontFamily.EXP_NEUE_BOLD} : {color: theme.icon}), + globalNavigationMenuItem: (isFocused) => (isFocused ? {color: theme.text, fontWeight: fontWeightBold, fontFamily: fontFamily.EXP_NEUE_BOLD} : {color: theme.icon}), globalNavigationItemContainer: { width: variables.globalNavigationWidth, From a6ad209bbf154e26ecb13a5d58e0360ff11b769a Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Thu, 5 Oct 2023 14:42:02 +0200 Subject: [PATCH 26/27] fix top elements aligment --- src/pages/home/sidebar/GlobalNavigation/index.js | 2 +- src/pages/home/sidebar/SidebarLinks.js | 2 +- src/styles/styles.js | 12 ++++++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/pages/home/sidebar/GlobalNavigation/index.js b/src/pages/home/sidebar/GlobalNavigation/index.js index e6665930afd8..1a8e923d1ff6 100644 --- a/src/pages/home/sidebar/GlobalNavigation/index.js +++ b/src/pages/home/sidebar/GlobalNavigation/index.js @@ -31,7 +31,7 @@ function GlobalNavigation() { return ( - + {_.map(items, (item) => (
({ height: '100%', }, + sidebarHeaderContainer: { + flexDirection: 'row', + paddingHorizontal: 20, + paddingVertical: 19, + justifyContent: 'space-between', + alignItems: 'center', + }, + subNavigationContainer: { backgroundColor: theme.sidebar, flex: 1, @@ -3722,6 +3730,10 @@ const styles = (theme) => ({ backgroundColor: theme.highlightBG, }, + globalNavigationMenuContainer: { + marginTop: 13, + }, + globalAndSubNavigationContainer: { backgroundColor: theme.highlightBG, }, From 9e879530de4d84ceaed9b9181d10f26cd1a902f6 Mon Sep 17 00:00:00 2001 From: Adam Grzybowski Date: Thu, 5 Oct 2023 16:08:29 +0200 Subject: [PATCH 27/27] change ref for GlobalNavigationMenuItem --- .../GlobalNavigationMenuItem.js | 63 ++++++++----------- 1 file changed, 25 insertions(+), 38 deletions(-) diff --git a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js index f0eb381de2df..d24960e80ff2 100644 --- a/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js +++ b/src/pages/home/sidebar/GlobalNavigation/GlobalNavigationMenuItem.js @@ -8,7 +8,6 @@ import Icon from '../../../../components/Icon'; import CONST from '../../../../CONST'; import variables from '../../../../styles/variables'; import PressableWithFeedback from '../../../../components/Pressable/PressableWithFeedback'; -import refPropTypes from '../../../../components/refPropTypes'; const propTypes = { /** Icon to display */ @@ -20,9 +19,6 @@ const propTypes = { /** Function to fire when component is pressed */ onPress: PropTypes.func, - /** A ref to forward to PressableWithFeedback */ - forwardedRef: refPropTypes, - /** Whether item is focused or active */ isFocused: PropTypes.bool, }; @@ -32,46 +28,37 @@ const defaultProps = { isFocused: false, onPress: () => {}, title: '', - forwardedRef: null, }; -function GlobalNavigationMenuItem({icon, title, isFocused, onPress, forwardedRef}) { - return ( - !isFocused && onPress()} - style={styles.globalNavigationItemContainer} - ref={forwardedRef} - accessibilityRole={CONST.ACCESSIBILITY_ROLE.MENUITEM} - accessibilityLabel={title} - > - {({pressed}) => ( - - - - - - {title} - +const GlobalNavigationMenuItem = React.forwardRef(({icon, title, isFocused, onPress}, ref) => ( + !isFocused && onPress()} + style={styles.globalNavigationItemContainer} + ref={ref} + accessibilityRole={CONST.ACCESSIBILITY_ROLE.MENUITEM} + accessibilityLabel={title} + > + {({pressed}) => ( + + + + + + {title} - )} - - ); -} + + )} + +)); GlobalNavigationMenuItem.propTypes = propTypes; GlobalNavigationMenuItem.defaultProps = defaultProps; GlobalNavigationMenuItem.displayName = 'GlobalNavigationMenuItem'; -export default React.forwardRef((props, ref) => ( - -)); +export default GlobalNavigationMenuItem;