Skip to content

Commit

Permalink
Merge pull request #42684 from abzokhattab/fix-chat-navigation
Browse files Browse the repository at this point in the history
Fix chat navigation
  • Loading branch information
NikkiWines authored Jun 10, 2024
2 parents ccce980 + 191f197 commit 2929a91
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {PickerStateProvider} from 'react-native-picker-select';
import {SafeAreaProvider} from 'react-native-safe-area-context';
import '../wdyr';
import ActiveElementRoleProvider from './components/ActiveElementRoleProvider';
import ActiveWorkspaceContextProvider from './components/ActiveWorkspace/ActiveWorkspaceProvider';
import ActiveWorkspaceContextProvider from './components/ActiveWorkspaceProvider';
import ColorSchemeWrapper from './components/ColorSchemeWrapper';
import ComposeProviders from './components/ComposeProviders';
import CustomStatusBarAndBackground from './components/CustomStatusBarAndBackground';
Expand Down
1 change: 1 addition & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4753,6 +4753,7 @@ const CONST = {

SESSION_STORAGE_KEYS: {
INITIAL_URL: 'INITIAL_URL',
ACTIVE_WORKSPACE_ID: 'ACTIVE_WORKSPACE_ID',
},

RESERVATION_TYPE: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, {useMemo, useState} from 'react';
import ActiveWorkspaceContext from '@components/ActiveWorkspace/ActiveWorkspaceContext';
import type ChildrenProps from '@src/types/utils/ChildrenProps';
import ActiveWorkspaceContext from './ActiveWorkspaceContext';

function ActiveWorkspaceContextProvider({children}: ChildrenProps) {
const [activeWorkspaceID, setActiveWorkspaceID] = useState<string | undefined>(undefined);
Expand All @@ -10,7 +10,7 @@ function ActiveWorkspaceContextProvider({children}: ChildrenProps) {
activeWorkspaceID,
setActiveWorkspaceID,
}),
[activeWorkspaceID],
[activeWorkspaceID, setActiveWorkspaceID],
);

return <ActiveWorkspaceContext.Provider value={value}>{children}</ActiveWorkspaceContext.Provider>;
Expand Down
29 changes: 29 additions & 0 deletions src/components/ActiveWorkspaceProvider/index.website.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React, {useCallback, useMemo, useState} from 'react';
import ActiveWorkspaceContext from '@components/ActiveWorkspace/ActiveWorkspaceContext';
import CONST from '@src/CONST';
import type ChildrenProps from '@src/types/utils/ChildrenProps';

function ActiveWorkspaceContextProvider({children}: ChildrenProps) {
const [activeWorkspaceID, updateActiveWorkspaceID] = useState<string | undefined>(undefined);

const setActiveWorkspaceID = useCallback((workspaceID: string | undefined) => {
updateActiveWorkspaceID(workspaceID);
if (workspaceID && sessionStorage) {
sessionStorage?.setItem(CONST.SESSION_STORAGE_KEYS.ACTIVE_WORKSPACE_ID, workspaceID);
} else {
sessionStorage?.removeItem(CONST.SESSION_STORAGE_KEYS.ACTIVE_WORKSPACE_ID);
}
}, []);

const value = useMemo(
() => ({
activeWorkspaceID,
setActiveWorkspaceID,
}),
[activeWorkspaceID, setActiveWorkspaceID],
);

return <ActiveWorkspaceContext.Provider value={value}>{children}</ActiveWorkspaceContext.Provider>;
}

export default ActiveWorkspaceContextProvider;
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {useNavigation, useNavigationState} from '@react-navigation/native';
import React, {useEffect} from 'react';
import React, {useCallback, useEffect} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
Expand All @@ -25,6 +25,7 @@ import * as Welcome from '@userActions/Welcome';
import CONST from '@src/CONST';
import NAVIGATORS from '@src/NAVIGATORS';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Route} from '@src/ROUTES';
import ROUTES from '@src/ROUTES';
import SCREENS from '@src/SCREENS';

