diff --git a/src/components/HeaderWithBackButton/headerWithBackButtonPropTypes.js b/src/components/HeaderWithBackButton/headerWithBackButtonPropTypes.js
index d2cdc5b29898..8db9fbb3a321 100644
--- a/src/components/HeaderWithBackButton/headerWithBackButtonPropTypes.js
+++ b/src/components/HeaderWithBackButton/headerWithBackButtonPropTypes.js
@@ -31,12 +31,18 @@ const propTypes = {
/** Whether we should show a get assistance (question mark) button */
shouldShowGetAssistanceButton: PropTypes.bool,
+ /** Whether we should disable the get assistance button */
+ shouldDisableGetAssistanceButton: PropTypes.bool,
+
/** Whether we should show a pin button */
shouldShowPinButton: PropTypes.bool,
/** Whether we should show a more options (threedots) button */
shouldShowThreeDotsButton: PropTypes.bool,
+ /** Whether we should disable threedots button */
+ shouldDisableThreeDotsButton: PropTypes.bool,
+
/** List of menu items for more(three dots) menu */
threeDotsMenuItems: ThreeDotsMenuItemPropTypes,
@@ -84,6 +90,9 @@ const propTypes = {
/** Children to wrap in Header */
children: PropTypes.node,
+
+ /** Single execution function to prevent concurrent navigation actions */
+ singleExecution: PropTypes.func,
};
export default propTypes;
diff --git a/src/components/HeaderWithBackButton/index.js b/src/components/HeaderWithBackButton/index.js
index 6a02ce02237d..fc1f1a533ab7 100755
--- a/src/components/HeaderWithBackButton/index.js
+++ b/src/components/HeaderWithBackButton/index.js
@@ -18,6 +18,7 @@ import headerWithBackButtonPropTypes from './headerWithBackButtonPropTypes';
import useThrottledButtonState from '../../hooks/useThrottledButtonState';
import useLocalize from '../../hooks/useLocalize';
import useKeyboardState from '../../hooks/useKeyboardState';
+import useWaitForNavigation from '../../hooks/useWaitForNavigation';
function HeaderWithBackButton({
iconFill = undefined,
@@ -35,8 +36,10 @@ function HeaderWithBackButton({
shouldShowCloseButton = false,
shouldShowDownloadButton = false,
shouldShowGetAssistanceButton = false,
+ shouldDisableGetAssistanceButton = false,
shouldShowPinButton = false,
shouldShowThreeDotsButton = false,
+ shouldDisableThreeDotsButton = false,
stepCounter = null,
subtitle = '',
title = '',
@@ -49,10 +52,12 @@ function HeaderWithBackButton({
shouldEnableDetailPageNavigation = false,
children = null,
shouldOverlay = false,
+ singleExecution = (func) => func,
}) {
const [isDownloadButtonActive, temporarilyDisableDownloadButton] = useThrottledButtonState();
const {translate} = useLocalize();
const {isKeyboardShown} = useKeyboardState();
+ const waitForNavigate = useWaitForNavigation();
return (
Navigation.navigate(ROUTES.GET_ASSISTANCE.getRoute(guidesCallTaskID))}
+ disabled={shouldDisableGetAssistanceButton}
+ onPress={singleExecution(waitForNavigate(() => Navigation.navigate(ROUTES.GET_ASSISTANCE.getRoute(guidesCallTaskID))))}
style={[styles.touchableButtonImage]}
accessibilityRole="button"
accessibilityLabel={translate('getAssistancePage.questionMarkButtonTooltip')}
@@ -141,6 +147,7 @@ function HeaderWithBackButton({
{shouldShowPinButton && }
{shouldShowThreeDotsButton && (
))}
>
diff --git a/src/components/ThreeDotsMenu/index.js b/src/components/ThreeDotsMenu/index.js
index 3aac98fa1275..ab7ca57ed721 100644
--- a/src/components/ThreeDotsMenu/index.js
+++ b/src/components/ThreeDotsMenu/index.js
@@ -50,12 +50,16 @@ const propTypes = {
/** Whether the popover menu should overlay the current view */
shouldOverlay: PropTypes.bool,
+ /** Whether the menu is disabled */
+ disabled: PropTypes.bool,
+
/** Should we announce the Modal visibility changes? */
shouldSetModalVisibility: PropTypes.bool,
};
const defaultProps = {
iconTooltip: 'common.more',
+ disabled: false,
iconFill: undefined,
iconStyles: [],
icon: Expensicons.ThreeDots,
@@ -68,7 +72,7 @@ const defaultProps = {
shouldSetModalVisibility: true,
};
-function ThreeDotsMenu({iconTooltip, icon, iconFill, iconStyles, onIconPress, menuItems, anchorPosition, anchorAlignment, shouldOverlay, shouldSetModalVisibility}) {
+function ThreeDotsMenu({iconTooltip, icon, iconFill, iconStyles, onIconPress, menuItems, anchorPosition, anchorAlignment, shouldOverlay, shouldSetModalVisibility, disabled}) {
const [isPopupMenuVisible, setPopupMenuVisible] = useState(false);
const buttonRef = useRef(null);
const {translate} = useLocalize();
@@ -96,6 +100,7 @@ function ThreeDotsMenu({iconTooltip, icon, iconFill, iconStyles, onIconPress, me
onIconPress();
}
}}
+ disabled={disabled}
onMouseDown={(e) => {
/* Keep the focus state on mWeb like we did on the native apps. */
if (!Browser.isMobile()) {
diff --git a/src/pages/settings/AboutPage/AboutPage.js b/src/pages/settings/AboutPage/AboutPage.js
index 25b6197f87f8..36f088487469 100644
--- a/src/pages/settings/AboutPage/AboutPage.js
+++ b/src/pages/settings/AboutPage/AboutPage.js
@@ -1,5 +1,5 @@
import _ from 'underscore';
-import React from 'react';
+import React, {useRef, useMemo} from 'react';
import {ScrollView, View} from 'react-native';
import DeviceInfo from 'react-native-device-info';
import HeaderWithBackButton from '../../../components/HeaderWithBackButton';
@@ -13,7 +13,6 @@ import * as Expensicons from '../../../components/Icon/Expensicons';
import ScreenWrapper from '../../../components/ScreenWrapper';
import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize';
import withWindowDimensions, {windowDimensionsPropTypes} from '../../../components/withWindowDimensions';
-import MenuItem from '../../../components/MenuItem';
import Logo from '../../../../assets/images/new-expensify.svg';
import pkg from '../../../../package.json';
import * as Report from '../../../libs/actions/Report';
@@ -22,6 +21,8 @@ import compose from '../../../libs/compose';
import * as ReportActionContextMenu from '../../home/report/ContextMenu/ReportActionContextMenu';
import {CONTEXT_MENU_TYPES} from '../../home/report/ContextMenu/ContextMenuActions';
import * as Environment from '../../../libs/Environment/Environment';
+import MenuItemList from '../../../components/MenuItemList';
+import useWaitForNavigation from '../../../hooks/useWaitForNavigation';
const propTypes = {
...withLocalizePropTypes,
@@ -40,46 +41,57 @@ function getFlavor() {
}
function AboutPage(props) {
- let popoverAnchor;
- const menuItems = [
- {
- translationKey: 'initialSettingsPage.aboutPage.appDownloadLinks',
- icon: Expensicons.Link,
- action: () => {
- Navigation.navigate(ROUTES.SETTINGS_APP_DOWNLOAD_LINKS);
+ const {translate} = props;
+ const popoverAnchor = useRef(null);
+ const waitForNavigate = useWaitForNavigation();
+
+ const menuItems = useMemo(() => {
+ const baseMenuItems = [
+ {
+ translationKey: 'initialSettingsPage.aboutPage.appDownloadLinks',
+ icon: Expensicons.Link,
+ action: waitForNavigate(() => Navigation.navigate(ROUTES.SETTINGS_APP_DOWNLOAD_LINKS)),
+ },
+ {
+ translationKey: 'initialSettingsPage.aboutPage.viewKeyboardShortcuts',
+ icon: Expensicons.Keyboard,
+ action: waitForNavigate(() => Navigation.navigate(ROUTES.KEYBOARD_SHORTCUTS)),
},
- },
- {
- translationKey: 'initialSettingsPage.aboutPage.viewKeyboardShortcuts',
- icon: Expensicons.Keyboard,
- action: () => {
- Navigation.navigate(ROUTES.KEYBOARD_SHORTCUTS);
+ {
+ translationKey: 'initialSettingsPage.aboutPage.viewTheCode',
+ icon: Expensicons.Eye,
+ iconRight: Expensicons.NewWindow,
+ action: () => {
+ Link.openExternalLink(CONST.GITHUB_URL);
+ },
},
- },
- {
- translationKey: 'initialSettingsPage.aboutPage.viewTheCode',
- icon: Expensicons.Eye,
- iconRight: Expensicons.NewWindow,
- action: () => {
- Link.openExternalLink(CONST.GITHUB_URL);
+ {
+ translationKey: 'initialSettingsPage.aboutPage.viewOpenJobs',
+ icon: Expensicons.MoneyBag,
+ iconRight: Expensicons.NewWindow,
+ action: () => {
+ Link.openExternalLink(CONST.UPWORK_URL);
+ },
+ link: CONST.UPWORK_URL,
},
- link: CONST.GITHUB_URL,
- },
- {
- translationKey: 'initialSettingsPage.aboutPage.viewOpenJobs',
- icon: Expensicons.MoneyBag,
- iconRight: Expensicons.NewWindow,
- action: () => {
- Link.openExternalLink(CONST.UPWORK_URL);
+ {
+ translationKey: 'initialSettingsPage.aboutPage.reportABug',
+ icon: Expensicons.Bug,
+ action: waitForNavigate(Report.navigateToConciergeChat),
},
- link: CONST.UPWORK_URL,
- },
- {
- translationKey: 'initialSettingsPage.aboutPage.reportABug',
- icon: Expensicons.Bug,
- action: Report.navigateToConciergeChat,
- },
- ];
+ ];
+ return _.map(baseMenuItems, (item) => ({
+ key: item.translationKey,
+ title: translate(item.translationKey),
+ icon: item.icon,
+ iconRight: item.iconRight,
+ onPress: item.action,
+ shouldShowRightIcon: true,
+ onSecondaryInteraction: !_.isEmpty(item.link) ? (e) => ReportActionContextMenu.showContextMenu(CONTEXT_MENU_TYPES.LINK, e, item.link, popoverAnchor) : undefined,
+ ref: popoverAnchor,
+ shouldBlockSelection: Boolean(item.link),
+ }));
+ }, [translate, waitForNavigate]);
return (
{props.translate('initialSettingsPage.aboutPage.description')}
- {_.map(menuItems, (item) => (
-