/** * 通知设置页 NotificationSettingsScreen(响应式适配) * 胡萝卜BBS - 通知相关设置 * 在宽屏下居中显示 */ import React, { useState, useEffect, useMemo } from 'react'; import { View, StyleSheet, Switch, ScrollView, } from 'react-native'; import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context'; import { MaterialCommunityIcons } from '@expo/vector-icons'; import { spacing, borderRadius, useAppColors, type AppColors } from '../../theme'; import { Text } from '../../components/common'; import { loadNotificationPreferences, setPushNotificationsPreference, setSoundPreference, setVibrationPreference, } from '../../services/notificationPreferences'; import { useResponsive, useResponsiveSpacing } from '../../hooks'; // 内容最大宽度 const CONTENT_MAX_WIDTH = 720; interface NotificationSettingItem { key: string; title: string; subtitle?: string; icon: string; value: boolean; onValueChange: (value: boolean) => void; } export const NotificationSettingsScreen: React.FC = () => { const colors = useAppColors(); const styles = useMemo(() => createNotificationSettingsStyles(colors), [colors]); const [vibrationEnabled, setVibrationEnabledState] = useState(true); const [pushEnabled, setPushEnabled] = useState(true); const [soundEnabled, setSoundEnabled] = useState(true); const { isWideScreen, isMobile } = useResponsive(); const insets = useSafeAreaInsets(); // 底部间距,避免被 TabBar 遮挡 const scrollBottomInset = isMobile ? 64 + 24 + insets.bottom + spacing.md : spacing.md; // 加载设置(与启动时 hydrate 一致,避免从其它入口进页时 UI 与内存不一致) useEffect(() => { const loadSettings = async () => { try { const prefs = await loadNotificationPreferences(); setVibrationEnabledState(prefs.vibrationEnabled); setPushEnabled(prefs.pushEnabled); setSoundEnabled(prefs.soundEnabled); } catch (error) { console.error('加载通知设置失败:', error); } }; loadSettings(); }, []); const toggleVibration = async (value: boolean) => { try { setVibrationEnabledState(value); await setVibrationPreference(value); } catch (error) { console.error('保存震动设置失败:', error); } }; const togglePush = async (value: boolean) => { try { setPushEnabled(value); await setPushNotificationsPreference(value); } catch (error) { console.error('保存推送开关失败:', error); } }; const toggleSound = async (value: boolean) => { try { setSoundEnabled(value); await setSoundPreference(value); } catch (error) { console.error('保存提示音设置失败:', error); } }; const settings: NotificationSettingItem[] = [ { key: 'push', title: '接收推送通知', subtitle: '接收新消息、点赞、评论等推送', icon: 'bell-outline', value: pushEnabled, onValueChange: togglePush, }, { key: 'vibration', title: '消息震动', subtitle: '收到新消息时震动提醒', icon: 'vibrate', value: vibrationEnabled, onValueChange: toggleVibration, }, { key: 'sound', title: '消息提示音', subtitle: '收到新消息时播放提示音', icon: 'volume-high', value: soundEnabled, onValueChange: toggleSound, }, ]; // 渲染内容 const renderContent = () => ( <> {/* 消息通知设置 */} 消息通知 {settings.map((item, index) => ( {item.title} {item.subtitle && ( {item.subtitle} )} {index < settings.length - 1 && } ))} {/* 提示信息 */} 关闭推送通知后,您将不再收到任何消息提醒,但消息仍会在应用内显示。 ); const responsivePadding = useResponsiveSpacing({ xs: 8, sm: 12, md: 16, lg: 24, xl: 32 }); return ( {renderContent()} ); }; function createNotificationSettingsStyles(colors: AppColors) { return StyleSheet.create({ container: { flex: 1, backgroundColor: colors.background.default, }, scrollContent: { paddingVertical: spacing.md, }, section: { marginBottom: spacing.lg, }, sectionHeader: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: spacing.lg, marginBottom: spacing.sm, gap: spacing.xs, }, sectionTitle: { fontWeight: '600', }, card: { backgroundColor: colors.background.paper, marginHorizontal: spacing.lg, borderRadius: borderRadius.lg, overflow: 'hidden', maxWidth: CONTENT_MAX_WIDTH, alignSelf: 'center', width: '100%', }, settingItem: { flexDirection: 'row', alignItems: 'center', paddingVertical: spacing.md, paddingHorizontal: spacing.md, }, iconContainer: { width: 36, height: 36, borderRadius: borderRadius.md, backgroundColor: colors.primary.light + '20', justifyContent: 'center', alignItems: 'center', marginRight: spacing.md, }, settingContent: { flex: 1, }, subtitle: { marginTop: 2, }, divider: { height: 1, backgroundColor: colors.divider, marginLeft: 36 + spacing.md + spacing.md, }, tipContainer: { flexDirection: 'row', alignItems: 'flex-start', marginHorizontal: spacing.lg, padding: spacing.md, backgroundColor: colors.background.paper, borderRadius: borderRadius.lg, gap: spacing.sm, }, tipText: { flex: 1, lineHeight: 20, }, }); } export default NotificationSettingsScreen;