diff --git a/src/Expensify.tsx b/src/Expensify.tsx index 0afde4a09222b..234f23d410808 100644 --- a/src/Expensify.tsx +++ b/src/Expensify.tsx @@ -4,29 +4,22 @@ import React, {useCallback, useEffect, useLayoutEffect, useRef, useState} from ' import type {NativeEventSubscription} from 'react-native'; import {AppState, Platform} from 'react-native'; import Onyx from 'react-native-onyx'; -import DelegateNoAccessModalProvider from './components/DelegateNoAccessModalProvider'; -import EmojiPicker from './components/EmojiPicker/EmojiPicker'; -import GrowlNotification from './components/GrowlNotification'; import {useInitialURLActions} from './components/InitialURLContextProvider'; -import ProactiveAppReviewModalManager from './components/ProactiveAppReviewModalManager'; -import ScreenShareRequestModal from './components/ScreenShareRequestModal'; import AppleAuthWrapper from './components/SignInButtons/AppleAuthWrapper'; import SplashScreenHider from './components/SplashScreenHider'; -import UpdateAppModal from './components/UpdateAppModal'; import CONFIG from './CONFIG'; import CONST from './CONST'; import DeepLinkHandler from './DeepLinkHandler'; import DelegateAccessHandler from './DelegateAccessHandler'; import FullstoryInitHandler from './FullstoryInitHandler'; +import GlobalModals from './GlobalModals'; import useDebugShortcut from './hooks/useDebugShortcut'; import useIsAuthenticated from './hooks/useIsAuthenticated'; import useLocalize from './hooks/useLocalize'; import useOnyx from './hooks/useOnyx'; import {updateLastRoute} from './libs/actions/App'; -import * as EmojiPickerAction from './libs/actions/EmojiPickerAction'; import * as ActiveClientManager from './libs/ActiveClientManager'; import {isSafari} from './libs/Browser'; -import {growlRef} from './libs/Growl'; import Log from './libs/Log'; import migrateOnyx from './libs/migrateOnyx'; import Navigation from './libs/Navigation/Navigation'; @@ -37,8 +30,6 @@ import {endSpan, getSpan, startSpan} from './libs/telemetry/activeSpans'; import {cleanupMemoryTrackingTelemetry, initializeMemoryTrackingTelemetry} from './libs/telemetry/TelemetrySynchronizer'; import Visibility from './libs/Visibility'; import ONYXKEYS from './ONYXKEYS'; -import PopoverReportActionContextMenu from './pages/inbox/report/ContextMenu/PopoverReportActionContextMenu'; -import * as ReportActionContextMenu from './pages/inbox/report/ContextMenu/ReportActionContextMenu'; import PriorityModeHandler from './PriorityModeHandler'; import type {Route} from './ROUTES'; import {accountIDSelector} from './selectors/Session'; @@ -66,7 +57,6 @@ function Expensify() { const [accountID] = useOnyx(ONYXKEYS.SESSION, {selector: accountIDSelector}); const [lastRoute] = useOnyx(ONYXKEYS.LAST_ROUTE); const [isCheckingPublicRoom = true] = useOnyx(ONYXKEYS.IS_CHECKING_PUBLIC_ROOM, {initWithStoredValues: false}); - const [updateAvailable] = useOnyx(ONYXKEYS.UPDATE_AVAILABLE, {initWithStoredValues: false}); const [updateRequired] = useOnyx(ONYXKEYS.UPDATE_REQUIRED, {initWithStoredValues: false}); const [lastVisitedPath] = useOnyx(ONYXKEYS.LAST_VISITED_PATH); @@ -223,7 +213,6 @@ function Expensify() { const propsToLog = { isCheckingPublicRoom, updateRequired, - updateAvailable, isAuthenticated, lastVisitedPath, }; @@ -282,21 +271,7 @@ function Expensify() { return ( <> - {shouldInit && ( - <> - - - - - - {/* We include the modal for showing a new update at the top level so the option is always present. */} - {updateAvailable && !updateRequired ? : null} - {/* Proactive app review modal shown when user has completed a trigger action */} - - - - )} - + {shouldInit && } diff --git a/src/GlobalModals.tsx b/src/GlobalModals.tsx new file mode 100644 index 0000000000000..b5b2b322ba1da --- /dev/null +++ b/src/GlobalModals.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import DelegateNoAccessModalProvider from './components/DelegateNoAccessModalProvider'; +import EmojiPicker from './components/EmojiPicker/EmojiPicker'; +import GrowlNotification from './components/GrowlNotification'; +import ProactiveAppReviewModalManager from './components/ProactiveAppReviewModalManager'; +import ScreenShareRequestModal from './components/ScreenShareRequestModal'; +import UpdateAppModal from './components/UpdateAppModal'; +import * as EmojiPickerAction from './libs/actions/EmojiPickerAction'; +import {growlRef} from './libs/Growl'; +import PopoverReportActionContextMenu from './pages/inbox/report/ContextMenu/PopoverReportActionContextMenu'; +import * as ReportActionContextMenu from './pages/inbox/report/ContextMenu/ReportActionContextMenu'; + +/** + * Renders global modals and overlays that are mounted once at the top level. + */ +function GlobalModals() { + return ( + <> + + {/* Those below are only available to the authenticated user. */} + + + {/* eslint-disable-next-line react-hooks/refs -- module-level createRef, safe to pass as ref prop */} + + + {/* eslint-disable-next-line react-hooks/refs -- module-level createRef, safe to pass as ref prop */} + + {/* Proactive app review modal shown when user has completed a trigger action */} + + + + ); +} + +export default GlobalModals; diff --git a/src/components/UpdateAppModal/BaseUpdateAppModal.tsx b/src/components/UpdateAppModal.tsx similarity index 53% rename from src/components/UpdateAppModal/BaseUpdateAppModal.tsx rename to src/components/UpdateAppModal.tsx index 2f01f4ff72e09..b0f4e4a488994 100755 --- a/src/components/UpdateAppModal/BaseUpdateAppModal.tsx +++ b/src/components/UpdateAppModal.tsx @@ -1,17 +1,19 @@ import React, {useState} from 'react'; -import ConfirmModal from '@components/ConfirmModal'; import useLocalize from '@hooks/useLocalize'; -import type UpdateAppModalProps from './types'; +import useOnyx from '@hooks/useOnyx'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ConfirmModal from './ConfirmModal'; -function BaseUpdateAppModal({onSubmit}: UpdateAppModalProps) { +function UpdateAppModal() { const [isModalOpen, setIsModalOpen] = useState(true); const {translate} = useLocalize(); + const [updateAvailable] = useOnyx(ONYXKEYS.UPDATE_AVAILABLE, {initWithStoredValues: false}); - /** - * Execute the onSubmit callback and close the modal. - */ - const submitAndClose = () => { - onSubmit?.(); + if (!updateAvailable) { + return null; + } + + const handleClose = () => { setIsModalOpen(false); }; @@ -19,8 +21,8 @@ function BaseUpdateAppModal({onSubmit}: UpdateAppModalProps) { setIsModalOpen(false)} + onConfirm={handleClose} + onCancel={handleClose} prompt={translate('baseUpdateAppModal.updatePrompt')} confirmText={translate('baseUpdateAppModal.updateApp')} cancelText={translate('common.cancel')} @@ -28,6 +30,4 @@ function BaseUpdateAppModal({onSubmit}: UpdateAppModalProps) { ); } -BaseUpdateAppModal.displayName = 'BaseUpdateAppModal'; - -export default React.memo(BaseUpdateAppModal); +export default UpdateAppModal; diff --git a/src/components/UpdateAppModal/index.tsx b/src/components/UpdateAppModal/index.tsx deleted file mode 100644 index 654f1cfbf03cd..0000000000000 --- a/src/components/UpdateAppModal/index.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react'; -import BaseUpdateAppModal from './BaseUpdateAppModal'; -import type UpdateAppModalProps from './types'; - -function UpdateAppModal(props: UpdateAppModalProps) { - return ( - - ); -} - -export default UpdateAppModal; diff --git a/src/components/UpdateAppModal/types.ts b/src/components/UpdateAppModal/types.ts deleted file mode 100644 index ae57de671db63..0000000000000 --- a/src/components/UpdateAppModal/types.ts +++ /dev/null @@ -1,6 +0,0 @@ -type UpdateAppModalProps = { - /** Callback to fire when we want to trigger the update. */ - onSubmit?: () => void; -}; - -export default UpdateAppModalProps;