Skip to content

Commit

Permalink
Merge pull request #103 from software-mansion-labs/poc/split-freeze-w…
Browse files Browse the repository at this point in the history
…rapper

Poc/split freeze wrapper
  • Loading branch information
WojtekBoman authored Oct 1, 2024
2 parents 8fff355 + 93e9233 commit 030b630
Show file tree
Hide file tree
Showing 11 changed files with 38 additions and 143 deletions.
10 changes: 0 additions & 10 deletions src/components/withPrepareCentralPaneScreen/index.native.tsx

This file was deleted.

3 changes: 2 additions & 1 deletion src/components/withPrepareCentralPaneScreen/index.tsx
Original file line number Diff line number Diff line change
@@ -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);
}
53 changes: 17 additions & 36 deletions src/libs/Navigation/AppNavigator/AuthScreens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';
Expand All @@ -53,21 +53,16 @@ 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';
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<ReactComponentModule>('../../../pages/home/report/ReportAttachments').default;
const loadValidateLoginPage = () => require<ReactComponentModule>('../../../pages/ValidateLoginPage').default;
Expand All @@ -81,6 +76,11 @@ const loadReportAvatar = () => require<ReactComponentModule>('../../../pages/Rep
const loadReceiptView = () => require<ReactComponentModule>('../../../pages/TransactionReceiptPage').default;
const loadWorkspaceJoinUser = () => require<ReactComponentModule>('@pages/workspace/WorkspaceJoinUserPage').default;

const loadReportSplitNavigator = withPrepareCentralPaneScreen(() => require<ReactComponentModule>('./Navigators/ReportsSplitNavigator').default);
const loadSettingsSplitNavigator = withPrepareCentralPaneScreen(() => require<ReactComponentModule>('./Navigators/SettingsSplitNavigator').default);
const loadWorkspaceSplitNavigator = withPrepareCentralPaneScreen(() => require<ReactComponentModule>('./Navigators/WorkspaceSplitNavigator').default);
const loadSearchPage = withPrepareCentralPaneScreen(() => require<ReactComponentModule>('@pages/Search/SearchPage').default);

function shouldOpenOnAdminRoom() {
const url = getCurrentUrl();
return url ? new URL(url).searchParams.get('openOnAdminRoom') === 'true' : false;
Expand All @@ -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,
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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 (
<ComposeProviders components={[OptionsListContextProvider, ActiveWorkspaceContextProvider, ReportIDsContextProvider, SearchContextProvider]}>
<View style={styles.rootNavigatorContainerStyles(shouldUseNarrowLayout)}>
Expand All @@ -417,19 +398,24 @@ function AuthScreens() {
<RootStack.Screen
name={NAVIGATORS.REPORTS_SPLIT_NAVIGATOR}
options={screenOptions.fullScreen}
component={ReportsSplitNavigator}
getComponent={loadReportSplitNavigator}
/>
<RootStack.Screen
name={NAVIGATORS.SETTINGS_SPLIT_NAVIGATOR}
options={screenOptions.fullScreen}
component={SettingsSplitNavigator}
getComponent={loadSettingsSplitNavigator}
/>
<RootStack.Screen
name={SCREENS.SEARCH.CENTRAL_PANE}
options={screenOptions.fullScreen}
component={SearchPage}
getComponent={loadSearchPage}
initialParams={{q: buildSearchQueryString()}}
/>
<RootStack.Screen
name={NAVIGATORS.WORKSPACE_SPLIT_NAVIGATOR}
options={screenOptions.fullScreen}
getComponent={loadWorkspaceSplitNavigator}
/>
<RootStack.Screen
name={SCREENS.VALIDATE_LOGIN}
options={{
Expand Down Expand Up @@ -506,11 +492,6 @@ function AuthScreens() {
component={RightModalNavigator}
listeners={modalScreenListenersWithCancelSearch}
/>
<RootStack.Screen
name={NAVIGATORS.WORKSPACE_SPLIT_NAVIGATOR}
options={screenOptions.fullScreen}
component={WorkspaceSplitNavigator}
/>
<RootStack.Screen
name={NAVIGATORS.LEFT_MODAL_NAVIGATOR}
options={screenOptions.leftModalNavigator}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import useThemeStyles from '@hooks/useThemeStyles';
import createSplitStackNavigator from '@libs/Navigation/AppNavigator/createSplitStackNavigator';
import getRootNavigatorScreenOptions from '@libs/Navigation/AppNavigator/getRootNavigatorScreenOptions';
import type {SettingsSplitNavigatorParamList} from '@libs/Navigation/types';
import withPrepareCentralPaneScreen from '@src/components/withPrepareCentralPaneScreen';
import SCREENS from '@src/SCREENS';
import type ReactComponentModule from '@src/types/utils/ReactComponentModule';

Expand All @@ -15,15 +14,15 @@ const loadInitialSettingsPage = () => require<ReactComponentModule>('../../../..
type Screens = Partial<Record<keyof SettingsSplitNavigatorParamList, () => React.ComponentType>>;

const CENTRAL_PANE_SETTINGS_SCREENS = {
[SCREENS.SETTINGS.WORKSPACES]: withPrepareCentralPaneScreen(() => require<ReactComponentModule>('../../../../pages/workspace/WorkspacesListPage').default),
[SCREENS.SETTINGS.PREFERENCES.ROOT]: withPrepareCentralPaneScreen(() => require<ReactComponentModule>('../../../../pages/settings/Preferences/PreferencesPage').default),
[SCREENS.SETTINGS.SECURITY]: withPrepareCentralPaneScreen(() => require<ReactComponentModule>('../../../../pages/settings/Security/SecuritySettingsPage').default),
[SCREENS.SETTINGS.PROFILE.ROOT]: withPrepareCentralPaneScreen(() => require<ReactComponentModule>('../../../../pages/settings/Profile/ProfilePage').default),
[SCREENS.SETTINGS.WALLET.ROOT]: withPrepareCentralPaneScreen(() => require<ReactComponentModule>('../../../../pages/settings/Wallet/WalletPage').default),
[SCREENS.SETTINGS.ABOUT]: withPrepareCentralPaneScreen(() => require<ReactComponentModule>('../../../../pages/settings/AboutPage/AboutPage').default),
[SCREENS.SETTINGS.TROUBLESHOOT]: withPrepareCentralPaneScreen(() => require<ReactComponentModule>('../../../../pages/settings/Troubleshoot/TroubleshootPage').default),
[SCREENS.SETTINGS.SAVE_THE_WORLD]: withPrepareCentralPaneScreen(() => require<ReactComponentModule>('../../../../pages/TeachersUnite/SaveTheWorldPage').default),
[SCREENS.SETTINGS.SUBSCRIPTION.ROOT]: withPrepareCentralPaneScreen(() => require<ReactComponentModule>('../../../../pages/settings/Subscription/SubscriptionSettingsPage').default),
[SCREENS.SETTINGS.WORKSPACES]: () => require<ReactComponentModule>('../../../../pages/workspace/WorkspacesListPage').default,
[SCREENS.SETTINGS.PREFERENCES.ROOT]: () => require<ReactComponentModule>('../../../../pages/settings/Preferences/PreferencesPage').default,
[SCREENS.SETTINGS.SECURITY]: () => require<ReactComponentModule>('../../../../pages/settings/Security/SecuritySettingsPage').default,
[SCREENS.SETTINGS.PROFILE.ROOT]: () => require<ReactComponentModule>('../../../../pages/settings/Profile/ProfilePage').default,
[SCREENS.SETTINGS.WALLET.ROOT]: () => require<ReactComponentModule>('../../../../pages/settings/Wallet/WalletPage').default,
[SCREENS.SETTINGS.ABOUT]: () => require<ReactComponentModule>('../../../../pages/settings/AboutPage/AboutPage').default,
[SCREENS.SETTINGS.TROUBLESHOOT]: () => require<ReactComponentModule>('../../../../pages/settings/Troubleshoot/TroubleshootPage').default,
[SCREENS.SETTINGS.SAVE_THE_WORLD]: () => require<ReactComponentModule>('../../../../pages/TeachersUnite/SaveTheWorldPage').default,
[SCREENS.SETTINGS.SUBSCRIPTION.ROOT]: () => require<ReactComponentModule>('../../../../pages/settings/Subscription/SubscriptionSettingsPage').default,
} satisfies Screens;

const Stack = createSplitStackNavigator<SettingsSplitNavigatorParamList>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -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 (
<NavigationContent>
<StackView
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
state={stateToRender}
state={state}
descriptors={descriptors}
navigation={navigation}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,28 @@
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 */
keepVisible?: boolean;
};

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<number | null>(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 <Freeze freeze={!isFocused && isScreenBlurred && !keepVisible}>{children}</Freeze>;
return <Freeze freeze={!isFocused && isBlurred && !keepVisible}>{children}</Freeze>;
}

FreezeWrapper.displayName = 'FreezeWrapper';
Expand Down
46 changes: 0 additions & 46 deletions src/libs/Navigation/FreezeWrapper/index.tsx

This file was deleted.

12 changes: 0 additions & 12 deletions src/libs/Navigation/shouldSetScreenBlurred/index.native.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/libs/Navigation/shouldSetScreenBlurred/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
4 changes: 2 additions & 2 deletions src/pages/settings/InitialSettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ function InitialSettingsPage({userWallet, bankAccountList, fundList, walletTerms
</View>
);
},
[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]);
Expand Down Expand Up @@ -427,7 +427,7 @@ function InitialSettingsPage({userWallet, bankAccountList, fundList, walletTerms
scrollEventThrottle={16}
contentContainerStyle={[styles.w100]}
showsVerticalScrollIndicator={false}
>
>
{accountMenuItems}
{workspaceMenuItems}
{generalMenuItems}
Expand Down
Loading

0 comments on commit 030b630

Please sign in to comment.