Move token verification from root layout SessionGate to (app) group layout, enabling cold-start verification without blocking public pages (privacy/terms). Show ActivityIndicator while verification is in progress, then redirect to login if unverified. BREAKING CHANGE: Authentication flow changed - token verification now occurs in the (app) layout group instead of root layout SessionGate wrapper.
57 lines
1.9 KiB
TypeScript
57 lines
1.9 KiB
TypeScript
import { useEffect, useState } from 'react';
|
||
import { ActivityIndicator, View, useWindowDimensions } from 'react-native';
|
||
import { Redirect } from 'expo-router';
|
||
|
||
import { AppDesktopShell } from '../../src/app-navigation/AppDesktopShell';
|
||
import { AppRouteStack } from '../../src/app-navigation/AppRouteStack';
|
||
import { BREAKPOINTS } from '../../src/hooks';
|
||
import { messageManager, useAuthStore } from '../../src/stores';
|
||
import { hrefAuthLogin } from '../../src/navigation/hrefs';
|
||
import { useAppColors } from '../../src/theme';
|
||
|
||
export default function AppLayoutWeb() {
|
||
const { width } = useWindowDimensions();
|
||
const isAuthenticated = useAuthStore((s) => s.isAuthenticated);
|
||
const fetchCurrentUser = useAuthStore((s) => s.fetchCurrentUser);
|
||
const useDesktopShell = width >= BREAKPOINTS.desktop;
|
||
const colors = useAppColors();
|
||
const [verified, setVerified] = useState(false);
|
||
|
||
useEffect(() => {
|
||
// 冷启动 token 校验:仅鉴权分组 (app) 需要。
|
||
// 公开页(/privacy、/terms)和 (auth) 分组在根布局直接渲染,不受此校验影响。
|
||
fetchCurrentUser().finally(() => setVerified(true));
|
||
}, [fetchCurrentUser]);
|
||
|
||
useEffect(() => {
|
||
messageManager.initialize();
|
||
}, []);
|
||
|
||
// 持久化状态显示已登录则立即渲染(后台静默校验)
|
||
if (isAuthenticated) {
|
||
if (useDesktopShell) {
|
||
return <AppDesktopShell />;
|
||
}
|
||
return <AppRouteStack />;
|
||
}
|
||
|
||
// 未登录且校验未完成,显示 loading
|
||
if (!verified) {
|
||
return (
|
||
<View
|
||
style={{
|
||
flex: 1,
|
||
justifyContent: 'center',
|
||
alignItems: 'center',
|
||
backgroundColor: colors.background.default,
|
||
}}
|
||
>
|
||
<ActivityIndicator size="large" color={colors.primary.main} />
|
||
</View>
|
||
);
|
||
}
|
||
|
||
// 校验完成仍未登录,跳转登录页
|
||
return <Redirect href={hrefAuthLogin()} />;
|
||
}
|