import { ThemedText } from '@/components/ThemedText'; import { useAuthGuard } from '@/hooks/useAuthGuard'; import { useNotifications } from '@/hooks/useNotifications'; import { getMedicationReminderEnabled, getNotificationEnabled, setMedicationReminderEnabled, setNotificationEnabled } from '@/utils/userPreferences'; import { Ionicons } from '@expo/vector-icons'; import { GlassView, isLiquidGlassAvailable } from 'expo-glass-effect'; import { LinearGradient } from 'expo-linear-gradient'; import { router, useFocusEffect } from 'expo-router'; import React, { useCallback, useState } from 'react'; import { Alert, Linking, ScrollView, StatusBar, StyleSheet, Switch, Text, TouchableOpacity, View } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; export default function NotificationSettingsScreen() { const insets = useSafeAreaInsets(); const { pushIfAuthedElseLogin } = useAuthGuard(); const { requestPermission, sendNotification } = useNotifications(); const isLgAvailable = isLiquidGlassAvailable(); // 通知设置状态 const [notificationEnabled, setNotificationEnabledState] = useState(false); const [medicationReminderEnabled, setMedicationReminderEnabledState] = useState(false); const [isLoading, setIsLoading] = useState(true); // 加载通知设置 const loadNotificationSettings = useCallback(async () => { try { const [notification, medicationReminder] = await Promise.all([ getNotificationEnabled(), getMedicationReminderEnabled(), ]); setNotificationEnabledState(notification); setMedicationReminderEnabledState(medicationReminder); } catch (error) { console.error('加载通知设置失败:', error); } finally { setIsLoading(false); } }, []); // 页面聚焦时加载设置 useFocusEffect( useCallback(() => { loadNotificationSettings(); }, [loadNotificationSettings]) ); // 处理总通知开关变化 const handleNotificationToggle = async (value: boolean) => { if (value) { try { // 先检查系统权限 const status = await requestPermission(); if (status === 'granted') { // 系统权限获取成功,保存用户偏好设置 await setNotificationEnabled(true); setNotificationEnabledState(true); // 发送测试通知 await sendNotification({ title: '通知已开启', body: '您将收到应用通知和提醒', sound: true, priority: 'normal', }); } else { // 系统权限被拒绝,不更新用户偏好设置 Alert.alert( '权限被拒绝', '请在系统设置中开启通知权限,然后再尝试开启推送功能', [ { text: '取消', style: 'cancel' }, { text: '去设置', onPress: () => Linking.openSettings() } ] ); } } catch (error) { console.error('开启推送通知失败:', error); Alert.alert('错误', '请求通知权限失败'); } } else { try { // 关闭推送,保存用户偏好设置 await setNotificationEnabled(false); setNotificationEnabledState(false); // 关闭总开关时,也关闭药品提醒 await setMedicationReminderEnabled(false); setMedicationReminderEnabledState(false); } catch (error) { console.error('关闭推送通知失败:', error); Alert.alert('错误', '保存设置失败'); } } }; // 处理药品通知提醒开关变化 const handleMedicationReminderToggle = async (value: boolean) => { try { await setMedicationReminderEnabled(value); setMedicationReminderEnabledState(value); if (value) { // 发送测试通知 await sendNotification({ title: '药品提醒已开启', body: '您将在用药时间收到提醒通知', sound: true, priority: 'high', }); } } catch (error) { console.error('设置药品提醒失败:', error); Alert.alert('错误', '保存设置失败'); } }; // 返回按钮 const BackButton = () => ( router.back()} style={styles.backButton} activeOpacity={0.7} > {isLgAvailable ? ( ) : ( )} ); // 开关项组件 const SwitchItem = ({ title, description, value, onValueChange, disabled = false }: { title: string; description: string; value: boolean; onValueChange: (value: boolean) => void; disabled?: boolean; }) => ( {title} {description} ); if (isLoading) { return ( 加载中... ); } return ( {/* 背景渐变 */} {/* 装饰性圆圈 */} {/* 头部 */} 通知设置 {/* 通知设置部分 */} 通知设置 {/* 药品提醒部分 */} 药品提醒 {/* 说明部分 */} 说明 • 消息推送是所有通知的总开关{'\n'} • 药品通知提醒需要在消息推送开启后才能使用{'\n'} • 您可以在系统设置中管理通知权限{'\n'} • 关闭消息推送将停止所有应用通知 ); } const styles = StyleSheet.create({ container: { flex: 1, }, gradientBackground: { position: 'absolute', left: 0, right: 0, top: 0, bottom: 0, }, decorativeCircle1: { position: 'absolute', top: 40, right: 20, width: 60, height: 60, borderRadius: 30, backgroundColor: '#0EA5E9', opacity: 0.1, }, decorativeCircle2: { position: 'absolute', bottom: -15, left: -15, width: 40, height: 40, borderRadius: 20, backgroundColor: '#0EA5E9', opacity: 0.05, }, scrollView: { flex: 1, }, loadingContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', }, loadingText: { fontSize: 16, color: '#666', }, header: { flexDirection: 'row', alignItems: 'center', marginBottom: 24, }, backButton: { marginRight: 16, }, glassButton: { width: 40, height: 40, borderRadius: 20, alignItems: 'center', justifyContent: 'center', overflow: 'hidden', }, fallbackButton: { backgroundColor: 'rgba(255, 255, 255, 0.9)', borderWidth: 1, borderColor: 'rgba(255, 255, 255, 0.3)', }, title: { fontSize: 28, fontWeight: 'bold', color: '#2C3E50', }, section: { marginBottom: 24, }, sectionTitle: { fontSize: 18, fontWeight: '600', color: '#2C3E50', marginBottom: 12, paddingHorizontal: 4, }, card: { backgroundColor: '#FFFFFF', borderRadius: 12, shadowColor: '#000', shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.05, shadowRadius: 4, elevation: 2, overflow: 'hidden', }, switchItem: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingVertical: 16, paddingHorizontal: 16, }, switchItemLeft: { flex: 1, marginRight: 16, }, switchItemTitle: { fontSize: 16, fontWeight: '500', color: '#2C3E50', marginBottom: 4, }, switchItemDescription: { fontSize: 14, color: '#6C757D', lineHeight: 20, }, switch: { transform: [{ scaleX: 0.8 }, { scaleY: 0.8 }], }, description: { fontSize: 14, color: '#6C757D', lineHeight: 22, paddingVertical: 16, paddingHorizontal: 16, }, });