Skip to content

Commit

Permalink
Merge pull request #142 from software-mansion-labs/poc/bottom-tab-cle…
Browse files Browse the repository at this point in the history
…anups

Poc/bottom tab cleanups
  • Loading branch information
WojtekBoman authored Dec 11, 2024
2 parents 2e212a7 + 0ae4aac commit 7345d80
Show file tree
Hide file tree
Showing 115 changed files with 525 additions and 1,114 deletions.
1 change: 0 additions & 1 deletion src/NAVIGATORS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* */
export default {
CENTRAL_PANE_NAVIGATOR: 'CentralPaneNavigator',
BOTTOM_TAB_NAVIGATOR: 'BottomTabNavigator',
LEFT_MODAL_NAVIGATOR: 'LeftModalNavigator',
RIGHT_MODAL_NAVIGATOR: 'RightModalNavigator',
ONBOARDING_MODAL_NAVIGATOR: 'OnboardingModalNavigator',
Expand Down
1 change: 0 additions & 1 deletion src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ const SCREENS = {
SAVED_SEARCH_RENAME_RHP: 'Search_Saved_Search_Rename_RHP',
ADVANCED_FILTERS_IN_RHP: 'Search_Advanced_Filters_In_RHP',
TRANSACTION_HOLD_REASON_RHP: 'Search_Transaction_Hold_Reason_RHP',
BOTTOM_TAB: 'Search_Bottom_Tab',
},
SETTINGS: {
ROOT: 'Settings_Root',
Expand Down
2 changes: 1 addition & 1 deletion src/components/DeeplinkWrapper/index.website.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {Str} from 'expensify-common';
import {useEffect, useRef, useState} from 'react';
import * as Browser from '@libs/Browser';
import {shouldPreventDeeplinkPrompt} from '@libs/Navigation/helpers';
import Navigation from '@libs/Navigation/Navigation';
import navigationRef from '@libs/Navigation/navigationRef';
import shouldPreventDeeplinkPrompt from '@libs/Navigation/shouldPreventDeeplinkPrompt';
import * as App from '@userActions/App';
import * as Link from '@userActions/Link';
import * as Session from '@userActions/Session';
Expand Down
6 changes: 0 additions & 6 deletions src/components/FocusTrap/BOTTOM_TAB_SCREENS.ts

This file was deleted.

4 changes: 2 additions & 2 deletions src/components/FocusTrap/FocusTrapForScreen/index.web.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {useIsFocused, useRoute} from '@react-navigation/native';
import FocusTrap from 'focus-trap-react';
import React, {useMemo} from 'react';
import BOTTOM_TAB_SCREENS from '@components/FocusTrap/BOTTOM_TAB_SCREENS';
import sharedTrapStack from '@components/FocusTrap/sharedTrapStack';
import TOP_TAB_SCREENS from '@components/FocusTrap/TOP_TAB_SCREENS';
import WIDE_LAYOUT_INACTIVE_SCREENS from '@components/FocusTrap/WIDE_LAYOUT_INACTIVE_SCREENS';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import {isSidebarScreenName} from '@libs/Navigation/helpers';
import CONST from '@src/CONST';
import type FocusTrapProps from './FocusTrapProps';

Expand All @@ -19,7 +19,7 @@ function FocusTrapForScreen({children, focusTrapSettings}: FocusTrapProps) {
return focusTrapSettings.active;
}
// Focus trap can't be active on bottom tab screens because it would block access to the tab bar.
if (BOTTOM_TAB_SCREENS.find((screen) => screen === route.name)) {
if (isSidebarScreenName(route.name)) {
return false;
}

Expand Down
2 changes: 0 additions & 2 deletions src/components/FocusTrap/WIDE_LAYOUT_INACTIVE_SCREENS.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import NAVIGATORS from '@src/NAVIGATORS';
import SCREENS from '@src/SCREENS';

/**
* Screens displayed in the BottomTab and CentralPane displayed side by side that should not have active
* focus trap when rendered on a wide screen to allow navigation between them using the keyboard
*/
const WIDE_LAYOUT_INACTIVE_SCREENS: string[] = [
NAVIGATORS.BOTTOM_TAB_NAVIGATOR,
SCREENS.HOME,
SCREENS.SETTINGS.ROOT,
SCREENS.REPORT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@ import Text from '@components/Text';
import useCurrentReportID from '@hooks/useCurrentReportID';
import useStyleUtils from '@hooks/useStyleUtils';
import useThemeStyles from '@hooks/useThemeStyles';
import getTopmostCentralPaneRoute from '@libs/Navigation/getTopmostCentralPaneRoute';
import type {RootStackParamList, State} from '@libs/Navigation/types';
import Navigation, {navigationRef} from '@navigation/Navigation';
import isSearchTopmostFullScreenRoute from '@libs/Navigation/helpers/isSearchTopmostFullScreenRoute';
import Navigation from '@navigation/Navigation';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {Route} from '@src/ROUTES';
import SCREENS from '@src/SCREENS';
import ROUTES from '@src/ROUTES';
import type {Report} from '@src/types/onyx';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import MentionReportContext from './MentionReportContext';
Expand Down Expand Up @@ -74,9 +72,8 @@ function MentionReportRenderer({style, tnode, TDefaultRenderer, ...defaultRender
const {reportID, mentionDisplayText} = mentionDetails;

let navigationRoute: Route | undefined = reportID ? ROUTES.REPORT_WITH_ID.getRoute(reportID) : undefined;
const topmostCentralPaneRoute = getTopmostCentralPaneRoute(navigationRef.getRootState() as State<RootStackParamList>);
const backTo = Navigation.getActiveRoute();
if (topmostCentralPaneRoute?.name === SCREENS.SEARCH.CENTRAL_PANE) {
if (isSearchTopmostFullScreenRoute()) {
navigationRoute = reportID ? ROUTES.SEARCH_REPORT.getRoute({reportID, backTo}) : undefined;
}
const isCurrentRoomMention = reportID === currentReportIDValue;
Expand Down
2 changes: 1 addition & 1 deletion src/components/Lottie/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import useAppState from '@hooks/useAppState';
import useNetwork from '@hooks/useNetwork';
import useThemeStyles from '@hooks/useThemeStyles';
import * as Browser from '@libs/Browser';
import isSideModalNavigator from '@libs/Navigation/isSideModalNavigator';
import isSideModalNavigator from '@libs/Navigation/helpers/isSideModalNavigator';
import CONST from '@src/CONST';
import {useSplashScreenStateContext} from '@src/SplashScreenStateContext';

Expand Down
9 changes: 3 additions & 6 deletions src/components/PromotedActionsBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@ import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import * as HeaderUtils from '@libs/HeaderUtils';
import * as Localize from '@libs/Localize';
import getTopmostCentralPaneRoute from '@libs/Navigation/getTopmostCentralPaneRoute';
import Navigation, {navigationRef} from '@libs/Navigation/Navigation';
import type {RootStackParamList, State} from '@libs/Navigation/types';
import isSearchTopmostFullScreenRoute from '@libs/Navigation/helpers/isSearchTopmostFullScreenRoute';
import Navigation from '@libs/Navigation/Navigation';
import * as ReportUtils from '@libs/ReportUtils';
import * as ReportActions from '@userActions/Report';
import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';
import SCREENS from '@src/SCREENS';
import type {ReportAction} from '@src/types/onyx';
import type OnyxReport from '@src/types/onyx/Report';
import Button from './Button';
Expand Down Expand Up @@ -93,9 +91,8 @@ const PromotedActions = {
Navigation.goBack();
}
const targetedReportID = reportID ?? reportAction?.childReportID ?? '';
const topmostCentralPaneRoute = getTopmostCentralPaneRoute(navigationRef.getRootState() as State<RootStackParamList>);

if (topmostCentralPaneRoute?.name !== SCREENS.SEARCH.CENTRAL_PANE && isTextHold) {
if (isSearchTopmostFullScreenRoute() && isTextHold) {
ReportUtils.changeMoneyRequestHoldStatus(reportAction, ROUTES.REPORT_WITH_ID.getRoute(targetedReportID));
return;
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/ScreenWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as Browser from '@libs/Browser';
import type {PlatformStackNavigationProp} from '@libs/Navigation/PlatformStackNavigation/types';
import type {AuthScreensParamList, RootStackParamList} from '@libs/Navigation/types';
import type {ReportsSplitNavigatorParamList, RootStackParamList} from '@libs/Navigation/types';
import toggleTestToolsModal from '@userActions/TestTool';
import CONST from '@src/CONST';
import CustomDevMenu from './CustomDevMenu';
Expand Down Expand Up @@ -99,7 +99,7 @@ type ScreenWrapperProps = {
*
* This is required because transitionEnd event doesn't trigger in the testing environment.
*/
navigation?: PlatformStackNavigationProp<RootStackParamList> | PlatformStackNavigationProp<AuthScreensParamList>;
navigation?: PlatformStackNavigationProp<RootStackParamList> | PlatformStackNavigationProp<ReportsSplitNavigatorParamList>;

/** Whether to show offline indicator on wide screens */
shouldShowOfflineIndicatorInWideScreen?: boolean;
Expand Down
15 changes: 6 additions & 9 deletions src/components/ScrollOffsetContextProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import type {ParamListBase} from '@react-navigation/native';
import React, {createContext, useCallback, useEffect, useMemo, useRef} from 'react';
import {withOnyx} from 'react-native-onyx';
import usePrevious from '@hooks/usePrevious';
import {isSidebarScreenName} from '@libs/Navigation/helpers';
import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types';
import type {NavigationPartialRoute, State} from '@libs/Navigation/types';
import NAVIGATORS from '@src/NAVIGATORS';
import ONYXKEYS from '@src/ONYXKEYS';
import SCREENS from '@src/SCREENS';
import type {PriorityMode} from '@src/types/onyx';
Expand Down Expand Up @@ -75,14 +75,11 @@ function ScrollOffsetContextProvider({children, priorityMode}: ScrollOffsetConte
}, []);

const cleanStaleScrollOffsets: ScrollOffsetContextValue['cleanStaleScrollOffsets'] = useCallback((state) => {
const bottomTabNavigator = state.routes.find((route) => route.name === NAVIGATORS.BOTTOM_TAB_NAVIGATOR);
if (bottomTabNavigator?.state && 'routes' in bottomTabNavigator.state) {
const bottomTabNavigatorRoutes = bottomTabNavigator.state.routes;
const scrollOffsetkeysOfExistingScreens = bottomTabNavigatorRoutes.map((route) => getKey(route));
for (const key of Object.keys(scrollOffsetsRef.current)) {
if (!scrollOffsetkeysOfExistingScreens.includes(key)) {
delete scrollOffsetsRef.current[key];
}
const sidebarRoutes = state.routes.filter((route) => isSidebarScreenName(route.name));
const scrollOffsetkeysOfExistingScreens = sidebarRoutes.map((route) => getKey(route));
for (const key of Object.keys(scrollOffsetsRef.current)) {
if (!scrollOffsetkeysOfExistingScreens.includes(key)) {
delete scrollOffsetsRef.current[key];
}
}
}, []);
Expand Down
2 changes: 1 addition & 1 deletion src/components/Search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import * as SearchActions from '@libs/actions/Search';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import Log from '@libs/Log';
import memoize from '@libs/memoize';
import isSearchTopmostFullScreenRoute from '@libs/Navigation/isSearchTopmostFullScreenRoute';
import isSearchTopmostFullScreenRoute from '@libs/Navigation/helpers/isSearchTopmostFullScreenRoute';
import type {PlatformStackNavigationProp} from '@libs/Navigation/PlatformStackNavigation/types';
import * as ReportUtils from '@libs/ReportUtils';
import * as SearchQueryUtils from '@libs/SearchQueryUtils';
Expand Down
4 changes: 2 additions & 2 deletions src/libs/Navigation/AppNavigator/AuthScreens.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {findFocusedRoute} from '@react-navigation/native';
import type {RouteProp} from '@react-navigation/native';
import {findFocusedRoute} from '@react-navigation/native';
import React, {memo, useEffect, useRef, useState} from 'react';
import {NativeModules, View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
Expand All @@ -24,12 +24,12 @@ import KeyboardShortcut from '@libs/KeyboardShortcut';
import Log from '@libs/Log';
import NavBarManager from '@libs/NavBarManager';
import getCurrentUrl from '@libs/Navigation/currentUrl';
import {isOnboardingFlowName} from '@libs/Navigation/helpers';
import SIDEBAR_TO_SPLIT from '@libs/Navigation/linkingConfig/RELATIONS/SIDEBAR_TO_SPLIT';
import Navigation, {navigationRef} from '@libs/Navigation/Navigation';
import Animations from '@libs/Navigation/PlatformStackNavigation/navigationOptions/animation';
import Presentation from '@libs/Navigation/PlatformStackNavigation/navigationOptions/presentation';
import type {AuthScreensParamList} from '@libs/Navigation/types';
import {isOnboardingFlowName} from '@libs/NavigationUtils';
import NetworkConnection from '@libs/NetworkConnection';
import onyxSubscribe from '@libs/onyxSubscribe';
import * as Pusher from '@libs/Pusher/pusher';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type {NavigationState} from '@react-navigation/native';
import {isFullScreenName} from '@libs/NavigationUtils';
import {isFullScreenName} from '@libs/Navigation/helpers';

function getIsScreenBlurred(state: NavigationState, currentRouteKey: string) {
// If the screen is one of the last two fullscreen routes in the stack, it is not freezed on native platforms.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type {NavigationState} from '@react-navigation/native';
import {isFullScreenName} from '@libs/NavigationUtils';
import {isFullScreenName} from '@libs/Navigation/helpers';

function getIsScreenBlurred(state: NavigationState, currentRouteKey: string) {
const lastFullScreenRoute = state.routes.findLast((route) => isFullScreenName(route.name));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import React, {useRef} from 'react';
import FocusTrapForScreens from '@components/FocusTrap/FocusTrapForScreen';
import useActiveWorkspace from '@hooks/useActiveWorkspace';
import usePermissions from '@hooks/usePermissions';
import createSplitStackNavigator from '@libs/Navigation/AppNavigator/createSplitStackNavigator';
import createSplitNavigator from '@libs/Navigation/AppNavigator/createSplitNavigator';
import FreezeWrapper from '@libs/Navigation/AppNavigator/FreezeWrapper';
import useRootNavigatorOptions from '@libs/Navigation/AppNavigator/useRootNavigatorOptions';
import getCurrentUrl from '@libs/Navigation/currentUrl';
import shouldOpenOnAdminRoom from '@libs/Navigation/shouldOpenOnAdminRoom';
import shouldOpenOnAdminRoom from '@libs/Navigation/helpers/shouldOpenOnAdminRoom';
import type {ReportsSplitNavigatorParamList} from '@libs/Navigation/types';
import * as ReportUtils from '@libs/ReportUtils';
import CONST from '@src/CONST';
Expand All @@ -17,7 +17,7 @@ import type ReactComponentModule from '@src/types/utils/ReactComponentModule';
const loadReportScreen = () => require<ReactComponentModule>('../../../../pages/home/ReportScreen').default;
const loadSidebarScreen = () => require<ReactComponentModule>('@pages/home/sidebar/SidebarScreen').default;

const Stack = createSplitStackNavigator<ReportsSplitNavigatorParamList>();
const Split = createSplitNavigator<ReportsSplitNavigatorParamList>();

function ReportsSplitNavigator() {
const {canUseDefaultRooms} = usePermissions();
Expand Down Expand Up @@ -47,23 +47,23 @@ function ReportsSplitNavigator() {
return (
<FreezeWrapper>
<FocusTrapForScreens>
<Stack.Navigator
<Split.Navigator
sidebarScreen={SCREENS.HOME}
defaultCentralScreen={SCREENS.REPORT}
parentRoute={route}
screenOptions={rootNavigatorOptions.centralPaneNavigator}
>
<Stack.Screen
<Split.Screen
name={SCREENS.HOME}
getComponent={loadSidebarScreen}
options={rootNavigatorOptions.homeScreen}
/>
<Stack.Screen
<Split.Screen
name={SCREENS.REPORT}
initialParams={{reportID: initialReportID, openOnAdminRoom: shouldOpenOnAdminRoom() ? true : undefined}}
getComponent={loadReportScreen}
/>
</Stack.Navigator>
</Split.Navigator>
</FocusTrapForScreens>
</FreezeWrapper>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {useRoute} from '@react-navigation/native';
import React from 'react';
import FocusTrapForScreens from '@components/FocusTrap/FocusTrapForScreen';
import createSplitStackNavigator from '@libs/Navigation/AppNavigator/createSplitStackNavigator';
import createSplitNavigator from '@libs/Navigation/AppNavigator/createSplitNavigator';
import useRootNavigatorOptions from '@libs/Navigation/AppNavigator/useRootNavigatorOptions';
import Animations from '@libs/Navigation/PlatformStackNavigation/navigationOptions/animation';
import type {PlatformStackNavigationOptions} from '@libs/Navigation/PlatformStackNavigation/types';
Expand All @@ -25,21 +25,21 @@ const CENTRAL_PANE_SETTINGS_SCREENS = {
[SCREENS.SETTINGS.SUBSCRIPTION.ROOT]: () => require<ReactComponentModule>('../../../../pages/settings/Subscription/SubscriptionSettingsPage').default,
} satisfies Screens;

const Stack = createSplitStackNavigator<SettingsSplitNavigatorParamList>();
const Split = createSplitNavigator<SettingsSplitNavigatorParamList>();

function SettingsSplitNavigator() {
const route = useRoute();
const rootNavigatorOptions = useRootNavigatorOptions();

return (
<FocusTrapForScreens>
<Stack.Navigator
<Split.Navigator
sidebarScreen={SCREENS.SETTINGS.ROOT}
defaultCentralScreen={SCREENS.SETTINGS.PROFILE.ROOT}
parentRoute={route}
screenOptions={rootNavigatorOptions.centralPaneNavigator}
>
<Stack.Screen
<Split.Screen
name={SCREENS.SETTINGS.ROOT}
getComponent={loadInitialSettingsPage}
options={rootNavigatorOptions.homeScreen}
Expand All @@ -52,15 +52,15 @@ function SettingsSplitNavigator() {
}

return (
<Stack.Screen
<Split.Screen
key={screenName}
name={screenName as keyof Screens}
getComponent={componentGetter}
options={options}
/>
);
})}
</Stack.Navigator>
</Split.Navigator>
</FocusTrapForScreens>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {useRoute} from '@react-navigation/native';
import React from 'react';
import FocusTrapForScreens from '@components/FocusTrap/FocusTrapForScreen';
import createSplitStackNavigator from '@libs/Navigation/AppNavigator/createSplitStackNavigator';
import createSplitNavigator from '@libs/Navigation/AppNavigator/createSplitNavigator';
import useRootNavigatorOptions from '@libs/Navigation/AppNavigator/useRootNavigatorOptions';
import type {WorkspaceSplitNavigatorParamList} from '@libs/Navigation/types';
import SCREENS from '@src/SCREENS';
Expand Down Expand Up @@ -29,33 +29,33 @@ const CENTRAL_PANE_WORKSPACE_SCREENS = {
[SCREENS.WORKSPACE.RULES]: () => require<ReactComponentModule>('../../../../pages/workspace/rules/PolicyRulesPage').default,
} satisfies Screens;

const Stack = createSplitStackNavigator<WorkspaceSplitNavigatorParamList>();
const Split = createSplitNavigator<WorkspaceSplitNavigatorParamList>();

function WorkspaceNavigator() {
const route = useRoute();
const rootNavigatorOptions = useRootNavigatorOptions();

return (
<FocusTrapForScreens>
<Stack.Navigator
<Split.Navigator
sidebarScreen={SCREENS.WORKSPACE.INITIAL}
defaultCentralScreen={SCREENS.WORKSPACE.PROFILE}
parentRoute={route}
screenOptions={rootNavigatorOptions.centralPaneNavigator}
>
<Stack.Screen
<Split.Screen
name={SCREENS.WORKSPACE.INITIAL}
getComponent={loadWorkspaceInitialPage}
options={rootNavigatorOptions.homeScreen}
/>
{Object.entries(CENTRAL_PANE_WORKSPACE_SCREENS).map(([screenName, componentGetter]) => (
<Stack.Screen
<Split.Screen
key={screenName}
name={screenName as keyof Screens}
getComponent={componentGetter}
/>
))}
</Stack.Navigator>
</Split.Navigator>
</FocusTrapForScreens>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ function BottomTabBar({selectedTab}: BottomTabBarProps) {
}, [selectedTab]);

const navigateToSearch = useCallback(() => {
if (selectedTab === SCREENS.SEARCH.BOTTOM_TAB) {
if (selectedTab === SCREENS.SEARCH.CENTRAL_PANE) {
return;
}
interceptAnonymousUser(() => {
Expand Down
Loading

0 comments on commit 7345d80

Please sign in to comment.