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',
},
});