75 lines
2.6 KiB
TypeScript
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>
|
|
);
|
|
};
|