diff --git a/app/(tabs)/fasting.tsx b/app/(tabs)/fasting.tsx
index c511f7a..ad30790 100644
--- a/app/(tabs)/fasting.tsx
+++ b/app/(tabs)/fasting.tsx
@@ -24,6 +24,7 @@ import {
} from '@/utils/fasting';
import { useFocusEffect } from '@react-navigation/native';
import { useRouter } from 'expo-router';
+import dayjs from 'dayjs';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { ScrollView, StyleSheet, Text, View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
@@ -154,6 +155,53 @@ export default function FastingTabScreen() {
}
}, [notificationsReady, notificationsLoading, notificationError, notificationIds, lastSyncTime, activeSchedule?.startISO, currentPlan?.id]);
+ useEffect(() => {
+ if (!activeSchedule || !currentPlan) return;
+ if (phase !== 'completed') return;
+
+ const start = dayjs(activeSchedule.startISO);
+ const end = dayjs(activeSchedule.endISO);
+ if (!start.isValid() || !end.isValid()) return;
+
+ const now = dayjs();
+ if (now.isBefore(end)) return;
+
+ const fastingHours = currentPlan.fastingHours;
+ const eatingHours = currentPlan.eatingHours;
+ const cycleHours = fastingHours + eatingHours;
+
+ if (fastingHours <= 0 || cycleHours <= 0) return;
+
+ let nextStart = start;
+ let nextEnd = end;
+ let iterations = 0;
+ const maxIterations = 60;
+
+ while (!now.isBefore(nextEnd)) {
+ nextStart = nextStart.add(cycleHours, 'hour');
+ nextEnd = nextStart.add(fastingHours, 'hour');
+ iterations += 1;
+
+ if (iterations >= maxIterations) {
+ if (__DEV__) {
+ console.warn('自动续订断食周期失败: 超出最大迭代次数', {
+ start: activeSchedule.startISO,
+ end: activeSchedule.endISO,
+ planId: currentPlan.id,
+ });
+ }
+ return;
+ }
+ }
+
+ if (iterations === 0) return;
+
+ dispatch(rescheduleActivePlan({
+ start: nextStart.toDate().toISOString(),
+ origin: 'auto',
+ }));
+ }, [dispatch, activeSchedule, currentPlan, phase]);
+
const handleAdjustStart = () => {
if (!currentPlan) return;
setShowPicker(true);
@@ -213,6 +261,7 @@ export default function FastingTabScreen() {
endTimeLabel={displayWindow.endTimeLabel}
onAdjustStartPress={handleAdjustStart}
onViewMealsPress={handleViewMeal}
+ onResetPress={handleResetPlan}
progress={progress}
/>
)}
@@ -233,9 +282,6 @@ export default function FastingTabScreen() {
如果计划与作息不符,可重新选择方案或调整开始时间。
-
- 重置
-
)}
@@ -325,20 +371,10 @@ const styles = StyleSheet.create({
lineHeight: 20,
},
resetRow: {
- flexDirection: 'row',
- justifyContent: 'space-between',
- alignItems: 'center',
marginTop: 16,
},
resetHint: {
- flex: 1,
fontSize: 12,
color: '#8A96A3',
- marginRight: 12,
- },
- resetAction: {
- fontSize: 12,
- fontWeight: '600',
- color: '#6366F1',
},
});
diff --git a/components/fasting/FastingOverviewCard.tsx b/components/fasting/FastingOverviewCard.tsx
index faf5f8e..6aa087a 100644
--- a/components/fasting/FastingOverviewCard.tsx
+++ b/components/fasting/FastingOverviewCard.tsx
@@ -2,9 +2,13 @@ import { CircularRing } from '@/components/CircularRing';
import { Colors } from '@/constants/Colors';
import type { FastingPlan } from '@/constants/Fasting';
import { useColorScheme } from '@/hooks/useColorScheme';
+import { Ionicons } from '@expo/vector-icons';
+import { GlassView, isLiquidGlassAvailable } from 'expo-glass-effect';
import { LinearGradient } from 'expo-linear-gradient';
-import React from 'react';
+import React, { useState } from 'react';
import {
+ Modal,
+ Pressable,
StyleSheet,
Text,
TouchableOpacity,
@@ -22,6 +26,7 @@ type FastingOverviewCardProps = {
endTimeLabel: string;
onAdjustStartPress: () => void;
onViewMealsPress: () => void;
+ onResetPress: () => void;
progress: number;
};
@@ -36,93 +41,149 @@ export function FastingOverviewCard({
endTimeLabel,
onAdjustStartPress,
onViewMealsPress,
+ onResetPress,
progress,
}: FastingOverviewCardProps) {
const theme = useColorScheme() ?? 'light';
const colors = Colors[theme];
const themeColors = plan?.theme;
+ const [showResetInfo, setShowResetInfo] = useState(false);
+ const isGlassAvailable = isLiquidGlassAvailable();
return (
-
-
-
- 轻断食计划
- {plan?.id && (
-
-
- {plan.id}
+ <>
+
+
+
+ 轻断食计划
+ {plan?.id && (
+
+
+ {plan.id}
+
+
+ )}
+
+ {plan?.badge && (
+
+
+ {plan.badge}
)}
- {plan?.badge && (
-
-
- {plan.badge}
+
+
+
+ 断食开始时间
+ {startDayLabel}
+ {startTimeLabel}
+
+
+
+ 断食结束时间
+ {endDayLabel}
+ {endTimeLabel}
+
+
+
+
+
+
+
+ {phaseLabel}
+ {countdownLabel}
+ {countdownValue}
+
+
+
+
+
+
+
+ 提前开始断食
-
- )}
-
+
-
-
- 断食开始时间
- {startDayLabel}
- {startTimeLabel}
-
-
-
- 断食结束时间
- {endDayLabel}
- {endTimeLabel}
-
-
+
+
+ 重置
+
+
-
-
-
-
- {phaseLabel}
- {countdownLabel}
- {countdownValue}
-
+ {isGlassAvailable ? (
+
+ setShowResetInfo(true)} style={styles.infoButtonInner}>
+
+
+
+ ) : (
+ setShowResetInfo(true)}
+ style={[styles.infoButton, styles.fallbackInfoButton]}
+ >
+
+
+ )}
-
+
-
- setShowResetInfo(false)}
+ >
+ setShowResetInfo(false)}
>
-
- 提前开始断食
-
-
- {/*
- 查看食谱
- */}
-
-
+ { }}>
+
+ 重置断食计划
+
+ 重置将清除当前活跃的断食计划和时间安排。您可以重新选择适合的计划或调整开始时间。
+
+
+ 如果计划与您的作息不符,建议先尝试调整开始时间,而不是完全重置。
+
+ setShowResetInfo(false)}
+ >
+ 我知道了
+
+
+
+
+ >
);
}
@@ -258,6 +319,70 @@ const styles = StyleSheet.create({
fontSize: 15,
fontWeight: '600',
},
+ infoButton: {
+ width: 36,
+ height: 36,
+ borderRadius: 18,
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginLeft: 8,
+ },
+ infoButtonInner: {
+ width: '100%',
+ height: '100%',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ fallbackInfoButton: {
+ backgroundColor: 'rgba(255,255,255,0.3)',
+ },
+ infoModalOverlay: {
+ flex: 1,
+ backgroundColor: 'rgba(0,0,0,0.5)',
+ justifyContent: 'flex-end',
+ },
+ infoModalContent: {
+ backgroundColor: 'white',
+ borderTopLeftRadius: 24,
+ borderTopRightRadius: 24,
+ paddingVertical: 24,
+ paddingHorizontal: 20,
+ paddingBottom: 40,
+ },
+ infoModalHandle: {
+ width: 36,
+ height: 4,
+ backgroundColor: '#E5E7EB',
+ borderRadius: 2,
+ alignSelf: 'center',
+ marginBottom: 16,
+ },
+ infoModalTitle: {
+ fontSize: 18,
+ fontWeight: '700',
+ color: '#2E3142',
+ marginBottom: 16,
+ textAlign: 'center',
+ },
+ infoModalText: {
+ fontSize: 15,
+ color: '#4A5460',
+ lineHeight: 22,
+ marginBottom: 12,
+ },
+ infoModalButton: {
+ paddingVertical: 14,
+ paddingHorizontal: 24,
+ borderRadius: 24,
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginTop: 8,
+ },
+ infoModalButtonText: {
+ fontSize: 15,
+ fontWeight: '600',
+ color: '#FFFFFF',
+ },
primaryButton: {
flex: 1,
borderRadius: 24,
diff --git a/ios/OutLive.xcodeproj/project.pbxproj b/ios/OutLive.xcodeproj/project.pbxproj
index 75e5ec8..9a52c3e 100644
--- a/ios/OutLive.xcodeproj/project.pbxproj
+++ b/ios/OutLive.xcodeproj/project.pbxproj
@@ -261,6 +261,7 @@
"${PODS_CONFIGURATION_BUILD_DIR}/EXNotifications/ExpoNotifications_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/EXTaskManager/ExpoTaskManager_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoFileSystem/ExpoFileSystem_privacy.bundle",
+ "${PODS_CONFIGURATION_BUILD_DIR}/ExpoMediaLibrary/ExpoMediaLibrary_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoSystemUI/ExpoSystemUI_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/PurchasesHybridCommon/PurchasesHybridCommon.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNCAsyncStorage/RNCAsyncStorage_resources.bundle",
@@ -282,6 +283,7 @@
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoNotifications_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoTaskManager_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoFileSystem_privacy.bundle",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoMediaLibrary_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoSystemUI_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/PurchasesHybridCommon.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNCAsyncStorage_resources.bundle",
diff --git a/ios/OutLive/Info.plist b/ios/OutLive/Info.plist
index 1fe19a4..c1c0fe3 100644
--- a/ios/OutLive/Info.plist
+++ b/ios/OutLive/Info.plist
@@ -80,6 +80,7 @@
UIBackgroundModes
fetch
+ remote-notification
UILaunchStoryboardName
SplashScreen
diff --git a/ios/OutLive/OutLive.entitlements b/ios/OutLive/OutLive.entitlements
index 3ab3686..0eaca8a 100644
--- a/ios/OutLive/OutLive.entitlements
+++ b/ios/OutLive/OutLive.entitlements
@@ -3,7 +3,7 @@
aps-environment
- development
+ production
com.apple.developer.applesignin
Default
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index ec8d926..52cd5df 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -71,6 +71,9 @@ PODS:
- ExpoModulesCore
- ExpoLinking (8.0.8):
- ExpoModulesCore
+ - ExpoMediaLibrary (18.2.0):
+ - ExpoModulesCore
+ - React-Core
- ExpoModulesCore (3.0.21):
- hermes-engine
- RCTRequired
@@ -104,7 +107,7 @@ PODS:
- ExpoModulesCore
- ExpoSystemUI (6.0.7):
- ExpoModulesCore
- - ExpoUI (0.2.0-beta.4):
+ - ExpoUI (0.2.0-beta.7):
- ExpoModulesCore
- ExpoWebBrowser (15.0.8):
- ExpoModulesCore
@@ -1508,9 +1511,31 @@ PODS:
- ReactCommon/turbomodule/core
- ReactNativeDependencies
- Yoga
+ - react-native-view-shot (4.0.3):
+ - hermes-engine
+ - RCTRequired
+ - RCTTypeSafety
+ - React-Core
+ - React-Core-prebuilt
+ - React-debug
+ - React-Fabric
+ - React-featureflags
+ - React-graphics
+ - React-ImageManager
+ - React-jsi
+ - React-NativeModulesApple
+ - React-RCTFabric
+ - React-renderercss
+ - React-rendererdebug
+ - React-utils
+ - ReactCodegen
+ - ReactCommon/turbomodule/bridging
+ - ReactCommon/turbomodule/core
+ - ReactNativeDependencies
+ - Yoga
- react-native-voice (3.2.4):
- React-Core
- - react-native-webview (13.16.0):
+ - react-native-webview (13.15.0):
- hermes-engine
- RCTRequired
- RCTTypeSafety
@@ -1927,7 +1952,7 @@ PODS:
- ReactCommon/turbomodule/core
- ReactNativeDependencies
- Yoga
- - RNCPicker (2.11.2):
+ - RNCPicker (2.11.1):
- hermes-engine
- RCTRequired
- RCTTypeSafety
@@ -1949,7 +1974,7 @@ PODS:
- ReactCommon/turbomodule/core
- ReactNativeDependencies
- Yoga
- - RNDateTimePicker (8.4.5):
+ - RNDateTimePicker (8.4.4):
- hermes-engine
- RCTRequired
- RCTTypeSafety
@@ -2119,7 +2144,7 @@ PODS:
- ReactCommon/turbomodule/core
- ReactNativeDependencies
- Yoga
- - RNSentry (7.1.0):
+ - RNSentry (7.2.0):
- hermes-engine
- RCTRequired
- RCTTypeSafety
@@ -2141,9 +2166,9 @@ PODS:
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- ReactNativeDependencies
- - Sentry/HybridSDK (= 8.56.0)
+ - Sentry/HybridSDK (= 8.56.1)
- Yoga
- - RNSVG (15.14.0):
+ - RNSVG (15.12.1):
- hermes-engine
- RCTRequired
- RCTTypeSafety
@@ -2164,9 +2189,9 @@ PODS:
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- ReactNativeDependencies
- - RNSVG/common (= 15.14.0)
+ - RNSVG/common (= 15.12.1)
- Yoga
- - RNSVG/common (15.14.0):
+ - RNSVG/common (15.12.1):
- hermes-engine
- RCTRequired
- RCTTypeSafety
@@ -2270,7 +2295,7 @@ PODS:
- SDWebImageWebPCoder (0.14.6):
- libwebp (~> 1.0)
- SDWebImage/Core (~> 5.17)
- - Sentry/HybridSDK (8.56.0)
+ - Sentry/HybridSDK (8.56.1)
- UMAppLoader (6.0.7)
- Yoga (0.0.0)
- ZXingObjC/Core (3.6.9)
@@ -2300,6 +2325,7 @@ DEPENDENCIES:
- ExpoKeepAwake (from `../node_modules/expo-keep-awake/ios`)
- ExpoLinearGradient (from `../node_modules/expo-linear-gradient/ios`)
- ExpoLinking (from `../node_modules/expo-linking/ios`)
+ - ExpoMediaLibrary (from `../node_modules/expo-media-library/ios`)
- ExpoModulesCore (from `../node_modules/expo-modules-core`)
- ExpoQuickActions (from `../node_modules/expo-quick-actions/ios`)
- ExpoSplashScreen (from `../node_modules/expo-splash-screen/ios`)
@@ -2348,6 +2374,7 @@ DEPENDENCIES:
- React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`)
- react-native-render-html (from `../node_modules/react-native-render-html`)
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
+ - react-native-view-shot (from `../node_modules/react-native-view-shot`)
- "react-native-voice (from `../node_modules/@react-native-voice/voice`)"
- react-native-webview (from `../node_modules/react-native-webview`)
- React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
@@ -2452,6 +2479,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/expo-linear-gradient/ios"
ExpoLinking:
:path: "../node_modules/expo-linking/ios"
+ ExpoMediaLibrary:
+ :path: "../node_modules/expo-media-library/ios"
ExpoModulesCore:
:path: "../node_modules/expo-modules-core"
ExpoQuickActions:
@@ -2547,6 +2576,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-render-html"
react-native-safe-area-context:
:path: "../node_modules/react-native-safe-area-context"
+ react-native-view-shot:
+ :path: "../node_modules/react-native-view-shot"
react-native-voice:
:path: "../node_modules/@react-native-voice/voice"
react-native-webview:
@@ -2663,13 +2694,14 @@ SPEC CHECKSUMS:
ExpoKeepAwake: 1a2e820692e933c94a565ec3fbbe38ac31658ffe
ExpoLinearGradient: a464898cb95153125e3b81894fd479bcb1c7dd27
ExpoLinking: f051f28e50ea9269ff539317c166adec81d9342d
+ ExpoMediaLibrary: 641a6952299b395159ccd459bd8f5f6764bf55fe
ExpoModulesCore: 3a6eb12a5f4d67b2f5fc7d0bc4777b18348f2d7a
ExpoQuickActions: 31a70aa6a606128de4416a4830e09cfabfe6667f
ExpoSplashScreen: cbb839de72110dea1851dd3e85080b7923af2540
ExpoSQLite: 7fa091ba5562474093fef09be644161a65e11b3f
ExpoSymbols: 1ae04ce686de719b9720453b988d8bc5bf776c68
ExpoSystemUI: 6cd74248a2282adf6dec488a75fa532d69dee314
- ExpoUI: 5e44b62e2589b7bc8a6123943105a230c693d000
+ ExpoUI: b99a1d1ef5352a60bebf4f4fd3a50d2f896ae804
ExpoWebBrowser: d04a0d6247a0bea4519fbc2ea816610019ad83e0
EXTaskManager: cf225704fab8de8794a6f57f7fa41a90c0e2cd47
FBLazyVector: 9e0cd874afd81d9a4d36679daca991b58b260d42
@@ -2715,8 +2747,9 @@ SPEC CHECKSUMS:
React-microtasksnativemodule: 76905804171d8ccbe69329fc84c57eb7934add7f
react-native-render-html: 5afc4751f1a98621b3009432ef84c47019dcb2bd
react-native-safe-area-context: 42a1b4f8774b577d03b53de7326e3d5757fe9513
+ react-native-view-shot: fb3c0774edb448f42705491802a455beac1502a2
react-native-voice: 908a0eba96c8c3d643e4f98b7232c6557d0a6f9c
- react-native-webview: 3e303e80cadb5f17118c8c1502aa398e9287e415
+ react-native-webview: b29007f4723bca10872028067b07abacfa1cb35a
React-NativeModulesApple: a9464983ccc0f66f45e93558671f60fc7536e438
React-oscompat: 73db7dbc80edef36a9d6ed3c6c4e1724ead4236d
React-perflogger: 123272debf907cc423962adafcf4513320e43757
@@ -2751,21 +2784,21 @@ SPEC CHECKSUMS:
RevenueCat: a51003d4cb33820cc504cf177c627832b462a98e
RNCAsyncStorage: 3a4f5e2777dae1688b781a487923a08569e27fe4
RNCMaskedView: d2578d41c59b936db122b2798ba37e4722d21035
- RNCPicker: ddce382c4b42ea2ee36dd588066f0c6d5a240707
- RNDateTimePicker: 7dda2673bd2a6022ea8888fe669d735b2eac0b2d
+ RNCPicker: a7170edbcbf8288de8edb2502e08e7fc757fa755
+ RNDateTimePicker: be0e44bcb9ed0607c7c5f47dbedd88cf091f6791
RNDeviceInfo: bcce8752b5043a623fe3c26789679b473f705d3c
RNGestureHandler: 2914750df066d89bf9d8f48a10ad5f0051108ac3
RNPurchases: 2569675abdc1dbc739f2eec0fa564a112cf860de
RNReanimated: 3895a29fdf77bbe2a627e1ed599a5e5d1df76c29
RNScreens: d8d6f1792f6e7ac12b0190d33d8d390efc0c1845
- RNSentry: dbee413744aec703b8763b620b14ed7a1e2db095
- RNSVG: 6c534e37eaaefe882b3f55294d0d607de20562dc
+ RNSentry: 41979b419908128847ef662cc130a400b7576fa9
+ RNSVG: 31d6639663c249b7d5abc9728dde2041eb2a3c34
RNWorklets: 54d8dffb7f645873a58484658ddfd4bd1a9a0bc1
SDWebImage: 16309af6d214ba3f77a7c6f6fdda888cb313a50a
SDWebImageAVIFCoder: afe194a084e851f70228e4be35ef651df0fc5c57
SDWebImageSVGCoder: 15a300a97ec1c8ac958f009c02220ac0402e936c
SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380
- Sentry: 3d82977434c80381cae856c40b99c39e4be6bc11
+ Sentry: b3ec44d01708fce73f99b544beb57e890eca4406
UMAppLoader: e1234c45d2b7da239e9e90fc4bbeacee12afd5b6
Yoga: 051f086b5ccf465ff2ed38a2cf5a558ae01aaaa1
ZXingObjC: 8898711ab495761b2dbbdec76d90164a6d7e14c5
diff --git a/package-lock.json b/package-lock.json
index db8f8f6..453f276 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,18 +9,18 @@
"version": "1.0.2",
"dependencies": {
"@expo/metro-runtime": "~6.1.2",
- "@expo/ui": "~0.2.0-beta.4",
+ "@expo/ui": "~0.2.0-beta.7",
"@expo/vector-icons": "^15.0.2",
"@react-native-async-storage/async-storage": "^2.2.0",
- "@react-native-community/datetimepicker": "8.4.5",
+ "@react-native-community/datetimepicker": "8.4.4",
"@react-native-masked-view/masked-view": "^0.3.2",
- "@react-native-picker/picker": "2.11.2",
+ "@react-native-picker/picker": "2.11.1",
"@react-native-voice/voice": "^3.2.4",
- "@react-navigation/bottom-tabs": "^7.4.7",
+ "@react-navigation/bottom-tabs": "^7.4.0",
"@react-navigation/elements": "^2.6.4",
- "@react-navigation/native": "^7.1.17",
+ "@react-navigation/native": "^7.1.8",
"@reduxjs/toolkit": "^2.9.0",
- "@sentry/react-native": "~7.1.0",
+ "@sentry/react-native": "~7.2.0",
"@types/lodash": "^4.17.20",
"dayjs": "^1.11.18",
"expo": "^54.0.13",
@@ -36,6 +36,7 @@
"expo-image-picker": "~17.0.8",
"expo-linear-gradient": "~15.0.7",
"expo-linking": "~8.0.8",
+ "expo-media-library": "^18.2.0",
"expo-notifications": "~0.32.12",
"expo-quick-actions": "^6.0.0",
"expo-router": "~6.0.12",
@@ -63,10 +64,11 @@
"react-native-render-html": "^6.3.4",
"react-native-safe-area-context": "~5.6.1",
"react-native-screens": "~4.16.0",
- "react-native-svg": "^15.13.0",
+ "react-native-svg": "15.12.1",
"react-native-toast-message": "^2.3.3",
+ "react-native-view-shot": "^4.0.3",
"react-native-web": "^0.21.1",
- "react-native-webview": "13.16.0",
+ "react-native-webview": "13.15.0",
"react-native-wheel-picker-expo": "^0.5.4",
"react-redux": "^9.2.0"
},
@@ -2224,9 +2226,9 @@
"license": "MIT"
},
"node_modules/@expo/ui": {
- "version": "0.2.0-beta.4",
- "resolved": "https://mirrors.tencent.com/npm/@expo/ui/-/ui-0.2.0-beta.4.tgz",
- "integrity": "sha512-49DoNCQ5jyLFvnTZpVU1aMSbfgRtX4QQtnX7WM97A7dJhocvaF7g7MA3LBeoZ07MMVKuuwfcIBM2F/f52S+6zw==",
+ "version": "0.2.0-beta.7",
+ "resolved": "https://mirrors.tencent.com/npm/@expo/ui/-/ui-0.2.0-beta.7.tgz",
+ "integrity": "sha512-oz2HEpwll+yMFUKbryZ84IgxjLx7RPxxMDVKpCEsK0OhETrLF5NxHlpCkKjdLuQL3QiVSvj5kn6hBFknco3aCw==",
"license": "MIT",
"dependencies": {
"sf-symbols-typescript": "^2.1.0"
@@ -3031,9 +3033,9 @@
}
},
"node_modules/@react-native-community/datetimepicker": {
- "version": "8.4.5",
- "resolved": "https://mirrors.tencent.com/npm/@react-native-community/datetimepicker/-/datetimepicker-8.4.5.tgz",
- "integrity": "sha512-vvVOJAHjU8TFBzTUjQzANCL6C3pZSE2zjfutCATk790uz7ASEc2tOBD+EIG4BTelWtP2G9jqvXp2L7XGdhEBRg==",
+ "version": "8.4.4",
+ "resolved": "https://mirrors.tencent.com/npm/@react-native-community/datetimepicker/-/datetimepicker-8.4.4.tgz",
+ "integrity": "sha512-bc4ZixEHxZC9/qf5gbdYvIJiLZ5CLmEsC3j+Yhe1D1KC/3QhaIfGDVdUcid0PdlSoGOSEq4VlB93AWyetEyBSQ==",
"license": "MIT",
"dependencies": {
"invariant": "^2.2.4"
@@ -3064,9 +3066,9 @@
}
},
"node_modules/@react-native-picker/picker": {
- "version": "2.11.2",
- "resolved": "https://mirrors.tencent.com/npm/@react-native-picker/picker/-/picker-2.11.2.tgz",
- "integrity": "sha512-2zyFdW4jgHjF+NeuDZ4nl3hJ+8suey69bI3yljqhNyowfklW2NwNrdDUaJ2iwtPCpk2pt7834aPF8TI6iyZRhA==",
+ "version": "2.11.1",
+ "resolved": "https://mirrors.tencent.com/npm/@react-native-picker/picker/-/picker-2.11.1.tgz",
+ "integrity": "sha512-ThklnkK4fV3yynnIIRBkxxjxR4IFbdMNJVF6tlLdOJ/zEFUEFUEdXY0KmH0iYzMwY8W4/InWsLiA7AkpAbnexA==",
"license": "MIT",
"workspaces": [
"example"
@@ -3717,9 +3719,9 @@
}
},
"node_modules/@sentry/cli": {
- "version": "2.53.0",
- "resolved": "https://mirrors.tencent.com/npm/@sentry/cli/-/cli-2.53.0.tgz",
- "integrity": "sha512-n2ZNb+5Z6AZKQSI0SusQ7ZzFL637mfw3Xh4C3PEyVSn9LiF683fX0TTq8OeGmNZQS4maYfS95IFD+XpydU0dEA==",
+ "version": "2.55.0",
+ "resolved": "https://mirrors.tencent.com/npm/@sentry/cli/-/cli-2.55.0.tgz",
+ "integrity": "sha512-cynvcIM2xL8ddwELyFRSpZQw4UtFZzoM2rId2l9vg7+wDREPDocMJB9lEQpBIo3eqhp9JswqUT037yjO6iJ5Sw==",
"hasInstallScript": true,
"license": "BSD-3-Clause",
"dependencies": {
@@ -3736,20 +3738,20 @@
"node": ">= 10"
},
"optionalDependencies": {
- "@sentry/cli-darwin": "2.53.0",
- "@sentry/cli-linux-arm": "2.53.0",
- "@sentry/cli-linux-arm64": "2.53.0",
- "@sentry/cli-linux-i686": "2.53.0",
- "@sentry/cli-linux-x64": "2.53.0",
- "@sentry/cli-win32-arm64": "2.53.0",
- "@sentry/cli-win32-i686": "2.53.0",
- "@sentry/cli-win32-x64": "2.53.0"
+ "@sentry/cli-darwin": "2.55.0",
+ "@sentry/cli-linux-arm": "2.55.0",
+ "@sentry/cli-linux-arm64": "2.55.0",
+ "@sentry/cli-linux-i686": "2.55.0",
+ "@sentry/cli-linux-x64": "2.55.0",
+ "@sentry/cli-win32-arm64": "2.55.0",
+ "@sentry/cli-win32-i686": "2.55.0",
+ "@sentry/cli-win32-x64": "2.55.0"
}
},
"node_modules/@sentry/cli-darwin": {
- "version": "2.53.0",
- "resolved": "https://mirrors.tencent.com/npm/@sentry/cli-darwin/-/cli-darwin-2.53.0.tgz",
- "integrity": "sha512-NNPfpILMwKgpHiyJubHHuauMKltkrgLQ5tvMdxNpxY60jBNdo5VJtpESp4XmXlnidzV4j1z61V4ozU6ttDgt5Q==",
+ "version": "2.55.0",
+ "resolved": "https://mirrors.tencent.com/npm/@sentry/cli-darwin/-/cli-darwin-2.55.0.tgz",
+ "integrity": "sha512-jGHE7SHHzqXUmnsmRLgorVH6nmMmTjQQXdPZbSL5tRtH8d3OIYrVNr5D72DSgD26XAPBDMV0ibqOQ9NKoiSpfA==",
"license": "BSD-3-Clause",
"optional": true,
"os": [
@@ -3759,6 +3761,128 @@
"node": ">=10"
}
},
+ "node_modules/@sentry/cli-linux-arm": {
+ "version": "2.55.0",
+ "resolved": "https://mirrors.tencent.com/npm/@sentry/cli-linux-arm/-/cli-linux-arm-2.55.0.tgz",
+ "integrity": "sha512-ATjU0PsiWADSPLF/kZroLZ7FPKd5W9TDWHVkKNwIUNTei702LFgTjNeRwOIzTgSvG3yTmVEqtwFQfFN/7hnVXQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "linux",
+ "freebsd",
+ "android"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sentry/cli-linux-arm64": {
+ "version": "2.55.0",
+ "resolved": "https://mirrors.tencent.com/npm/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.55.0.tgz",
+ "integrity": "sha512-jNB/0/gFcOuDCaY/TqeuEpsy/k52dwyk1SOV3s1ku4DUsln6govTppeAGRewY3T1Rj9B2vgIWTrnB8KVh9+Rgg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "linux",
+ "freebsd",
+ "android"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sentry/cli-linux-i686": {
+ "version": "2.55.0",
+ "resolved": "https://mirrors.tencent.com/npm/@sentry/cli-linux-i686/-/cli-linux-i686-2.55.0.tgz",
+ "integrity": "sha512-8LZjo6PncTM6bWdaggscNOi5r7F/fqRREsCwvd51dcjGj7Kp1plqo9feEzYQ+jq+KUzVCiWfHrUjddFmYyZJrg==",
+ "cpu": [
+ "x86",
+ "ia32"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "linux",
+ "freebsd",
+ "android"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sentry/cli-linux-x64": {
+ "version": "2.55.0",
+ "resolved": "https://mirrors.tencent.com/npm/@sentry/cli-linux-x64/-/cli-linux-x64-2.55.0.tgz",
+ "integrity": "sha512-5LUVvq74Yj2cZZy5g5o/54dcWEaX4rf3myTHy73AKhRj1PABtOkfexOLbF9xSrZy95WXWaXyeH+k5n5z/vtHfA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "linux",
+ "freebsd",
+ "android"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sentry/cli-win32-arm64": {
+ "version": "2.55.0",
+ "resolved": "https://mirrors.tencent.com/npm/@sentry/cli-win32-arm64/-/cli-win32-arm64-2.55.0.tgz",
+ "integrity": "sha512-cWIQdzm1pfLwPARsV6dUb8TVd6Y3V1A2VWxjTons3Ift6GvtVmiAe0OWL8t2Yt95i8v61kTD/6Tq21OAaogqzA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sentry/cli-win32-i686": {
+ "version": "2.55.0",
+ "resolved": "https://mirrors.tencent.com/npm/@sentry/cli-win32-i686/-/cli-win32-i686-2.55.0.tgz",
+ "integrity": "sha512-ldepCn2t9r4I0wvgk7NRaA7coJyy4rTQAzM66u9j5nTEsUldf66xym6esd5ZZRAaJUjffqvHqUIr/lrieTIrVg==",
+ "cpu": [
+ "x86",
+ "ia32"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sentry/cli-win32-x64": {
+ "version": "2.55.0",
+ "resolved": "https://mirrors.tencent.com/npm/@sentry/cli-win32-x64/-/cli-win32-x64-2.55.0.tgz",
+ "integrity": "sha512-4hPc/I/9tXx+HLTdTGwlagtAfDSIa2AoTUP30tl32NAYQhx9a6niUbPAemK2qfxesiufJ7D2djX83rCw6WnJVA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/@sentry/cli/node_modules/agent-base": {
"version": "6.0.2",
"resolved": "https://mirrors.tencent.com/npm/agent-base/-/agent-base-6.0.2.tgz",
@@ -3811,14 +3935,14 @@
}
},
"node_modules/@sentry/react-native": {
- "version": "7.1.0",
- "resolved": "https://mirrors.tencent.com/npm/@sentry/react-native/-/react-native-7.1.0.tgz",
- "integrity": "sha512-Nhs/1j+w7cl9Q+FmaBl0+nByeAKpZttWFz1R0YkZJsg01b+4g63pepI3WMwUSq2QrvYIAu/5PiUoTa2dx9HK6g==",
+ "version": "7.2.0",
+ "resolved": "https://mirrors.tencent.com/npm/@sentry/react-native/-/react-native-7.2.0.tgz",
+ "integrity": "sha512-rjqYgEjntPz1sPysud78wi4B9ui7LBVPsG6qr8s/htLMYho9GPGFA5dF+eqsQWqMX8NDReAxNkLTC4+gCNklLQ==",
"license": "MIT",
"dependencies": {
"@sentry/babel-plugin-component-annotate": "4.3.0",
"@sentry/browser": "10.12.0",
- "@sentry/cli": "2.53.0",
+ "@sentry/cli": "2.55.0",
"@sentry/core": "10.12.0",
"@sentry/react": "10.12.0",
"@sentry/types": "10.12.0"
@@ -5052,6 +5176,15 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"license": "MIT"
},
+ "node_modules/base64-arraybuffer": {
+ "version": "1.0.2",
+ "resolved": "https://mirrors.tencent.com/npm/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
+ "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@@ -5819,6 +5952,14 @@
"hyphenate-style-name": "^1.0.3"
}
},
+ "node_modules/css-line-break": {
+ "version": "2.1.0",
+ "resolved": "https://mirrors.tencent.com/npm/css-line-break/-/css-line-break-2.1.0.tgz",
+ "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
+ "dependencies": {
+ "utrie": "^1.0.2"
+ }
+ },
"node_modules/css-select": {
"version": "5.2.2",
"resolved": "https://mirrors.tencent.com/npm/css-select/-/css-select-5.2.2.tgz",
@@ -7174,6 +7315,16 @@
"react-native": "*"
}
},
+ "node_modules/expo-media-library": {
+ "version": "18.2.0",
+ "resolved": "https://mirrors.tencent.com/npm/expo-media-library/-/expo-media-library-18.2.0.tgz",
+ "integrity": "sha512-aIYLIqmU8LFWrQcfZdwg9f/iWm0wC8uhZ7HiUiTnrigtxf417cVvNokX9afXpIOKBHAHRjVIbcs1nN8KZDE2Fw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*",
+ "react-native": "*"
+ }
+ },
"node_modules/expo-modules-autolinking": {
"version": "3.0.15",
"resolved": "https://mirrors.tencent.com/npm/expo-modules-autolinking/-/expo-modules-autolinking-3.0.15.tgz",
@@ -8487,6 +8638,19 @@
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"license": "ISC"
},
+ "node_modules/html2canvas": {
+ "version": "1.4.1",
+ "resolved": "https://mirrors.tencent.com/npm/html2canvas/-/html2canvas-1.4.1.tgz",
+ "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
+ "license": "MIT",
+ "dependencies": {
+ "css-line-break": "^2.1.0",
+ "text-segmentation": "^1.0.3"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
"node_modules/htmlparser2": {
"version": "7.2.0",
"resolved": "https://mirrors.tencent.com/npm/htmlparser2/-/htmlparser2-7.2.0.tgz",
@@ -11526,8 +11690,7 @@
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://mirrors.tencent.com/npm/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
- "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
- "license": "MIT"
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/punycode": {
"version": "2.3.1",
@@ -11952,9 +12115,9 @@
}
},
"node_modules/react-native-svg": {
- "version": "15.14.0",
- "resolved": "https://mirrors.tencent.com/npm/react-native-svg/-/react-native-svg-15.14.0.tgz",
- "integrity": "sha512-B3gYc7WztcOT4N54AtUutbe0Nuqqh/nkresY0fAXzUHYLsWuIu/yGiCCD3DKfAs6GLv5LFtWTu7N333Q+e3bkg==",
+ "version": "15.12.1",
+ "resolved": "https://mirrors.tencent.com/npm/react-native-svg/-/react-native-svg-15.12.1.tgz",
+ "integrity": "sha512-vCuZJDf8a5aNC2dlMovEv4Z0jjEUET53lm/iILFnFewa15b4atjVxU6Wirm6O9y6dEsdjDZVD7Q3QM4T1wlI8g==",
"license": "MIT",
"dependencies": {
"css-select": "^5.1.0",
@@ -11976,6 +12139,19 @@
"react-native": "*"
}
},
+ "node_modules/react-native-view-shot": {
+ "version": "4.0.3",
+ "resolved": "https://mirrors.tencent.com/npm/react-native-view-shot/-/react-native-view-shot-4.0.3.tgz",
+ "integrity": "sha512-USNjYmED7C0me02c1DxKA0074Hw+y/nxo+xJKlffMvfUWWzL5ELh/TJA/pTnVqFurIrzthZDPtDM7aBFJuhrHQ==",
+ "license": "MIT",
+ "dependencies": {
+ "html2canvas": "^1.4.1"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ }
+ },
"node_modules/react-native-web": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.21.1.tgz",
@@ -12009,9 +12185,9 @@
"license": "MIT"
},
"node_modules/react-native-webview": {
- "version": "13.16.0",
- "resolved": "https://mirrors.tencent.com/npm/react-native-webview/-/react-native-webview-13.16.0.tgz",
- "integrity": "sha512-Nh13xKZWW35C0dbOskD7OX01nQQavOzHbCw9XoZmar4eXCo7AvrYJ0jlUfRVVIJzqINxHlpECYLdmAdFsl9xDA==",
+ "version": "13.15.0",
+ "resolved": "https://mirrors.tencent.com/npm/react-native-webview/-/react-native-webview-13.15.0.tgz",
+ "integrity": "sha512-Vzjgy8mmxa/JO6l5KZrsTC7YemSdq+qB01diA0FqjUTaWGAGwuykpJ73MDj3+mzBSlaDxAEugHzTtkUQkQEQeQ==",
"license": "MIT",
"dependencies": {
"escape-string-regexp": "^4.0.0",
@@ -13634,6 +13810,15 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/text-segmentation": {
+ "version": "1.0.3",
+ "resolved": "https://mirrors.tencent.com/npm/text-segmentation/-/text-segmentation-1.0.3.tgz",
+ "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
+ "license": "MIT",
+ "dependencies": {
+ "utrie": "^1.0.2"
+ }
+ },
"node_modules/thenify": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
@@ -14210,6 +14395,15 @@
"node": ">= 0.4.0"
}
},
+ "node_modules/utrie": {
+ "version": "1.0.2",
+ "resolved": "https://mirrors.tencent.com/npm/utrie/-/utrie-1.0.2.tgz",
+ "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
+ "license": "MIT",
+ "dependencies": {
+ "base64-arraybuffer": "^1.0.2"
+ }
+ },
"node_modules/uuid": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz",
diff --git a/package.json b/package.json
index 3fb5c2e..e37e7a7 100644
--- a/package.json
+++ b/package.json
@@ -10,18 +10,18 @@
},
"dependencies": {
"@expo/metro-runtime": "~6.1.2",
- "@expo/ui": "~0.2.0-beta.4",
+ "@expo/ui": "~0.2.0-beta.7",
"@expo/vector-icons": "^15.0.2",
"@react-native-async-storage/async-storage": "^2.2.0",
- "@react-native-community/datetimepicker": "8.4.5",
+ "@react-native-community/datetimepicker": "8.4.4",
"@react-native-masked-view/masked-view": "^0.3.2",
- "@react-native-picker/picker": "2.11.2",
+ "@react-native-picker/picker": "2.11.1",
"@react-native-voice/voice": "^3.2.4",
- "@react-navigation/bottom-tabs": "^7.4.7",
+ "@react-navigation/bottom-tabs": "^7.4.0",
"@react-navigation/elements": "^2.6.4",
- "@react-navigation/native": "^7.1.17",
+ "@react-navigation/native": "^7.1.8",
"@reduxjs/toolkit": "^2.9.0",
- "@sentry/react-native": "~7.1.0",
+ "@sentry/react-native": "~7.2.0",
"@types/lodash": "^4.17.20",
"dayjs": "^1.11.18",
"expo": "^54.0.13",
@@ -37,6 +37,7 @@
"expo-image-picker": "~17.0.8",
"expo-linear-gradient": "~15.0.7",
"expo-linking": "~8.0.8",
+ "expo-media-library": "^18.2.0",
"expo-notifications": "~0.32.12",
"expo-quick-actions": "^6.0.0",
"expo-router": "~6.0.12",
@@ -64,10 +65,11 @@
"react-native-render-html": "^6.3.4",
"react-native-safe-area-context": "~5.6.1",
"react-native-screens": "~4.16.0",
- "react-native-svg": "^15.13.0",
+ "react-native-svg": "15.12.1",
"react-native-toast-message": "^2.3.3",
+ "react-native-view-shot": "^4.0.3",
"react-native-web": "^0.21.1",
- "react-native-webview": "13.16.0",
+ "react-native-webview": "13.15.0",
"react-native-wheel-picker-expo": "^0.5.4",
"react-redux": "^9.2.0"
},
@@ -79,4 +81,4 @@
"typescript": "~5.9.2"
},
"private": true
-}
\ No newline at end of file
+}
diff --git a/store/fastingSlice.ts b/store/fastingSlice.ts
index 1be2f8b..b7a17d5 100644
--- a/store/fastingSlice.ts
+++ b/store/fastingSlice.ts
@@ -4,7 +4,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import dayjs from 'dayjs';
import type { RootState } from './index';
-export type FastingScheduleOrigin = 'manual' | 'recommended' | 'quick-start';
+export type FastingScheduleOrigin = 'manual' | 'recommended' | 'quick-start' | 'auto';
export type FastingSchedule = {
planId: string;