feat: 集成推送通知功能及相关组件

- 在项目中引入expo-notifications库,支持本地推送通知功能
- 实现通知权限管理,用户可选择开启或关闭通知
- 新增通知发送、定时通知和重复通知功能
- 更新个人页面,集成通知开关和权限请求逻辑
- 编写推送通知功能实现文档,详细描述功能和使用方法
- 优化心情日历页面,确保数据实时刷新
This commit is contained in:
2025-08-22 22:00:05 +08:00
parent c12329bc96
commit 7d28b79d86
20 changed files with 2368 additions and 280 deletions

157
hooks/useNotifications.ts Normal file
View File

@@ -0,0 +1,157 @@
import { useEffect, useState, useCallback } from 'react';
import { notificationService, NotificationData, NotificationTypes } from '../services/notifications';
import * as Notifications from 'expo-notifications';
export interface UseNotificationsReturn {
isInitialized: boolean;
permissionStatus: Notifications.PermissionStatus | null;
initialize: () => Promise<void>;
requestPermission: () => Promise<Notifications.PermissionStatus>;
sendNotification: (notification: NotificationData) => Promise<string>;
scheduleNotification: (notification: NotificationData, date: Date) => Promise<string>;
scheduleRepeatingNotification: (
notification: NotificationData,
interval: {
seconds?: number;
minutes?: number;
hours?: number;
days?: number;
weeks?: number;
months?: number;
years?: number;
}
) => Promise<string>;
cancelNotification: (notificationId: string) => Promise<void>;
cancelAllNotifications: () => Promise<void>;
getAllScheduledNotifications: () => Promise<Notifications.NotificationRequest[]>;
sendWorkoutReminder: (title: string, body: string, date?: Date) => Promise<string>;
sendGoalAchievement: (title: string, body: string) => Promise<string>;
sendMoodCheckinReminder: (title: string, body: string, date?: Date) => Promise<string>;
}
export const useNotifications = (): UseNotificationsReturn => {
const [isInitialized, setIsInitialized] = useState(false);
const [permissionStatus, setPermissionStatus] = useState<Notifications.PermissionStatus | null>(null);
const initialize = useCallback(async () => {
try {
await notificationService.initialize();
const status = await notificationService.getPermissionStatus();
setPermissionStatus(status);
setIsInitialized(true);
} catch (error) {
console.error('初始化通知服务失败:', error);
}
}, []);
const requestPermission = useCallback(async () => {
try {
const status = await notificationService.requestPermission();
setPermissionStatus(status);
return status;
} catch (error) {
console.error('请求通知权限失败:', error);
throw error;
}
}, []);
const sendNotification = useCallback(async (notification: NotificationData) => {
return notificationService.sendImmediateNotification(notification);
}, []);
const scheduleNotification = useCallback(async (notification: NotificationData, date: Date) => {
return notificationService.scheduleNotificationAtDate(notification, date);
}, []);
const scheduleRepeatingNotification = useCallback(async (
notification: NotificationData,
interval: {
seconds?: number;
minutes?: number;
hours?: number;
days?: number;
weeks?: number;
months?: number;
years?: number;
}
) => {
return notificationService.scheduleRepeatingNotification(notification, interval);
}, []);
const cancelNotification = useCallback(async (notificationId: string) => {
return notificationService.cancelNotification(notificationId);
}, []);
const cancelAllNotifications = useCallback(async () => {
return notificationService.cancelAllNotifications();
}, []);
const getAllScheduledNotifications = useCallback(async () => {
return notificationService.getAllScheduledNotifications();
}, []);
const sendWorkoutReminder = useCallback(async (title: string, body: string, date?: Date) => {
const notification: NotificationData = {
title,
body,
data: { type: NotificationTypes.WORKOUT_REMINDER },
sound: true,
priority: 'high',
};
if (date) {
return notificationService.scheduleNotificationAtDate(notification, date);
} else {
return notificationService.sendImmediateNotification(notification);
}
}, []);
const sendGoalAchievement = useCallback(async (title: string, body: string) => {
const notification: NotificationData = {
title,
body,
data: { type: NotificationTypes.GOAL_ACHIEVEMENT },
sound: true,
priority: 'high',
};
return notificationService.sendImmediateNotification(notification);
}, []);
const sendMoodCheckinReminder = useCallback(async (title: string, body: string, date?: Date) => {
const notification: NotificationData = {
title,
body,
data: { type: NotificationTypes.MOOD_CHECKIN },
sound: true,
priority: 'normal',
};
if (date) {
return notificationService.scheduleNotificationAtDate(notification, date);
} else {
return notificationService.sendImmediateNotification(notification);
}
}, []);
// 组件挂载时自动初始化
useEffect(() => {
initialize();
}, [initialize]);
return {
isInitialized,
permissionStatus,
initialize,
requestPermission,
sendNotification,
scheduleNotification,
scheduleRepeatingNotification,
cancelNotification,
cancelAllNotifications,
getAllScheduledNotifications,
sendWorkoutReminder,
sendGoalAchievement,
sendMoodCheckinReminder,
};
};