import { HeaderBar } from '@/components/ui/HeaderBar'; import { palette } from '@/constants/Colors'; import { useI18n } from '@/hooks/useI18n'; import { useNotifications } from '@/hooks/useNotifications'; import { useSafeAreaTop } from '@/hooks/useSafeAreaWithPadding'; import { getMedicationReminderEnabled, getMoodReminderEnabled, getNotificationEnabled, getNutritionReminderEnabled, setMedicationReminderEnabled, setMoodReminderEnabled, setNotificationEnabled, setNutritionReminderEnabled } from '@/utils/userPreferences'; import { Ionicons } from '@expo/vector-icons'; 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, View } from 'react-native'; export default function NotificationSettingsScreen() { const safeAreaTop = useSafeAreaTop(60); const { t } = useI18n(); const { requestPermission, sendNotification } = useNotifications(); // 通知设置状态 const [notificationEnabled, setNotificationEnabledState] = useState(false); const [medicationReminderEnabled, setMedicationReminderEnabledState] = useState(false); const [nutritionReminderEnabled, setNutritionReminderEnabledState] = useState(false); const [moodReminderEnabled, setMoodReminderEnabledState] = useState(false); const [isLoading, setIsLoading] = useState(true); // 加载通知设置 const loadNotificationSettings = useCallback(async () => { try { const [notification, medicationReminder, nutritionReminder, moodReminder] = await Promise.all([ getNotificationEnabled(), getMedicationReminderEnabled(), getNutritionReminderEnabled(), getMoodReminderEnabled(), ]); setNotificationEnabledState(notification); setMedicationReminderEnabledState(medicationReminder); setNutritionReminderEnabledState(nutritionReminder); setMoodReminderEnabledState(moodReminder); } catch (error) { console.error('Failed to load notification settings:', 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: t('notificationSettings.alerts.notificationsEnabled.title'), body: t('notificationSettings.alerts.notificationsEnabled.body'), sound: true, priority: 'normal', }); } else { // 系统权限被拒绝,不更新用户偏好设置 Alert.alert( t('notificationSettings.alerts.permissionDenied.title'), t('notificationSettings.alerts.permissionDenied.message'), [ { text: t('notificationSettings.alerts.permissionDenied.cancel'), style: 'cancel' }, { text: t('notificationSettings.alerts.permissionDenied.goToSettings'), onPress: () => Linking.openSettings() } ] ); } } catch (error) { console.error('Failed to enable push notifications:', error); Alert.alert(t('notificationSettings.alerts.error.title'), t('notificationSettings.alerts.error.message')); } } else { try { // 关闭推送,保存用户偏好设置 await setNotificationEnabled(false); setNotificationEnabledState(false); // 关闭总开关时,也关闭所有提醒 await setMedicationReminderEnabled(false); setMedicationReminderEnabledState(false); await setNutritionReminderEnabled(false); setNutritionReminderEnabledState(false); await setMoodReminderEnabled(false); setMoodReminderEnabledState(false); } catch (error) { console.error('Failed to disable push notifications:', error); Alert.alert(t('notificationSettings.alerts.error.title'), t('notificationSettings.alerts.error.saveFailed')); } } }; // 处理药品通知提醒开关变化 const handleMedicationReminderToggle = async (value: boolean) => { try { await setMedicationReminderEnabled(value); setMedicationReminderEnabledState(value); if (value) { // 发送测试通知 await sendNotification({ title: t('notificationSettings.alerts.medicationReminderEnabled.title'), body: t('notificationSettings.alerts.medicationReminderEnabled.body'), sound: true, priority: 'high', }); } } catch (error) { console.error('Failed to set medication reminder:', error); Alert.alert(t('notificationSettings.alerts.error.title'), t('notificationSettings.alerts.error.medicationReminderFailed')); } }; // 处理营养通知提醒开关变化 const handleNutritionReminderToggle = async (value: boolean) => { try { await setNutritionReminderEnabled(value); setNutritionReminderEnabledState(value); if (value) { // 发送测试通知 await sendNotification({ title: t('notificationSettings.alerts.nutritionReminderEnabled.title'), body: t('notificationSettings.alerts.nutritionReminderEnabled.body'), sound: true, priority: 'high', }); } } catch (error) { console.error('Failed to set nutrition reminder:', error); Alert.alert(t('notificationSettings.alerts.error.title'), t('notificationSettings.alerts.error.nutritionReminderFailed')); } }; // 处理心情通知提醒开关变化 const handleMoodReminderToggle = async (value: boolean) => { try { await setMoodReminderEnabled(value); setMoodReminderEnabledState(value); if (value) { // 发送测试通知 await sendNotification({ title: t('notificationSettings.alerts.moodReminderEnabled.title'), body: t('notificationSettings.alerts.moodReminderEnabled.body'), sound: true, priority: 'high', }); } } catch (error) { console.error('Failed to set mood reminder:', error); Alert.alert(t('notificationSettings.alerts.error.title'), t('notificationSettings.alerts.error.moodReminderFailed')); } }; // 渲染设置项 const renderSettingItem = ( icon: keyof typeof Ionicons.glyphMap, title: string, description: string, value: boolean, onValueChange: (value: boolean) => void, disabled: boolean = false, showSeparator: boolean = true ) => ( {title} {description} {showSeparator && ( )} ); if (isLoading) { return ( {t('notificationSettings.loading')} ); } return ( router.back()} /> {/* 顶部说明卡片 */} {t('notificationSettings.sections.description')} {t('notificationSettings.description.text')} {/* 设置项列表 */} {renderSettingItem( 'notifications-outline', t('notificationSettings.items.pushNotifications.title'), t('notificationSettings.items.pushNotifications.description'), notificationEnabled, handleNotificationToggle, false, true )} {renderSettingItem( 'medkit-outline', t('notificationSettings.items.medicationReminder.title'), t('notificationSettings.items.medicationReminder.description'), medicationReminderEnabled, handleMedicationReminderToggle, !notificationEnabled, true )} {renderSettingItem( 'restaurant-outline', t('notificationSettings.items.nutritionReminder.title'), t('notificationSettings.items.nutritionReminder.description'), nutritionReminderEnabled, handleNutritionReminderToggle, !notificationEnabled, true )} {renderSettingItem( 'happy-outline', t('notificationSettings.items.moodReminder.title'), t('notificationSettings.items.moodReminder.description'), moodReminderEnabled, handleMoodReminderToggle, !notificationEnabled, false )} ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#F5F5F5', }, gradientBackground: { position: 'absolute', left: 0, right: 0, top: 0, height: '60%', }, scrollView: { flex: 1, }, scrollContent: { paddingHorizontal: 16, paddingBottom: 40, }, loadingContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', }, loadingText: { fontSize: 16, color: '#666', }, headerSection: { marginBottom: 20, }, subtitle: { fontSize: 14, color: '#6C757D', marginBottom: 12, marginLeft: 4, }, descriptionCard: { backgroundColor: 'rgba(255, 255, 255, 0.6)', borderRadius: 12, padding: 12, gap: 8, borderWidth: 1, borderColor: 'rgba(147, 112, 219, 0.1)', }, hintRow: { flexDirection: 'row', alignItems: 'center', gap: 8, }, descriptionText: { flex: 1, fontSize: 13, color: '#2C3E50', lineHeight: 18, }, sectionContainer: { backgroundColor: '#FFFFFF', borderRadius: 20, marginBottom: 20, overflow: 'hidden', shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.03, shadowRadius: 8, elevation: 2, }, settingItem: { flexDirection: 'row', alignItems: 'center', padding: 16, paddingVertical: 16, }, itemInfo: { flex: 1, flexDirection: 'row', alignItems: 'center', gap: 12, }, iconContainer: { width: 40, height: 40, alignItems: 'center', justifyContent: 'center', backgroundColor: 'rgba(147, 112, 219, 0.05)', borderRadius: 12, }, iconContainerDisabled: { backgroundColor: '#F5F5F5', }, textContainer: { flex: 1, marginRight: 8, }, itemTitle: { fontSize: 16, fontWeight: '500', color: '#2C3E50', marginBottom: 4, }, itemTitleDisabled: { color: '#999', }, itemDescription: { fontSize: 12, color: '#6C757D', lineHeight: 16, }, switch: { transform: [{ scaleX: 0.9 }, { scaleY: 0.9 }], }, separatorContainer: { paddingLeft: 68, // 40(icon) + 12(gap) + 16(padding) paddingRight: 16, }, separator: { height: 1, backgroundColor: '#F0F0F0', }, });