2026-03-18 12:11:49 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 根导航器
|
|
|
|
|
|
* 处理整个应用的顶级导航,包括认证状态切换
|
|
|
|
|
|
*/
|
|
|
|
|
|
import React, { useEffect, useState } from 'react';
|
|
|
|
|
|
import { View, ActivityIndicator, StyleSheet } from 'react-native';
|
|
|
|
|
|
import { NavigationContainer } from '@react-navigation/native';
|
|
|
|
|
|
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
|
|
|
|
|
|
|
|
|
|
|
import type { RootStackParamList } from './types';
|
|
|
|
|
|
import { colors } from '../theme';
|
|
|
|
|
|
import { navigationService } from '../infrastructure/navigation/navigationService';
|
|
|
|
|
|
|
|
|
|
|
|
import { AuthNavigator } from './AuthNavigator';
|
|
|
|
|
|
import { SimpleMobileTabNavigator } from './SimpleMobileTabNavigator';
|
|
|
|
|
|
import { DesktopNavigator } from './DesktopNavigator';
|
|
|
|
|
|
|
|
|
|
|
|
import { useResponsive } from '../hooks';
|
|
|
|
|
|
import { useTotalUnreadCount } from '../stores';
|
|
|
|
|
|
|
|
|
|
|
|
// 导入全局屏幕组件
|
|
|
|
|
|
import { PostDetailScreen } from '../screens/home';
|
|
|
|
|
|
import { UserScreen } from '../screens/profile';
|
|
|
|
|
|
import FollowListScreen from '../screens/profile/FollowListScreen';
|
|
|
|
|
|
import { CreatePostScreen } from '../screens/create';
|
|
|
|
|
|
import {
|
|
|
|
|
|
ChatScreen,
|
|
|
|
|
|
CreateGroupScreen,
|
|
|
|
|
|
JoinGroupScreen,
|
|
|
|
|
|
GroupInfoScreen,
|
|
|
|
|
|
GroupMembersScreen,
|
|
|
|
|
|
GroupRequestDetailScreen,
|
|
|
|
|
|
GroupInviteDetailScreen,
|
|
|
|
|
|
PrivateChatInfoScreen,
|
|
|
|
|
|
} from '../screens/message';
|
|
|
|
|
|
|
|
|
|
|
|
const RootStack = createNativeStackNavigator<RootStackParamList>();
|
|
|
|
|
|
|
|
|
|
|
|
interface RootNavigatorProps {
|
|
|
|
|
|
isAuthenticated: boolean;
|
|
|
|
|
|
isInitializing: boolean;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-18 14:52:58 +08:00
|
|
|
|
// 未认证时可访问的屏幕 - 返回数组而不是 JSX
|
|
|
|
|
|
const getPublicScreens = () => [
|
|
|
|
|
|
<RootStack.Screen
|
|
|
|
|
|
key="PostDetail"
|
|
|
|
|
|
name="PostDetail"
|
|
|
|
|
|
component={PostDetailScreen}
|
|
|
|
|
|
options={{
|
|
|
|
|
|
headerShown: true,
|
|
|
|
|
|
title: '',
|
|
|
|
|
|
headerStyle: { backgroundColor: colors.background.paper },
|
|
|
|
|
|
headerTintColor: colors.text.primary,
|
|
|
|
|
|
animation: 'slide_from_right',
|
|
|
|
|
|
}}
|
|
|
|
|
|
/>,
|
|
|
|
|
|
<RootStack.Screen
|
|
|
|
|
|
key="UserProfile"
|
|
|
|
|
|
name="UserProfile"
|
|
|
|
|
|
component={UserScreen}
|
|
|
|
|
|
options={{
|
|
|
|
|
|
headerShown: true,
|
|
|
|
|
|
title: '用户主页',
|
|
|
|
|
|
headerStyle: { backgroundColor: colors.background.paper },
|
|
|
|
|
|
headerTintColor: colors.text.primary,
|
|
|
|
|
|
}}
|
|
|
|
|
|
/>,
|
|
|
|
|
|
];
|
2026-03-18 12:11:49 +08:00
|
|
|
|
|
2026-03-18 14:52:58 +08:00
|
|
|
|
// 认证后可访问的屏幕 - 返回数组而不是 JSX
|
|
|
|
|
|
const getAuthenticatedScreens = () => [
|
|
|
|
|
|
<RootStack.Screen
|
|
|
|
|
|
key="PostDetail"
|
|
|
|
|
|
name="PostDetail"
|
|
|
|
|
|
component={PostDetailScreen}
|
|
|
|
|
|
options={{
|
|
|
|
|
|
headerShown: true,
|
|
|
|
|
|
title: '',
|
|
|
|
|
|
headerStyle: { backgroundColor: colors.background.paper },
|
|
|
|
|
|
headerTintColor: colors.text.primary,
|
|
|
|
|
|
animation: 'slide_from_right',
|
|
|
|
|
|
}}
|
|
|
|
|
|
/>,
|
|
|
|
|
|
<RootStack.Screen
|
|
|
|
|
|
key="UserProfile"
|
|
|
|
|
|
name="UserProfile"
|
|
|
|
|
|
component={UserScreen}
|
|
|
|
|
|
options={{
|
|
|
|
|
|
headerShown: true,
|
|
|
|
|
|
title: '用户主页',
|
|
|
|
|
|
headerStyle: { backgroundColor: colors.background.paper },
|
|
|
|
|
|
headerTintColor: colors.text.primary,
|
|
|
|
|
|
}}
|
|
|
|
|
|
/>,
|
|
|
|
|
|
<RootStack.Screen
|
|
|
|
|
|
key="CreatePost"
|
|
|
|
|
|
name="CreatePost"
|
|
|
|
|
|
component={CreatePostScreen}
|
|
|
|
|
|
options={{
|
|
|
|
|
|
headerShown: true,
|
|
|
|
|
|
title: '发布帖子',
|
|
|
|
|
|
headerStyle: { backgroundColor: colors.background.paper },
|
|
|
|
|
|
headerTintColor: colors.text.primary,
|
|
|
|
|
|
presentation: 'modal',
|
|
|
|
|
|
}}
|
|
|
|
|
|
/>,
|
|
|
|
|
|
<RootStack.Screen
|
|
|
|
|
|
key="Chat"
|
|
|
|
|
|
name="Chat"
|
|
|
|
|
|
component={ChatScreen}
|
|
|
|
|
|
options={{
|
|
|
|
|
|
headerShown: false,
|
|
|
|
|
|
animation: 'slide_from_right',
|
|
|
|
|
|
}}
|
|
|
|
|
|
/>,
|
|
|
|
|
|
<RootStack.Screen
|
|
|
|
|
|
key="FollowList"
|
|
|
|
|
|
name="FollowList"
|
|
|
|
|
|
component={FollowListScreen}
|
|
|
|
|
|
options={{
|
|
|
|
|
|
headerShown: true,
|
|
|
|
|
|
title: '关注列表',
|
|
|
|
|
|
headerStyle: { backgroundColor: colors.background.paper },
|
|
|
|
|
|
headerTintColor: colors.text.primary,
|
|
|
|
|
|
animation: 'slide_from_right',
|
|
|
|
|
|
}}
|
|
|
|
|
|
/>,
|
|
|
|
|
|
<RootStack.Screen
|
|
|
|
|
|
key="CreateGroup"
|
|
|
|
|
|
name="CreateGroup"
|
|
|
|
|
|
component={CreateGroupScreen}
|
|
|
|
|
|
options={{
|
|
|
|
|
|
headerShown: true,
|
|
|
|
|
|
title: '创建群聊',
|
|
|
|
|
|
headerStyle: { backgroundColor: colors.background.paper },
|
|
|
|
|
|
headerTintColor: colors.text.primary,
|
|
|
|
|
|
presentation: 'modal',
|
|
|
|
|
|
}}
|
|
|
|
|
|
/>,
|
|
|
|
|
|
<RootStack.Screen
|
|
|
|
|
|
key="JoinGroup"
|
|
|
|
|
|
name="JoinGroup"
|
|
|
|
|
|
component={JoinGroupScreen}
|
|
|
|
|
|
options={{
|
|
|
|
|
|
headerShown: true,
|
|
|
|
|
|
title: '搜索群聊',
|
|
|
|
|
|
headerStyle: { backgroundColor: colors.background.paper },
|
|
|
|
|
|
headerTintColor: colors.text.primary,
|
|
|
|
|
|
animation: 'slide_from_right',
|
|
|
|
|
|
}}
|
|
|
|
|
|
/>,
|
|
|
|
|
|
<RootStack.Screen
|
|
|
|
|
|
key="GroupInfo"
|
|
|
|
|
|
name="GroupInfo"
|
|
|
|
|
|
component={GroupInfoScreen}
|
|
|
|
|
|
options={{
|
|
|
|
|
|
headerShown: true,
|
|
|
|
|
|
title: '群信息',
|
|
|
|
|
|
headerStyle: { backgroundColor: colors.background.paper },
|
|
|
|
|
|
headerTintColor: colors.text.primary,
|
|
|
|
|
|
animation: 'slide_from_right',
|
|
|
|
|
|
}}
|
|
|
|
|
|
/>,
|
|
|
|
|
|
<RootStack.Screen
|
|
|
|
|
|
key="GroupMembers"
|
|
|
|
|
|
name="GroupMembers"
|
|
|
|
|
|
component={GroupMembersScreen}
|
|
|
|
|
|
options={{
|
|
|
|
|
|
headerShown: true,
|
|
|
|
|
|
title: '群成员',
|
|
|
|
|
|
headerStyle: { backgroundColor: colors.background.paper },
|
|
|
|
|
|
headerTintColor: colors.text.primary,
|
|
|
|
|
|
animation: 'slide_from_right',
|
|
|
|
|
|
}}
|
|
|
|
|
|
/>,
|
|
|
|
|
|
<RootStack.Screen
|
|
|
|
|
|
key="GroupRequestDetail"
|
|
|
|
|
|
name="GroupRequestDetail"
|
|
|
|
|
|
component={GroupRequestDetailScreen}
|
|
|
|
|
|
options={{
|
|
|
|
|
|
headerShown: true,
|
|
|
|
|
|
title: '入群审批',
|
|
|
|
|
|
headerStyle: { backgroundColor: colors.background.paper },
|
|
|
|
|
|
headerTintColor: colors.text.primary,
|
|
|
|
|
|
animation: 'slide_from_right',
|
|
|
|
|
|
}}
|
|
|
|
|
|
/>,
|
|
|
|
|
|
<RootStack.Screen
|
|
|
|
|
|
key="GroupInviteDetail"
|
|
|
|
|
|
name="GroupInviteDetail"
|
|
|
|
|
|
component={GroupInviteDetailScreen}
|
|
|
|
|
|
options={{
|
|
|
|
|
|
headerShown: true,
|
|
|
|
|
|
title: '群聊邀请',
|
|
|
|
|
|
headerStyle: { backgroundColor: colors.background.paper },
|
|
|
|
|
|
headerTintColor: colors.text.primary,
|
|
|
|
|
|
animation: 'slide_from_right',
|
|
|
|
|
|
}}
|
|
|
|
|
|
/>,
|
|
|
|
|
|
<RootStack.Screen
|
|
|
|
|
|
key="PrivateChatInfo"
|
|
|
|
|
|
name="PrivateChatInfo"
|
|
|
|
|
|
component={PrivateChatInfoScreen}
|
|
|
|
|
|
options={{
|
|
|
|
|
|
headerShown: true,
|
|
|
|
|
|
title: '聊天信息',
|
|
|
|
|
|
headerStyle: { backgroundColor: colors.background.paper },
|
|
|
|
|
|
headerTintColor: colors.text.primary,
|
|
|
|
|
|
animation: 'slide_from_right',
|
|
|
|
|
|
}}
|
|
|
|
|
|
/>,
|
|
|
|
|
|
];
|
2026-03-18 12:11:49 +08:00
|
|
|
|
|
|
|
|
|
|
export function RootNavigator({ isAuthenticated, isInitializing }: RootNavigatorProps) {
|
|
|
|
|
|
const { isMobile } = useResponsive();
|
|
|
|
|
|
const unreadCount = useTotalUnreadCount();
|
|
|
|
|
|
|
|
|
|
|
|
// 设置导航引用
|
|
|
|
|
|
const setNavigationRef = (ref: any) => {
|
|
|
|
|
|
navigationService.setNavigationRef(ref);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 加载中显示
|
|
|
|
|
|
if (isInitializing) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
<View style={styles.loadingContainer}>
|
|
|
|
|
|
<ActivityIndicator size="large" color={colors.primary.main} />
|
|
|
|
|
|
</View>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<NavigationContainer ref={setNavigationRef}>
|
|
|
|
|
|
<RootStack.Navigator
|
|
|
|
|
|
screenOptions={{
|
|
|
|
|
|
headerShown: false,
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
{isAuthenticated ? (
|
|
|
|
|
|
<>
|
|
|
|
|
|
<RootStack.Screen name="Main">
|
|
|
|
|
|
{() =>
|
|
|
|
|
|
isMobile ? (
|
|
|
|
|
|
<SimpleMobileTabNavigator />
|
|
|
|
|
|
) : (
|
|
|
|
|
|
<DesktopNavigator unreadCount={unreadCount} />
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
</RootStack.Screen>
|
2026-03-18 14:52:58 +08:00
|
|
|
|
{getAuthenticatedScreens()}
|
2026-03-18 12:11:49 +08:00
|
|
|
|
</>
|
|
|
|
|
|
) : (
|
|
|
|
|
|
<>
|
|
|
|
|
|
<RootStack.Screen
|
|
|
|
|
|
name="Auth"
|
|
|
|
|
|
component={AuthNavigator}
|
|
|
|
|
|
options={{ headerShown: false }}
|
|
|
|
|
|
/>
|
2026-03-18 14:52:58 +08:00
|
|
|
|
{getPublicScreens()}
|
2026-03-18 12:11:49 +08:00
|
|
|
|
</>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</RootStack.Navigator>
|
|
|
|
|
|
</NavigationContainer>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const styles = StyleSheet.create({
|
|
|
|
|
|
loadingContainer: {
|
|
|
|
|
|
flex: 1,
|
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
backgroundColor: colors.background.default,
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|