Expand All @@ -37,9 +38,8 @@ function BottomTabBar({isLoadingApp = false}: PurposeForUsingExpensifyModalProps
const theme = useTheme();
const styles = useThemeStyles();
const {translate} = useLocalize();
const {activeWorkspaceID} = useActiveWorkspace();

const navigation = useNavigation();
const {activeWorkspaceID} = useActiveWorkspace();

useEffect(() => {
const navigationState = navigation.getState() as State<RootStackParamList> | undefined;
Expand Down Expand Up @@ -69,13 +69,16 @@ function BottomTabBar({isLoadingApp = false}: PurposeForUsingExpensifyModalProps

const chatTabBrickRoad = getChatTabBrickRoad(activeWorkspaceID);

const navigateToChats = useCallback(() => {
const route = activeWorkspaceID ? (`/w/${activeWorkspaceID}/home` as Route) : ROUTES.HOME;
Navigation.navigate(route);
}, [activeWorkspaceID]);

return (
<View style={styles.bottomTabBarContainer}>
<Tooltip text={translate('common.inbox')}>
<PressableWithFeedback
onPress={() => {
Navigation.navigate(ROUTES.HOME);
}}
onPress={navigateToChats}
role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('common.inbox')}
wrapperStyle={styles.flex1}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import {useNavigation, useNavigationState} from '@react-navigation/native';
import React, {useCallback, useEffect} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import {PressableWithFeedback} from '@components/Pressable';
import Tooltip from '@components/Tooltip';
import useActiveWorkspace from '@hooks/useActiveWorkspace';
import useLocalize from '@hooks/useLocalize';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import * as Session from '@libs/actions/Session';
import interceptAnonymousUser from '@libs/interceptAnonymousUser';
import getTopmostBottomTabRoute from '@libs/Navigation/getTopmostBottomTabRoute';
import getTopmostCentralPaneRoute from '@libs/Navigation/getTopmostCentralPaneRoute';
import Navigation from '@libs/Navigation/Navigation';
import type {RootStackParamList, State} from '@libs/Navigation/types';
import {getChatTabBrickRoad} from '@libs/WorkspacesSettingsUtils';
import BottomTabAvatar from '@pages/home/sidebar/BottomTabAvatar';
import BottomTabBarFloatingActionButton from '@pages/home/sidebar/BottomTabBarFloatingActionButton';
import variables from '@styles/variables';
import * as Welcome from '@userActions/Welcome';
import CONST from '@src/CONST';
import NAVIGATORS from '@src/NAVIGATORS';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Route} from '@src/ROUTES';
import ROUTES from '@src/ROUTES';
import SCREENS from '@src/SCREENS';

type PurposeForUsingExpensifyModalOnyxProps = {
isLoadingApp: OnyxEntry<boolean>;
};
type PurposeForUsingExpensifyModalProps = PurposeForUsingExpensifyModalOnyxProps;

function BottomTabBar({isLoadingApp = false}: PurposeForUsingExpensifyModalProps) {
const theme = useTheme();
const styles = useThemeStyles();
const {translate} = useLocalize();
const navigation = useNavigation();
const {activeWorkspaceID: contextActiveWorkspaceID} = useActiveWorkspace();
const activeWorkspaceID = sessionStorage.getItem(CONST.SESSION_STORAGE_KEYS.ACTIVE_WORKSPACE_ID) ?? contextActiveWorkspaceID;

useEffect(() => {
const navigationState = navigation.getState() as State<RootStackParamList> | undefined;
const routes = navigationState?.routes;
const currentRoute = routes?.[navigationState?.index ?? 0];
// When we are redirected to the Settings tab from the OldDot, we don't want to call the Welcome.show() method.
// To prevent this, the value of the bottomTabRoute?.name is checked here
if (!!(currentRoute && currentRoute.name !== NAVIGATORS.BOTTOM_TAB_NAVIGATOR && currentRoute.name !== NAVIGATORS.CENTRAL_PANE_NAVIGATOR) || Session.isAnonymousUser()) {
return;
}

Welcome.isOnboardingFlowCompleted({onNotCompleted: () => Navigation.navigate(ROUTES.ONBOARDING_ROOT)});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isLoadingApp]);

// Parent navigator of the bottom tab bar is the root navigator.
const currentTabName = useNavigationState<RootStackParamList, string | undefined>((state) => {
const topmostCentralPaneRoute = getTopmostCentralPaneRoute(state);

if (topmostCentralPaneRoute && topmostCentralPaneRoute.name === SCREENS.SEARCH.CENTRAL_PANE) {
return SCREENS.SEARCH.CENTRAL_PANE;
}

const topmostBottomTabRoute = getTopmostBottomTabRoute(state);
return topmostBottomTabRoute?.name ?? SCREENS.HOME;
});

const chatTabBrickRoad = getChatTabBrickRoad(activeWorkspaceID);

const navigateToChats = useCallback(() => {
const route = activeWorkspaceID ? (`/w/${activeWorkspaceID}/home` as Route) : ROUTES.HOME;
Navigation.navigate(route);
}, [activeWorkspaceID]);

return (
<View style={styles.bottomTabBarContainer}>
<Tooltip text={translate('common.inbox')}>
<PressableWithFeedback
onPress={navigateToChats}
role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('common.inbox')}
wrapperStyle={styles.flex1}
style={styles.bottomTabBarItem}
>
<View>
<Icon
src={Expensicons.Inbox}
fill={currentTabName === SCREENS.HOME ? theme.iconMenu : theme.icon}
width={variables.iconBottomBar}
height={variables.iconBottomBar}
/>
{chatTabBrickRoad && (
<View style={styles.bottomTabStatusIndicator(chatTabBrickRoad === CONST.BRICK_ROAD_INDICATOR_STATUS.INFO ? theme.iconSuccessFill : theme.danger)} />
)}
</View>
</PressableWithFeedback>
</Tooltip>
<Tooltip text={translate('common.search')}>
<PressableWithFeedback
onPress={() => {
interceptAnonymousUser(() => Navigation.navigate(ROUTES.SEARCH.getRoute(CONST.TAB_SEARCH.ALL)));
}}
role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('common.search')}
wrapperStyle={styles.flex1}
style={styles.bottomTabBarItem}
>
<View>
<Icon
src={Expensicons.MoneySearch}
fill={currentTabName === SCREENS.SEARCH.BOTTOM_TAB || currentTabName === SCREENS.SEARCH.CENTRAL_PANE ? theme.iconMenu : theme.icon}
width={variables.iconBottomBar}
height={variables.iconBottomBar}
/>
</View>
</PressableWithFeedback>
</Tooltip>
<BottomTabAvatar isSelected={currentTabName === SCREENS.SETTINGS.ROOT} />
<View style={[styles.flex1, styles.bottomTabBarItem]}>
<BottomTabBarFloatingActionButton />
</View>
</View>
);
}

BottomTabBar.displayName = 'BottomTabBar';

export default withOnyx<PurposeForUsingExpensifyModalProps, PurposeForUsingExpensifyModalOnyxProps>({
isLoadingApp: {
key: ONYXKEYS.IS_LOADING_APP,
},
})(BottomTabBar);

0 comments on commit 2929a91

Please sign in to comment.