diff --git a/src/components/withPrepareCentralPaneScreen/index.native.tsx b/src/components/withPrepareCentralPaneScreen/index.native.tsx deleted file mode 100644 index 84ba31cd63fd..000000000000 --- a/src/components/withPrepareCentralPaneScreen/index.native.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import type React from 'react'; -import freezeScreenWithLazyLoading from '@libs/freezeScreenWithLazyLoading'; - -/** - * This higher-order function is dependent on the platform. On native platforms, screens that aren't already displayed in the navigation stack should be frozen to prevent unnecessary rendering. - * It's handled this way only on mobile platforms because on the web, more than one screen is displayed in a wide layout, so these screens shouldn't be frozen. - */ -export default function withPrepareCentralPaneScreen(lazyComponent: () => React.ComponentType) { - return freezeScreenWithLazyLoading(lazyComponent); -} diff --git a/src/components/withPrepareCentralPaneScreen/index.tsx b/src/components/withPrepareCentralPaneScreen/index.tsx index f53368188b3d..84ba31cd63fd 100644 --- a/src/components/withPrepareCentralPaneScreen/index.tsx +++ b/src/components/withPrepareCentralPaneScreen/index.tsx @@ -1,9 +1,10 @@ import type React from 'react'; +import freezeScreenWithLazyLoading from '@libs/freezeScreenWithLazyLoading'; /** * This higher-order function is dependent on the platform. On native platforms, screens that aren't already displayed in the navigation stack should be frozen to prevent unnecessary rendering. * It's handled this way only on mobile platforms because on the web, more than one screen is displayed in a wide layout, so these screens shouldn't be frozen. */ export default function withPrepareCentralPaneScreen(lazyComponent: () => React.ComponentType) { - return lazyComponent; + return freezeScreenWithLazyLoading(lazyComponent); } diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index 300f4119f992..ea08eefff015 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -9,6 +9,7 @@ import ComposeProviders from '@components/ComposeProviders'; import OptionsListContextProvider from '@components/OptionListContextProvider'; import {SearchContextProvider} from '@components/Search/SearchContext'; import SearchRouter from '@components/Search/SearchRouter/SearchRouter'; +import withPrepareCentralPaneScreen from '@components/withPrepareCentralPaneScreen'; import useActiveWorkspace from '@hooks/useActiveWorkspace'; import usePermissions from '@hooks/usePermissions'; import {ReportIDsContextProvider} from '@hooks/useReportIDs'; @@ -32,7 +33,6 @@ import {buildSearchQueryString} from '@libs/SearchUtils'; import * as SessionUtils from '@libs/SessionUtils'; import ConnectionCompletePage from '@pages/ConnectionCompletePage'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; -import SearchPage from '@pages/Search/SearchPage'; import DesktopSignInRedirectPage from '@pages/signin/DesktopSignInRedirectPage'; import * as App from '@userActions/App'; import * as Download from '@userActions/Download'; @@ -53,9 +53,7 @@ import SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; import type {SelectedTimezone, Timezone} from '@src/types/onyx/PersonalDetails'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; import type ReactComponentModule from '@src/types/utils/ReactComponentModule'; -import beforeRemoveReportOpenedFromSearchRHP from './beforeRemoveReportOpenedFromSearchRHP'; import createCustomStackNavigator from './createCustomStackNavigator'; import defaultScreenOptions from './defaultScreenOptions'; import getRootNavigatorScreenOptions from './getRootNavigatorScreenOptions'; @@ -63,11 +61,8 @@ import ExplanationModalNavigator from './Navigators/ExplanationModalNavigator'; import FeatureTrainingModalNavigator from './Navigators/FeatureTrainingModalNavigator'; import LeftModalNavigator from './Navigators/LeftModalNavigator'; import OnboardingModalNavigator from './Navigators/OnboardingModalNavigator'; -import ReportsSplitNavigator from './Navigators/ReportsSplitNavigator'; import RightModalNavigator from './Navigators/RightModalNavigator'; -import SettingsSplitNavigator from './Navigators/SettingsSplitNavigator'; import WelcomeVideoModalNavigator from './Navigators/WelcomeVideoModalNavigator'; -import WorkspaceSplitNavigator from './Navigators/WorkspaceSplitNavigator'; const loadReportAttachments = () => require('../../../pages/home/report/ReportAttachments').default; const loadValidateLoginPage = () => require('../../../pages/ValidateLoginPage').default; @@ -81,6 +76,11 @@ const loadReportAvatar = () => require('../../../pages/Rep const loadReceiptView = () => require('../../../pages/TransactionReceiptPage').default; const loadWorkspaceJoinUser = () => require('@pages/workspace/WorkspaceJoinUserPage').default; +const loadReportSplitNavigator = withPrepareCentralPaneScreen(() => require('./Navigators/ReportsSplitNavigator').default); +const loadSettingsSplitNavigator = withPrepareCentralPaneScreen(() => require('./Navigators/SettingsSplitNavigator').default); +const loadWorkspaceSplitNavigator = withPrepareCentralPaneScreen(() => require('./Navigators/WorkspaceSplitNavigator').default); +const loadSearchPage = withPrepareCentralPaneScreen(() => require('@pages/Search/SearchPage').default); + function shouldOpenOnAdminRoom() { const url = getCurrentUrl(); return url ? new URL(url).searchParams.get('openOnAdminRoom') === 'true' : false; @@ -103,14 +103,6 @@ function getCentralPaneScreenInitialParams(screenName: CentralPaneName, initialR return undefined; } -function getCentralPaneScreenListeners(screenName: CentralPaneName) { - if (screenName === SCREENS.REPORT) { - return {beforeRemove: beforeRemoveReportOpenedFromSearchRHP}; - } - - return {}; -} - function initializePusher() { return Pusher.init({ appKey: CONFIG.PUSHER.APP_KEY, @@ -218,9 +210,9 @@ const modalScreenListenersWithCancelSearch = { }; function AuthScreens() { - const [session, sessionStatus] = useOnyx(ONYXKEYS.SESSION); - const [lastOpenedPublicRoomID, lastOpenedPublicRoomIDStatus] = useOnyx(ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID); - const [initialLastUpdateIDAppliedToClient, initialLastUpdateIDAppliedToClientStatus] = useOnyx(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT); + const [session] = useOnyx(ONYXKEYS.SESSION); + const [lastOpenedPublicRoomID] = useOnyx(ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID); + const [initialLastUpdateIDAppliedToClient] = useOnyx(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const {shouldUseNarrowLayout, onboardingIsMediumOrLargerScreenWidth, isSmallScreenWidth} = useResponsiveLayout(); @@ -395,17 +387,6 @@ function AuthScreens() { // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps }, []); - const CentralPaneScreenOptions = { - headerShown: false, - title: 'New Expensify', - - // Prevent unnecessary scrolling - cardStyle: styles.cardStyleNavigator, - }; - if (isLoadingOnyxValue(sessionStatus, lastOpenedPublicRoomIDStatus, initialLastUpdateIDAppliedToClientStatus)) { - return; - } - return ( @@ -417,19 +398,24 @@ function AuthScreens() { + - require('../../../.. type Screens = Partial React.ComponentType>>; const CENTRAL_PANE_SETTINGS_SCREENS = { - [SCREENS.SETTINGS.WORKSPACES]: withPrepareCentralPaneScreen(() => require('../../../../pages/workspace/WorkspacesListPage').default), - [SCREENS.SETTINGS.PREFERENCES.ROOT]: withPrepareCentralPaneScreen(() => require('../../../../pages/settings/Preferences/PreferencesPage').default), - [SCREENS.SETTINGS.SECURITY]: withPrepareCentralPaneScreen(() => require('../../../../pages/settings/Security/SecuritySettingsPage').default), - [SCREENS.SETTINGS.PROFILE.ROOT]: withPrepareCentralPaneScreen(() => require('../../../../pages/settings/Profile/ProfilePage').default), - [SCREENS.SETTINGS.WALLET.ROOT]: withPrepareCentralPaneScreen(() => require('../../../../pages/settings/Wallet/WalletPage').default), - [SCREENS.SETTINGS.ABOUT]: withPrepareCentralPaneScreen(() => require('../../../../pages/settings/AboutPage/AboutPage').default), - [SCREENS.SETTINGS.TROUBLESHOOT]: withPrepareCentralPaneScreen(() => require('../../../../pages/settings/Troubleshoot/TroubleshootPage').default), - [SCREENS.SETTINGS.SAVE_THE_WORLD]: withPrepareCentralPaneScreen(() => require('../../../../pages/TeachersUnite/SaveTheWorldPage').default), - [SCREENS.SETTINGS.SUBSCRIPTION.ROOT]: withPrepareCentralPaneScreen(() => require('../../../../pages/settings/Subscription/SubscriptionSettingsPage').default), + [SCREENS.SETTINGS.WORKSPACES]: () => require('../../../../pages/workspace/WorkspacesListPage').default, + [SCREENS.SETTINGS.PREFERENCES.ROOT]: () => require('../../../../pages/settings/Preferences/PreferencesPage').default, + [SCREENS.SETTINGS.SECURITY]: () => require('../../../../pages/settings/Security/SecuritySettingsPage').default, + [SCREENS.SETTINGS.PROFILE.ROOT]: () => require('../../../../pages/settings/Profile/ProfilePage').default, + [SCREENS.SETTINGS.WALLET.ROOT]: () => require('../../../../pages/settings/Wallet/WalletPage').default, + [SCREENS.SETTINGS.ABOUT]: () => require('../../../../pages/settings/AboutPage/AboutPage').default, + [SCREENS.SETTINGS.TROUBLESHOOT]: () => require('../../../../pages/settings/Troubleshoot/TroubleshootPage').default, + [SCREENS.SETTINGS.SAVE_THE_WORLD]: () => require('../../../../pages/TeachersUnite/SaveTheWorldPage').default, + [SCREENS.SETTINGS.SUBSCRIPTION.ROOT]: () => require('../../../../pages/settings/Subscription/SubscriptionSettingsPage').default, } satisfies Screens; const Stack = createSplitStackNavigator(); diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx index af4407af6dc2..8c98002e5c7b 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx @@ -2,7 +2,7 @@ import type {ParamListBase, StackActionHelpers, StackNavigationState} from '@rea import {createNavigatorFactory, useNavigationBuilder} from '@react-navigation/native'; import type {StackNavigationEventMap, StackNavigationOptions} from '@react-navigation/stack'; import {StackView} from '@react-navigation/stack'; -import React, {useMemo} from 'react'; +import React from 'react'; import CustomRouter from './CustomRouter'; import type {ResponsiveStackNavigatorProps, ResponsiveStackNavigatorRouterOptions} from './types'; @@ -20,21 +20,12 @@ function ResponsiveStackNavigator(props: ResponsiveStackNavigatorProps) { initialRouteName: props.initialRouteName, }); - const stateToRender = useMemo(() => { - const routes = state.routes.slice(-3); - return { - ...state, - routes, - index: routes.length - 1, - }; - }, [state]); - return ( diff --git a/src/libs/Navigation/FreezeWrapper/index.native.tsx b/src/libs/Navigation/FreezeWrapper.tsx similarity index 59% rename from src/libs/Navigation/FreezeWrapper/index.native.tsx rename to src/libs/Navigation/FreezeWrapper.tsx index b071a065bd31..aa6e302cdbd0 100644 --- a/src/libs/Navigation/FreezeWrapper/index.native.tsx +++ b/src/libs/Navigation/FreezeWrapper.tsx @@ -1,8 +1,8 @@ import {useIsFocused, useNavigation, useRoute} from '@react-navigation/native'; -import React, {useEffect, useRef, useState} from 'react'; +import React, {useEffect, useRef} from 'react'; import {Freeze} from 'react-freeze'; -import shouldSetScreenBlurred from '@libs/Navigation/shouldSetScreenBlurred'; import type ChildrenProps from '@src/types/utils/ChildrenProps'; +import shouldSetScreenBlurred from './shouldSetScreenBlurred'; type FreezeWrapperProps = ChildrenProps & { /** Prop to disable freeze */ @@ -10,28 +10,19 @@ type FreezeWrapperProps = ChildrenProps & { }; function FreezeWrapper({keepVisible = false, children}: FreezeWrapperProps) { - const [isScreenBlurred, setIsScreenBlurred] = useState(false); // we need to know the screen index to determine if the screen can be frozen const screenIndexRef = useRef(null); const isFocused = useIsFocused(); const navigation = useNavigation(); const currentRoute = useRoute(); - + const isBlurred = shouldSetScreenBlurred((navigation.getState()?.index ?? 0) - (screenIndexRef.current ?? 0)); useEffect(() => { const index = navigation.getState()?.routes.findIndex((route) => route.key === currentRoute.key) ?? 0; screenIndexRef.current = index; // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps }, []); - useEffect(() => { - const unsubscribe = navigation.addListener('state', () => { - const navigationIndex = (navigation.getState()?.index ?? 0) - (screenIndexRef.current ?? 0); - setIsScreenBlurred(shouldSetScreenBlurred(navigationIndex)); - }); - return () => unsubscribe(); - }, [isFocused, isScreenBlurred, navigation]); - - return {children}; + return {children}; } FreezeWrapper.displayName = 'FreezeWrapper'; diff --git a/src/libs/Navigation/FreezeWrapper/index.tsx b/src/libs/Navigation/FreezeWrapper/index.tsx deleted file mode 100644 index 7219666b1b18..000000000000 --- a/src/libs/Navigation/FreezeWrapper/index.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import {useIsFocused, useNavigation, useRoute} from '@react-navigation/native'; -import React, {useEffect, useLayoutEffect, useRef, useState} from 'react'; -import {Freeze} from 'react-freeze'; -import shouldSetScreenBlurred from '@libs/Navigation/shouldSetScreenBlurred'; -import type ChildrenProps from '@src/types/utils/ChildrenProps'; - -type FreezeWrapperProps = ChildrenProps & { - /** Prop to disable freeze */ - keepVisible?: boolean; -}; - -function FreezeWrapper({keepVisible = false, children}: FreezeWrapperProps) { - const [isScreenBlurred, setIsScreenBlurred] = useState(false); - const [freezed, setFreezed] = useState(false); - // we need to know the screen index to determine if the screen can be frozen - const screenIndexRef = useRef(null); - const isFocused = useIsFocused(); - const navigation = useNavigation(); - const currentRoute = useRoute(); - - useEffect(() => { - const index = navigation.getState()?.routes.findIndex((route) => route.key === currentRoute.key) ?? 0; - screenIndexRef.current = index; - // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps - }, []); - - useEffect(() => { - const unsubscribe = navigation.addListener('state', () => { - const navigationIndex = (navigation.getState()?.index ?? 0) - (screenIndexRef.current ?? 0); - setIsScreenBlurred(shouldSetScreenBlurred(navigationIndex)); - }); - return () => unsubscribe(); - }, [isFocused, isScreenBlurred, navigation]); - - // Decouple the Suspense render task so it won't be interuptted by React's concurrent mode - // and stuck in an infinite loop - useLayoutEffect(() => { - setFreezed(!isFocused && isScreenBlurred && !keepVisible); - }, [isFocused, isScreenBlurred, keepVisible]); - - return {children}; -} - -FreezeWrapper.displayName = 'FreezeWrapper'; - -export default FreezeWrapper; diff --git a/src/libs/Navigation/shouldSetScreenBlurred/index.native.tsx b/src/libs/Navigation/shouldSetScreenBlurred/index.native.tsx deleted file mode 100644 index 4043fddb7372..000000000000 --- a/src/libs/Navigation/shouldSetScreenBlurred/index.native.tsx +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @param navigationIndex - * - * Decides whether to set screen to blurred state. - * - * If the screen is more than 1 screen away from the current screen, freeze it, - * we don't want to freeze the screen if it's the previous screen because the freeze placeholder - * would be visible at the beginning of the back animation then - */ -const shouldSetScreenBlurred = (navigationIndex: number) => navigationIndex > 1; - -export default shouldSetScreenBlurred; diff --git a/src/libs/Navigation/shouldSetScreenBlurred/index.tsx b/src/libs/Navigation/shouldSetScreenBlurred/index.tsx index 14b45921bdb2..2461187046d8 100644 --- a/src/libs/Navigation/shouldSetScreenBlurred/index.tsx +++ b/src/libs/Navigation/shouldSetScreenBlurred/index.tsx @@ -8,6 +8,6 @@ * LHN, we have FlashList rendering in the back while we are on * Settings screen. */ -const shouldSetScreenBlurred = (navigationIndex: number) => navigationIndex >= 1; +const shouldSetScreenBlurred = (navigationIndex: number) => navigationIndex > 1; export default shouldSetScreenBlurred; diff --git a/src/pages/settings/InitialSettingsPage.tsx b/src/pages/settings/InitialSettingsPage.tsx index 9a7469325087..49e74a8ac06d 100755 --- a/src/pages/settings/InitialSettingsPage.tsx +++ b/src/pages/settings/InitialSettingsPage.tsx @@ -350,7 +350,7 @@ function InitialSettingsPage({userWallet, bankAccountList, fundList, walletTerms ); }, - [styles.pb4, styles.mh3, styles.sectionTitle, styles.sectionMenuItem, translate, userWallet?.currentBalance, isExecuting, singleExecution, waitForNavigate], + [styles.pb4, styles.mh3, styles.sectionTitle, styles.sectionMenuItem, translate, userWallet?.currentBalance, isExecuting, singleExecution, activeRoute, waitForNavigate], ); const accountMenuItems = useMemo(() => getMenuItemsSection(accountMenuItemsData), [accountMenuItemsData, getMenuItemsSection]); @@ -427,7 +427,7 @@ function InitialSettingsPage({userWallet, bankAccountList, fundList, walletTerms scrollEventThrottle={16} contentContainerStyle={[styles.w100]} showsVerticalScrollIndicator={false} - > + > {accountMenuItems} {workspaceMenuItems} {generalMenuItems} diff --git a/src/pages/workspace/WorkspacesListPage.tsx b/src/pages/workspace/WorkspacesListPage.tsx index caf19a95cfea..a5212424b03b 100755 --- a/src/pages/workspace/WorkspacesListPage.tsx +++ b/src/pages/workspace/WorkspacesListPage.tsx @@ -107,7 +107,7 @@ function WorkspacesListPage() { const styles = useThemeStyles(); const {translate} = useLocalize(); const {isOffline} = useNetwork(); - const {shouldUseNarrowLayout, isSmallScreenWidth, isMediumScreenWidth} = useResponsiveLayout(); + const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout(); const [allConnectionSyncProgresses] = useOnyx(ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS); const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY); const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);