Files
digital-pilates/utils/workoutPreferences.ts
richarjiang 971aebd560 feat(workout): 新增锻炼结束监听和个性化通知功能
实现了iOS HealthKit锻炼数据实时监听,当用户完成锻炼时自动发送个性化鼓励通知。包括锻炼类型筛选、时间范围控制、用户偏好设置等完整功能,并提供了测试工具和详细文档。
2025-10-13 10:05:02 +08:00

152 lines
5.3 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import AsyncStorage from '@/utils/kvStore';
const WORKOUT_NOTIFICATION_ENABLED_KEY = '@workout_notification_enabled';
const WORKOUT_NOTIFICATION_TIME_RANGE_KEY = '@workout_notification_time_range';
const WORKOUT_NOTIFICATION_TYPES_KEY = '@workout_notification_types';
export interface WorkoutNotificationPreferences {
enabled: boolean;
startTimeHour: number; // 开始时间小时0-23
endTimeHour: number; // 结束时间小时0-23
enabledWorkoutTypes: string[]; // 启用通知的锻炼类型
}
const DEFAULT_PREFERENCES: WorkoutNotificationPreferences = {
enabled: true,
startTimeHour: 8, // 早上8点
endTimeHour: 22, // 晚上10点
enabledWorkoutTypes: [] // 空数组表示所有类型都启用
};
/**
* 获取锻炼通知偏好设置
*/
export async function getWorkoutNotificationPreferences(): Promise<WorkoutNotificationPreferences> {
try {
const enabled = await AsyncStorage.getItem(WORKOUT_NOTIFICATION_ENABLED_KEY);
const timeRange = await AsyncStorage.getItem(WORKOUT_NOTIFICATION_TIME_RANGE_KEY);
const workoutTypes = await AsyncStorage.getItem(WORKOUT_NOTIFICATION_TYPES_KEY);
return {
enabled: enabled !== 'false', // 默认启用
startTimeHour: timeRange ? JSON.parse(timeRange).start : DEFAULT_PREFERENCES.startTimeHour,
endTimeHour: timeRange ? JSON.parse(timeRange).end : DEFAULT_PREFERENCES.endTimeHour,
enabledWorkoutTypes: workoutTypes ? JSON.parse(workoutTypes) : DEFAULT_PREFERENCES.enabledWorkoutTypes
};
} catch (error) {
console.error('获取锻炼通知偏好设置失败:', error);
return DEFAULT_PREFERENCES;
}
}
/**
* 保存锻炼通知偏好设置
*/
export async function saveWorkoutNotificationPreferences(preferences: Partial<WorkoutNotificationPreferences>): Promise<void> {
try {
const currentPrefs = await getWorkoutNotificationPreferences();
const newPrefs = { ...currentPrefs, ...preferences };
if (preferences.enabled !== undefined) {
await AsyncStorage.setItem(WORKOUT_NOTIFICATION_ENABLED_KEY, preferences.enabled.toString());
}
if (preferences.startTimeHour !== undefined || preferences.endTimeHour !== undefined) {
const timeRange = {
start: preferences.startTimeHour ?? currentPrefs.startTimeHour,
end: preferences.endTimeHour ?? currentPrefs.endTimeHour
};
await AsyncStorage.setItem(WORKOUT_NOTIFICATION_TIME_RANGE_KEY, JSON.stringify(timeRange));
}
if (preferences.enabledWorkoutTypes !== undefined) {
await AsyncStorage.setItem(WORKOUT_NOTIFICATION_TYPES_KEY, JSON.stringify(preferences.enabledWorkoutTypes));
}
console.log('锻炼通知偏好设置已保存:', newPrefs);
} catch (error) {
console.error('保存锻炼通知偏好设置失败:', error);
throw error;
}
}
/**
* 检查当前时间是否在允许的通知时间范围内
*/
export async function isNotificationTimeAllowed(): Promise<boolean> {
try {
const preferences = await getWorkoutNotificationPreferences();
const currentHour = new Date().getHours();
// 处理跨天的情况(例如 22:00 - 8:00
if (preferences.startTimeHour <= preferences.endTimeHour) {
// 正常情况,如 8:00 - 22:00
return currentHour >= preferences.startTimeHour && currentHour <= preferences.endTimeHour;
} else {
// 跨天情况,如 22:00 - 8:00
return currentHour >= preferences.startTimeHour || currentHour <= preferences.endTimeHour;
}
} catch (error) {
console.error('检查通知时间失败:', error);
return true; // 默认允许
}
}
/**
* 检查特定锻炼类型是否启用了通知
*/
export async function isWorkoutTypeEnabled(workoutType: string): Promise<boolean> {
try {
const preferences = await getWorkoutNotificationPreferences();
// 如果启用的类型列表为空,表示所有类型都启用
if (preferences.enabledWorkoutTypes.length === 0) {
return true;
}
return preferences.enabledWorkoutTypes.includes(workoutType);
} catch (error) {
console.error('检查锻炼类型通知设置失败:', error);
return true; // 默认允许
}
}
/**
* 获取锻炼通知的简化状态(仅检查是否启用)
*/
export async function getWorkoutNotificationEnabled(): Promise<boolean> {
try {
const preferences = await getWorkoutNotificationPreferences();
return preferences.enabled;
} catch (error) {
console.error('获取锻炼通知启用状态失败:', error);
return true; // 默认启用
}
}
/**
* 设置锻炼通知启用状态
*/
export async function setWorkoutNotificationEnabled(enabled: boolean): Promise<void> {
try {
await saveWorkoutNotificationPreferences({ enabled });
} catch (error) {
console.error('设置锻炼通知启用状态失败:', error);
throw error;
}
}
/**
* 重置锻炼通知偏好设置为默认值
*/
export async function resetWorkoutNotificationPreferences(): Promise<void> {
try {
await AsyncStorage.removeItem(WORKOUT_NOTIFICATION_ENABLED_KEY);
await AsyncStorage.removeItem(WORKOUT_NOTIFICATION_TIME_RANGE_KEY);
await AsyncStorage.removeItem(WORKOUT_NOTIFICATION_TYPES_KEY);
console.log('锻炼通知偏好设置已重置为默认值');
} catch (error) {
console.error('重置锻炼通知偏好设置失败:', error);
throw error;
}
}