Files
CBS-Mobile-App/src/navigation/RootNavigator.tsx
T

75 lines
2.6 KiB
TypeScript

import React from 'react';
import { View } from 'react-native';
import {
DarkTheme,
NavigationContainer,
} from '@react-navigation/native';
import { useAppSelector } from '../app/hooks';
import { selectAuthHydrating, selectIsAuthenticated, selectAuthRole } from '../modules/auth/store/authSelectors';
import { Loader } from '../components';
import { FeatureKey } from '../constants/featureKeys';
import { useFeature, useFeatureContext } from '../features';
import { useTheme } from '../theme';
import { AuthNavigator } from './AuthNavigator';
import { MainTabNavigator } from './MainTabNavigator';
import { AgentNavigator } from './AgentNavigator';
export const RootNavigator = () => {
const theme = useTheme();
const isHydrating = useAppSelector(selectAuthHydrating);
const isAuthenticated = useAppSelector(selectIsAuthenticated);
const role = useAppSelector(selectAuthRole);
const agentAppEnabled = useFeature(FeatureKey.AGENT);
/**
* Navigators register their screens at mount time, so mounting one before the
* feature layers have resolved would leave a disabled route reachable — by
* `navigate()`, a deep link or restored state — until the next launch. Waiting
* is what makes a server-side kill switch take effect on this launch.
*/
const { ready: featuresReady } = useFeatureContext();
const renderAppStack = () => {
switch (role) {
// Turning off `agent` retires the whole field-agent application. An
// already-signed-in agent falls back to the customer app rather than
// landing on an empty navigator.
case 'Agent':
return agentAppEnabled ? <AgentNavigator /> : <MainTabNavigator />;
case 'User':
default:
return <MainTabNavigator />;
}
};
return (
<NavigationContainer
theme={{
...DarkTheme,
colors: {
...DarkTheme.colors,
background: theme.colors.background,
card: theme.colors.backgroundElevated,
text: theme.colors.textPrimary,
primary: theme.colors.accent,
border: theme.colors.cardBorder,
notification: theme.colors.accent,
},
}}
>
{/* Bootstrap validates a stored session against the server before
trusting it, so rendering the sign-in screen meanwhile would flash it
at a user who turns out to be signed in already. */}
{isHydrating || !featuresReady ? (
<View style={{ flex: 1, backgroundColor: theme.colors.background }}>
<Loader />
</View>
) : isAuthenticated ? (
renderAppStack()
) : (
<AuthNavigator />
)}
</NavigationContainer>
);
};