/** * 桌面端导航器 * 为平板/桌面设备提供侧边栏导航体验 */ import React, { useState, useCallback, useEffect } from 'react'; import { View, StyleSheet, ScrollView, TouchableOpacity, Text, Animated, Platform, } from 'react-native'; import { useSafeAreaInsets, SafeAreaView } from 'react-native-safe-area-context'; import { MaterialCommunityIcons } from '@expo/vector-icons'; import type { TabName, NavItemConfig } from '../infrastructure/navigation/types'; import { NAVIGATION_CONSTANTS } from '../infrastructure/navigation/types'; import { colors, shadows } from '../theme'; import { useNavigationState } from '../infrastructure/navigation/hooks/useNavigationState'; // 导入屏幕 import { HomeScreen } from '../screens/home'; import { ScheduleScreen } from '../screens/schedule'; import { MessageListScreen } from '../screens/message'; import { ProfileScreen } from '../screens/profile'; // 侧边栏常量 const { SIDEBAR_WIDTH_DESKTOP, SIDEBAR_WIDTH_TABLET, SIDEBAR_COLLAPSED_WIDTH } = NAVIGATION_CONSTANTS; // 导航项配置 const NAV_ITEMS: NavItemConfig[] = [ { name: 'HomeTab', label: '首页', icon: 'home', iconOutline: 'home-outline' }, { name: 'MessageTab', label: '消息', icon: 'message-text', iconOutline: 'message-text-outline' }, { name: 'ScheduleTab', label: '课表', icon: 'calendar-today', iconOutline: 'calendar-today' }, { name: 'ProfileTab', label: '我的', icon: 'account', iconOutline: 'account-outline' }, ]; interface DesktopNavigatorProps { unreadCount?: number; } export function DesktopNavigator({ unreadCount = 0 }: DesktopNavigatorProps) { const insets = useSafeAreaInsets(); const { currentTab, isCollapsed, setCurrentTab, toggleCollapse, setIsReady } = useNavigationState(); const [isDesktop, setIsDesktop] = useState(false); // 检测是否是桌面尺寸 useEffect(() => { const checkDesktop = () => { const width = window.innerWidth || document.documentElement.clientWidth; setIsDesktop(width >= SIDEBAR_WIDTH_DESKTOP); }; checkDesktop(); window.addEventListener('resize', checkDesktop); setIsReady(true); return () => window.removeEventListener('resize', checkDesktop); }, [setIsReady]); // 计算侧边栏宽度 const sidebarWidth = isCollapsed ? SIDEBAR_COLLAPSED_WIDTH : (isDesktop ? SIDEBAR_WIDTH_DESKTOP : SIDEBAR_WIDTH_TABLET); // 处理 Tab 切换 const handleTabChange = useCallback((tab: TabName) => { setCurrentTab(tab); }, [setCurrentTab]); // 渲染当前 Tab 的内容 const renderTabContent = () => { switch (currentTab) { case 'HomeTab': return ; case 'MessageTab': return ; case 'ScheduleTab': return ; case 'ProfileTab': return ; default: return ; } }; return ( {/* 侧边栏 */} {/* Logo 区域 */} {!isCollapsed && ( 胡萝卜BBS )} {/* 导航项 */} {NAV_ITEMS.map((item) => { const isActive = currentTab === item.name; const showBadge = item.name === 'MessageTab' && unreadCount > 0; return ( handleTabChange(item.name)} activeOpacity={0.7} > {showBadge && ( {unreadCount > 99 ? '99+' : unreadCount} )} {!isCollapsed && ( {item.label} )} ); })} {/* 折叠按钮 */} {/* 主内容区域 */} {renderTabContent()} ); } const styles = StyleSheet.create({ container: { flex: 1, flexDirection: 'row', backgroundColor: colors.background.default, }, sidebar: { backgroundColor: colors.background.paper, borderRightWidth: 1, borderRightColor: colors.divider, flexDirection: 'column', ...shadows.md, }, sidebarHeader: { paddingHorizontal: 16, paddingVertical: 20, borderBottomWidth: 1, borderBottomColor: colors.divider, alignItems: 'center', justifyContent: 'center', flexDirection: 'row', }, logoText: { fontSize: 18, fontWeight: '700', color: colors.primary.main, marginLeft: 8, }, sidebarContent: { flex: 1, paddingTop: 8, }, sidebarItem: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, paddingVertical: 12, marginHorizontal: 8, marginVertical: 4, borderRadius: 12, }, sidebarItemActive: { backgroundColor: `${colors.primary.main}15`, }, sidebarItemCollapsed: { justifyContent: 'center', paddingHorizontal: 0, }, sidebarIconContainer: { position: 'relative', width: 40, height: 40, alignItems: 'center', justifyContent: 'center', borderRadius: 12, }, sidebarLabel: { fontSize: 15, fontWeight: '500', color: colors.text.secondary, marginLeft: 12, flex: 1, }, sidebarLabelActive: { color: colors.primary.main, fontWeight: '600', }, collapseButton: { flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-end', paddingHorizontal: 16, paddingVertical: 12, borderTopWidth: 1, borderTopColor: colors.divider, }, collapseButtonCollapsed: { justifyContent: 'center', paddingHorizontal: 0, }, badge: { position: 'absolute', top: 2, right: 2, backgroundColor: colors.error.main, borderRadius: 10, minWidth: 18, height: 18, alignItems: 'center', justifyContent: 'center', paddingHorizontal: 4, }, badgeText: { color: colors.primary.contrast, fontSize: 10, fontWeight: '600', }, mainContent: { flex: 1, backgroundColor: colors.background.default, }, });