Refactor: Remove background task management and related hooks

- Deleted `useBackgroundTasks.ts` hook and its associated logic for managing background tasks.
- Removed `backgroundTaskManager.ts` service and all related task definitions and registrations.
- Cleaned up `Podfile.lock` and `package.json` to remove unused dependencies related to background tasks.
- Updated iOS project files to eliminate references to removed background task components.
- Added new background fetch identifier in `Info.plist` for future use.
This commit is contained in:
richarjiang
2025-09-05 09:47:49 +08:00
parent cb89ee7bc2
commit acb3907344
60 changed files with 77 additions and 2230 deletions

View File

@@ -13,9 +13,7 @@ import { Colors } from '@/constants/Colors';
import { getTabBarBottomPadding } from '@/constants/TabBar';
import { useAppDispatch, useAppSelector } from '@/hooks/redux';
import { useAuthGuard } from '@/hooks/useAuthGuard';
import { useBackgroundTasks } from '@/hooks/useBackgroundTasks';
import { notificationService } from '@/services/notifications';
import { backgroundTaskManager } from '@/services/backgroundTaskManager';
import { selectHealthDataByDate, setHealthData } from '@/store/healthSlice';
import { fetchDailyMoodCheckins, selectLatestMoodRecordByDate } from '@/store/moodSlice';
import { fetchDailyNutritionData, selectNutritionSummaryByDate } from '@/store/nutritionSlice';
@@ -38,8 +36,8 @@ import {
ScrollView,
StyleSheet,
Text,
View,
TouchableOpacity
TouchableOpacity,
View
} from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
@@ -150,7 +148,6 @@ export default function ExploreScreen() {
});
}, [userProfile]);
const { registerTask, isInitialized } = useBackgroundTasks();
// 心情相关状态
const dispatch = useAppDispatch();
const [isMoodLoading, setIsMoodLoading] = useState(false);
@@ -416,49 +413,6 @@ export default function ExploreScreen() {
};
}, [loadAllData, currentSelectedDate]);
useEffect(() => {
// 只有在后台任务管理器初始化完成后才注册任务
if (isInitialized) {
console.log('后台任务管理器已初始化,开始注册健康数据任务...');
registerTask({
id: 'health-data-task',
name: 'health-data-task',
handler: async () => {
try {
console.log('后台任务:更新健康数据和检查压力水平...');
// 发送测试通知,验证后台任务是否执行
await notificationService.sendImmediateNotification({
title: '后台任务测试 🔔',
body: `任务执行时间: ${new Date().toLocaleTimeString('zh-CN')}`,
data: {
type: 'background_task_test',
timestamp: new Date().toISOString(),
},
sound: true,
priority: 'high'
});
// 后台任务只更新健康数据,强制刷新以获取最新数据
await loadHealthData(undefined, true);
// 执行压力检查
await checkStressLevelAndNotify();
// 执行喝水目标检查
await checkWaterGoalAndNotify();
} catch (error) {
console.error('健康数据任务执行失败:', error);
}
},
}).then(() => {
console.log('健康数据任务注册成功');
}).catch((error) => {
console.error('健康数据任务注册失败:', error);
});
}
}, [isInitialized]);
// 检查压力水平并发送通知
const checkStressLevelAndNotify = React.useCallback(async () => {
try {
@@ -627,7 +581,7 @@ export default function ExploreScreen() {
style={styles.debugButton}
onPress={async () => {
console.log('🔧 手动触发后台任务测试...');
await backgroundTaskManager.debugExecuteBackgroundTask();
// await backgroundTaskManager.triggerTaskForTesting();
}}
>
<Text style={styles.debugButtonText}>🔧</Text>

View File

@@ -8,7 +8,6 @@ import 'react-native-reanimated';
import PrivacyConsentModal from '@/components/PrivacyConsentModal';
import { useAppDispatch, useAppSelector } from '@/hooks/redux';
import { clearAiCoachSessionCache } from '@/services/aiCoachSession';
import { backgroundTaskManager } from '@/services/backgroundTaskManager';
import { notificationService } from '@/services/notifications';
import { store } from '@/store';
import { rehydrateUser, setPrivacyAgreed } from '@/store/userSlice';
@@ -31,16 +30,6 @@ function Bootstrapper({ children }: { children: React.ReactNode }) {
await dispatch(rehydrateUser());
setUserDataLoaded(true);
};
const initializeBackgroundTasks = async () => {
try {
await backgroundTaskManager.initialize();
console.log('后台任务管理器初始化成功');
} catch (error) {
console.error('后台任务管理器初始化失败:', error);
}
};
const initializeNotifications = async () => {
try {
// 初始化通知服务
@@ -52,7 +41,6 @@ function Bootstrapper({ children }: { children: React.ReactNode }) {
};
loadUserData();
initializeBackgroundTasks();
initializeNotifications();
// 冷启动时清空 AI 教练会话缓存
clearAiCoachSessionCache();

View File

@@ -7,13 +7,14 @@ import { addDietRecord, type CreateDietRecordDto, type MealType } from '@/servic
import { selectFoodRecognitionResult } from '@/store/foodRecognitionSlice';
import { Ionicons } from '@expo/vector-icons';
import dayjs from 'dayjs';
import { Image } from 'expo-image';
import { LinearGradient } from 'expo-linear-gradient';
import { useLocalSearchParams, useRouter } from 'expo-router';
import React, { useEffect, useState } from 'react';
import {
ActivityIndicator,
BackHandler,
Image,
Modal,
Pressable,
ScrollView,
@@ -297,7 +298,7 @@ export default function FoodAnalysisResultScreen() {
<Image
source={{ uri: imageUri }}
style={styles.foodImage}
resizeMode="cover"
cachePolicy={'memory-disk'}
/>
{/* 预览提示图标 */}
<View style={styles.previewHint}>

View File

@@ -3,21 +3,19 @@ import { Colors } from '@/constants/Colors';
import { useAppDispatch, useAppSelector } from '@/hooks/redux';
import { useColorScheme } from '@/hooks/useColorScheme';
import { useMoodData } from '@/hooks/useMoodData';
import { getMoodOptions, MoodOption } from '@/services/moodCheckins';
import { getMoodOptions } from '@/services/moodCheckins';
import { selectLatestMoodRecordByDate } from '@/store/moodSlice';
import { Image } from 'react-native';
import dayjs from 'dayjs';
import { LinearGradient } from 'expo-linear-gradient';
import { router, useFocusEffect, useLocalSearchParams } from 'expo-router';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import {
Dimensions,
SafeAreaView,
Dimensions, Image, SafeAreaView,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View,
View
} from 'react-native';
const { width } = Dimensions.get('window');
@@ -60,7 +58,7 @@ export default function MoodCalendarScreen() {
// 使用 useRef 来存储函数引用,避免依赖循环
const fetchMoodRecordsRef = useRef(fetchMoodRecords);
const fetchMoodHistoryRecordsRef = useRef(fetchMoodHistoryRecords);
// 更新 ref 值
fetchMoodRecordsRef.current = fetchMoodRecords;
fetchMoodHistoryRecordsRef.current = fetchMoodHistoryRecords;
@@ -73,7 +71,7 @@ export default function MoodCalendarScreen() {
// 使用 Redux store 中的数据
const moodRecords = useAppSelector(state => state.mood.moodRecords);
// 获取选中日期的数据
const selectedDateMood = useAppSelector(state => {
if (!selectedDay) return null;
@@ -191,46 +189,30 @@ export default function MoodCalendarScreen() {
const moodRecord = dayRecords.length > 0 ? dayRecords[0] : null;
const isToday = day === new Date().getDate() &&
month === new Date().getMonth() + 1 &&
year === new Date().getFullYear();
month === new Date().getMonth() + 1 &&
year === new Date().getFullYear();
if (moodRecord) {
const mood = moodOptions.find(m => m.type === moodRecord.moodType);
const intensity = moodRecord.intensity;
const color = mood?.color || '#7a5af8';
// 计算圆环的填充比例 (0-1)
const fillRatio = intensity / 10;
return (
<View style={isToday ? styles.todayMoodRingContainer : styles.moodRingContainer}>
<View style={[isToday ? styles.todayMoodRing : styles.moodRing, { borderColor: color }]}>
<View style={[
styles.moodRingFill,
{
backgroundColor: color,
height: `${fillRatio * 100}%`,
opacity: 0.7,
}
]} />
<Text style={[styles.moodIntensityText, { color: '#fff', fontSize: isToday ? 7 : 8 }]}>
{intensity}
</Text>
<View style={isToday ? styles.todayMoodIconContainer : styles.moodIconContainer}>
<View style={styles.moodIcon}>
<Image
source={mood?.image}
style={styles.moodIconImage}
/>
</View>
</View>
);
}
return (
<View style={isToday ? styles.todayDefaultMoodRing : styles.defaultMoodRing}>
<View style={isToday ? styles.todayDefaultMoodRingBorder : styles.defaultMoodRingBorder} />
<View style={isToday ? styles.todayDefaultMoodIcon : styles.defaultMoodIcon}>
</View>
);
};
// 使用统一的渐变背景色
const backgroundGradientColors = [colorTokens.backgroundGradientStart, colorTokens.backgroundGradientEnd] as const;
return (
<View style={styles.container}>
<LinearGradient
@@ -242,7 +224,7 @@ export default function MoodCalendarScreen() {
{/* 装饰性圆圈 */}
<View style={styles.decorativeCircle1} />
<View style={styles.decorativeCircle2} />
<SafeAreaView style={styles.safeArea}>
<HeaderBar
title="心情日历"
@@ -538,6 +520,20 @@ const styles = StyleSheet.create({
shadowRadius: 2,
elevation: 1,
},
todayMoodIconContainer: {
position: 'absolute',
bottom: 1,
width: 20,
height: 20,
borderRadius: 10,
justifyContent: 'center',
alignItems: 'center',
shadowColor: '#7a5af8',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.2,
shadowRadius: 2,
elevation: 2,
},
moodIcon: {
width: 18,
height: 18,
@@ -547,8 +543,8 @@ const styles = StyleSheet.create({
alignItems: 'center',
},
moodIconImage: {
width: 18,
height: 18,
width: 28,
height: 28,
borderRadius: 9,
},
defaultMoodIcon: {
@@ -564,10 +560,18 @@ const styles = StyleSheet.create({
alignItems: 'center',
backgroundColor: 'rgba(122,90,248,0.05)',
},
defaultMoodEmoji: {
fontSize: 10,
opacity: 0.4,
color: '#7a5af8',
todayDefaultMoodIcon: {
position: 'absolute',
bottom: 1,
width: 20,
height: 20,
borderRadius: 10,
borderWidth: 1.5,
borderColor: 'rgba(122,90,248,0.4)',
borderStyle: 'dashed',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(122,90,248,0.08)',
},
moodRingContainer: {
position: 'absolute',
@@ -577,29 +581,7 @@ const styles = StyleSheet.create({
justifyContent: 'center',
alignItems: 'center',
},
moodRing: {
width: 20,
height: 20,
borderRadius: 10,
borderWidth: 1.5,
justifyContent: 'flex-end',
alignItems: 'center',
overflow: 'hidden',
backgroundColor: 'rgba(255,255,255,0.95)',
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,
shadowRadius: 2,
elevation: 1,
},
moodRingFill: {
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
borderBottomLeftRadius: 8,
borderBottomRightRadius: 8,
},
moodIntensityText: {
fontSize: 8,
fontWeight: '800',
@@ -610,63 +592,8 @@ const styles = StyleSheet.create({
textShadowOffset: { width: 0, height: 0.5 },
textShadowRadius: 1,
},
defaultMoodRing: {
position: 'absolute',
bottom: 2,
width: 22,
height: 22,
justifyContent: 'center',
alignItems: 'center',
},
defaultMoodRingBorder: {
width: 20,
height: 20,
borderRadius: 10,
borderWidth: 1.5,
borderColor: 'rgba(122,90,248,0.3)',
borderStyle: 'dashed',
backgroundColor: 'rgba(122,90,248,0.05)',
},
todayMoodRingContainer: {
position: 'absolute',
bottom: 1,
width: 20,
height: 20,
justifyContent: 'center',
alignItems: 'center',
},
todayMoodRing: {
width: 18,
height: 18,
borderRadius: 9,
borderWidth: 1.5,
justifyContent: 'flex-end',
alignItems: 'center',
overflow: 'hidden',
backgroundColor: 'rgba(255,255,255,0.95)',
shadowColor: '#7a5af8',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.2,
shadowRadius: 2,
elevation: 2,
},
todayDefaultMoodRing: {
position: 'absolute',
bottom: 1,
width: 20,
height: 20,
justifyContent: 'center',
alignItems: 'center',
},
todayDefaultMoodRingBorder: {
width: 18,
height: 18,
borderRadius: 9,
borderWidth: 1.5,
borderColor: 'rgba(122,90,248,0.4)',
borderStyle: 'dashed',
backgroundColor: 'rgba(122,90,248,0.08)',
},
selectedDateSection: {
backgroundColor: 'rgba(255,255,255,0.95)',
margin: 16,
@@ -720,7 +647,7 @@ const styles = StyleSheet.create({
width: 52,
height: 52,
borderRadius: 26,
backgroundColor: '#7a5af8',
backgroundColor: '#e9e7f1ff',
justifyContent: 'center',
alignItems: 'center',
marginRight: 16,