/** * 应用中心:与首页顶栏、个人主页帖子卡片同一套圆角 / 阴影 / 主色体系 */ import React, { useCallback, useMemo } from 'react'; import { View, StyleSheet, ScrollView, TouchableOpacity, StatusBar } from 'react-native'; import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context'; import { useRouter } from 'expo-router'; import { MaterialCommunityIcons } from '@expo/vector-icons'; import { spacing, fontSizes, borderRadius, shadows, useAppColors, useResolvedColorScheme, type AppColors, } from '../../theme'; import * as hrefs from '../../navigation/hrefs'; import { Text, ResponsiveContainer } from '../../components/common'; import { useResponsive, useResponsiveSpacing, useBreakpointGTE } from '../../hooks/useResponsive'; type AppItem = { id: string; title: string; subtitle: string; icon: React.ComponentProps['name']; href: string; }; const APP_ENTRIES: AppItem[] = [ { id: 'schedule', title: '课表', subtitle: '周课表、教务同步与课程管理', icon: 'calendar-week', href: hrefs.hrefSchedule(), }, ]; export const AppsScreen: React.FC = () => { const colors = useAppColors(); const resolvedScheme = useResolvedColorScheme(); const statusBarStyle = resolvedScheme === 'dark' ? 'light-content' : 'dark-content'; const styles = useMemo(() => createAppsStyles(colors), [colors]); /** 与个人主页 PostCard 外层 `postWrapper` 一致 */ const postCardShell = useMemo( () => ({ marginBottom: spacing.md, backgroundColor: colors.background.paper, borderRadius: 16, overflow: 'hidden' as const, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.06, shadowRadius: 8, elevation: 2, }), [colors] ); const router = useRouter(); const insets = useSafeAreaInsets(); const { isMobile } = useResponsive(); /** 与 MessageListScreen 顶栏宽屏 padding 一致 */ const isWideScreen = useBreakpointGTE('lg'); const responsivePadding = useResponsiveSpacing({ xs: 8, sm: 12, md: 16, lg: 24, xl: 32 }); const scrollBottomInset = isMobile ? 88 + insets.bottom + spacing.md : spacing['3xl']; const onOpenApp = useCallback( (href: string) => { router.push(href); }, [router] ); const renderTiles = () => ( <> 与社区账号打通的轻应用入口 {APP_ENTRIES.map(item => ( onOpenApp(item.href)} activeOpacity={0.88} > {item.title} {item.subtitle} ))} 更多应用陆续上线 ); return ( {/* 与 MessageListScreen 顶栏同一结构 / 样式 */} 应用 {isWideScreen ? ( {renderTiles()} ) : ( {renderTiles()} )} ); }; export default AppsScreen; function createAppsStyles(colors: AppColors) { const headerBg = colors.background.default; return StyleSheet.create({ container: { flex: 1, backgroundColor: colors.background.default, }, msgHeader: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: spacing.md, paddingVertical: spacing.md, backgroundColor: headerBg, ...shadows.sm, }, msgHeaderWide: { paddingHorizontal: spacing.lg, paddingVertical: spacing.lg, }, msgHeaderLeft: { width: 44, }, msgHeaderCenter: { flexDirection: 'row', alignItems: 'center', gap: spacing.xs, }, msgHeaderTitle: { fontSize: 19, fontWeight: '700', color: colors.text.primary, }, msgHeaderTitleWide: { fontSize: 22, }, msgHeaderRight: { flexDirection: 'row', alignItems: 'center', }, /** 与消息页「+」按钮同占位宽度,标题视觉居中 */ msgHeaderRightSpacer: { width: 36, height: 44, }, pageSubtitle: { marginBottom: spacing.md, lineHeight: fontSizes.sm * 1.45, }, /** 与消息列表区同色,避免顶栏阴影落在灰底上像一条线 */ scroll: { flex: 1, backgroundColor: headerBg, }, scrollContent: { paddingTop: spacing.md, flexGrow: 1, backgroundColor: headerBg, }, appCardInner: { flexDirection: 'row', alignItems: 'center', paddingVertical: spacing.lg, paddingHorizontal: spacing.lg, }, /** 与首页发帖 FAB 同主色实心圆 */ appIconCircle: { width: 52, height: 52, borderRadius: borderRadius.full, backgroundColor: colors.primary.main, alignItems: 'center', justifyContent: 'center', }, appCardText: { flex: 1, marginLeft: spacing.md, marginRight: spacing.sm, }, appTitle: { fontWeight: '700', fontSize: fontSizes.md + 1, }, appSubtitle: { marginTop: 4, }, footer: { alignItems: 'center', paddingTop: spacing.xl, paddingBottom: spacing.md, }, }); }