@kingstinct/react-native-healthkit 12.1.2 → 12.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ios/CategoryTypeModule.swift +49 -97
- package/ios/CharacteristicTypeModule.swift +77 -63
- package/ios/CoreModule.swift +324 -280
- package/ios/CorrelationTypeModule.swift +192 -144
- package/ios/ElectrocardiogramModule.swift +185 -194
- package/ios/HeartbeatSeriesModule.swift +123 -171
- package/ios/Helpers.swift +312 -571
- package/ios/MedicationModule.swift +259 -0
- package/ios/PredicateHelpers.swift +334 -0
- package/ios/QuantityTypeModule.swift +297 -378
- package/ios/Serializers.swift +273 -210
- package/ios/SourceProxy.swift +2 -2
- package/ios/StateOfMindModule.swift +179 -125
- package/ios/WorkoutProxy.swift +235 -112
- package/ios/WorkoutsModule.swift +214 -262
- package/lib/commonjs/healthkit.ios.js +22 -2
- package/lib/commonjs/healthkit.js +35 -5
- package/lib/commonjs/hooks/useStatisticsForQuantity.js +1 -1
- package/lib/commonjs/hooks/useSubscribeToCategorySamples.js +20 -0
- package/lib/commonjs/modules.js +2 -1
- package/lib/commonjs/specs/MedicationModule.nitro.js +27 -0
- package/lib/commonjs/types/Constants.js +2 -1
- package/lib/commonjs/types/QuantityType.js +8 -1
- package/lib/commonjs/types/QueryOptions.js +18 -0
- package/lib/commonjs/types/WeatherCondition.js +32 -32
- package/lib/commonjs/types/Workouts.js +1 -50
- package/lib/commonjs/utils/getCategorySampleById.js +1 -1
- package/lib/commonjs/utils/getQuantitySampleById.js +1 -1
- package/lib/commonjs/utils/getWorkoutById.js +1 -1
- package/lib/commonjs/utils/subscribeToCategorySamples.js +29 -0
- package/lib/commonjs/utils/subscribeToQuantitySamples.js +8 -25
- package/lib/module/healthkit.ios.js +20 -2
- package/lib/module/healthkit.js +32 -2
- package/lib/module/hooks/useStatisticsForQuantity.js +1 -1
- package/lib/module/hooks/useSubscribeToCategorySamples.js +17 -0
- package/lib/module/modules.js +1 -0
- package/lib/module/specs/MedicationModule.nitro.js +26 -0
- package/lib/module/types/Constants.js +1 -0
- package/lib/module/types/QuantityType.js +7 -0
- package/lib/module/types/QueryOptions.js +17 -1
- package/lib/module/types/WeatherCondition.js +31 -31
- package/lib/module/types/Workouts.js +0 -49
- package/lib/module/utils/getCategorySampleById.js +1 -1
- package/lib/module/utils/getQuantitySampleById.js +1 -1
- package/lib/module/utils/getWorkoutById.js +1 -1
- package/lib/module/utils/subscribeToCategorySamples.js +26 -0
- package/lib/module/utils/subscribeToQuantitySamples.js +8 -25
- package/lib/typescript/healthkit.d.ts +18 -9
- package/lib/typescript/healthkit.ios.d.ts +33 -15
- package/lib/typescript/hooks/useSubscribeToCategorySamples.d.ts +3 -0
- package/lib/typescript/modules.d.ts +2 -0
- package/lib/typescript/specs/CategoryTypeModule.nitro.d.ts +2 -2
- package/lib/typescript/specs/CoreModule.nitro.d.ts +2 -1
- package/lib/typescript/specs/CorrelationTypeModule.nitro.d.ts +4 -2
- package/lib/typescript/specs/ElectrocardiogramModule.nitro.d.ts +1 -1
- package/lib/typescript/specs/HeartbeatSeriesModule.nitro.d.ts +1 -1
- package/lib/typescript/specs/MedicationModule.nitro.d.ts +56 -0
- package/lib/typescript/specs/QuantityTypeModule.nitro.d.ts +4 -4
- package/lib/typescript/specs/StateOfMindModule.nitro.d.ts +4 -3
- package/lib/typescript/types/CategoryType.d.ts +10 -20
- package/lib/typescript/types/Constants.d.ts +1 -0
- package/lib/typescript/types/CorrelationType.d.ts +8 -10
- package/lib/typescript/types/ElectrocardiogramSample.d.ts +2 -12
- package/lib/typescript/types/HeartbeatSeries.d.ts +2 -14
- package/lib/typescript/types/QuantitySample.d.ts +2 -8
- package/lib/typescript/types/QuantityType.d.ts +7 -8
- package/lib/typescript/types/QuantityTypeIdentifier.d.ts +23 -23
- package/lib/typescript/types/QueryOptions.d.ts +43 -28
- package/lib/typescript/types/Shared.d.ts +52 -7
- package/lib/typescript/types/StateOfMind.d.ts +7 -10
- package/lib/typescript/types/Subscriptions.d.ts +12 -3
- package/lib/typescript/types/WeatherCondition.d.ts +1 -1
- package/lib/typescript/types/Workouts.d.ts +28 -81
- package/lib/typescript/utils/subscribeToCategorySamples.d.ts +5 -0
- package/nitrogen/generated/ios/ReactNativeHealthkit-Swift-Cxx-Bridge.cpp +57 -0
- package/nitrogen/generated/ios/ReactNativeHealthkit-Swift-Cxx-Bridge.hpp +592 -389
- package/nitrogen/generated/ios/ReactNativeHealthkit-Swift-Cxx-Umbrella.hpp +65 -30
- package/nitrogen/generated/ios/ReactNativeHealthkitAutolinking.mm +8 -0
- package/nitrogen/generated/ios/ReactNativeHealthkitAutolinking.swift +15 -0
- package/nitrogen/generated/ios/c++/HybridCategoryTypeModuleSpecSwift.hpp +32 -26
- package/nitrogen/generated/ios/c++/HybridCoreModuleSpecSwift.hpp +36 -37
- package/nitrogen/generated/ios/c++/HybridCorrelationTypeModuleSpecSwift.hpp +55 -2
- package/nitrogen/generated/ios/c++/HybridElectrocardiogramModuleSpecSwift.hpp +36 -30
- package/nitrogen/generated/ios/c++/HybridHeartbeatSeriesModuleSpecSwift.hpp +35 -29
- package/nitrogen/generated/ios/c++/HybridMedicationModuleSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridMedicationModuleSpecSwift.hpp +181 -0
- package/nitrogen/generated/ios/c++/HybridQuantityTypeModuleSpecSwift.hpp +48 -42
- package/nitrogen/generated/ios/c++/HybridStateOfMindModuleSpecSwift.hpp +59 -36
- package/nitrogen/generated/ios/c++/HybridWorkoutProxySpecSwift.hpp +150 -29
- package/nitrogen/generated/ios/c++/HybridWorkoutsModuleSpecSwift.hpp +13 -28
- package/nitrogen/generated/ios/swift/AggregationStyle.swift +48 -0
- package/nitrogen/generated/ios/swift/CategorySample.swift +571 -24
- package/nitrogen/generated/ios/swift/ComparisonPredicateOperator.swift +2 -2
- package/nitrogen/generated/ios/swift/CorrelationSample.swift +640 -17
- package/nitrogen/generated/ios/swift/{PredicateWithStartAndEnd.swift → DateFilter.swift} +5 -5
- package/nitrogen/generated/ios/swift/ECGQueryOptionsWithAnchor.swift +11 -91
- package/nitrogen/generated/ios/swift/ECGQueryOptionsWithSortOrder.swift +11 -91
- package/nitrogen/generated/ios/swift/ElectrocardiogramSample.swift +570 -72
- package/nitrogen/generated/ios/swift/FilterForSamples.swift +349 -12
- package/nitrogen/generated/ios/swift/FilterForSamplesBase.swift +234 -0
- package/nitrogen/generated/ios/swift/FilterForWorkouts.swift +366 -0
- package/nitrogen/generated/ios/swift/FilterForWorkoutsBase.swift +240 -0
- package/nitrogen/generated/ios/swift/Func_void_MedicationDoseEventsWithAnchorResponse.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_QueryCorrelationSamplesWithAnchorResponse.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_StateOfMindSamplesWithAnchorResponse.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_MedicationDoseEvent_.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_UserAnnotatedMedication_.swift +47 -0
- package/nitrogen/generated/ios/swift/GeneralForm.swift +104 -0
- package/nitrogen/generated/ios/swift/HeartRateMotionContext.swift +44 -0
- package/nitrogen/generated/ios/swift/HeartbeatSeriesSample.swift +565 -37
- package/nitrogen/generated/ios/swift/HybridCategoryTypeModuleSpec.swift +1 -1
- package/nitrogen/generated/ios/swift/HybridCategoryTypeModuleSpec_cxx.swift +2 -2
- package/nitrogen/generated/ios/swift/HybridCoreModuleSpec.swift +2 -1
- package/nitrogen/generated/ios/swift/HybridCoreModuleSpec_cxx.swift +19 -31
- package/nitrogen/generated/ios/swift/HybridCorrelationTypeModuleSpec.swift +2 -1
- package/nitrogen/generated/ios/swift/HybridCorrelationTypeModuleSpec_cxx.swift +21 -2
- package/nitrogen/generated/ios/swift/HybridElectrocardiogramModuleSpec.swift +1 -1
- package/nitrogen/generated/ios/swift/HybridElectrocardiogramModuleSpec_cxx.swift +2 -2
- package/nitrogen/generated/ios/swift/HybridHeartbeatSeriesModuleSpec.swift +1 -1
- package/nitrogen/generated/ios/swift/HybridHeartbeatSeriesModuleSpec_cxx.swift +2 -2
- package/nitrogen/generated/ios/swift/HybridMedicationModuleSpec.swift +60 -0
- package/nitrogen/generated/ios/swift/HybridMedicationModuleSpec_cxx.swift +208 -0
- package/nitrogen/generated/ios/swift/HybridQuantityTypeModuleSpec.swift +2 -2
- package/nitrogen/generated/ios/swift/HybridQuantityTypeModuleSpec_cxx.swift +9 -43
- package/nitrogen/generated/ios/swift/HybridStateOfMindModuleSpec.swift +2 -1
- package/nitrogen/generated/ios/swift/HybridStateOfMindModuleSpec_cxx.swift +21 -2
- package/nitrogen/generated/ios/swift/HybridWorkoutProxySpec.swift +34 -6
- package/nitrogen/generated/ios/swift/HybridWorkoutProxySpec_cxx.swift +376 -36
- package/nitrogen/generated/ios/swift/InsulinDeliveryReason.swift +40 -0
- package/nitrogen/generated/ios/swift/MedicationConcept.swift +80 -0
- package/nitrogen/generated/ios/swift/MedicationDoseEvent.swift +781 -0
- package/nitrogen/generated/ios/swift/MedicationDoseEventLogStatus.swift +56 -0
- package/nitrogen/generated/ios/swift/MedicationDoseEventScheduleType.swift +40 -0
- package/nitrogen/generated/ios/swift/MedicationDoseEventsWithAnchorResponse.swift +81 -0
- package/nitrogen/generated/ios/swift/ObjectTypeIdentifier.swift +16 -16
- package/nitrogen/generated/ios/swift/PredicateWithMetadataKey.swift +7 -7
- package/nitrogen/generated/ios/swift/QuantitySample.swift +574 -27
- package/nitrogen/generated/ios/swift/QuantityTypeIdentifier.swift +16 -16
- package/nitrogen/generated/ios/swift/QueryCorrelationSamplesWithAnchorResponse.swift +81 -0
- package/nitrogen/generated/ios/swift/QueryOptionsWithAnchor.swift +11 -91
- package/nitrogen/generated/ios/swift/QueryOptionsWithAnchorAndUnit.swift +11 -91
- package/nitrogen/generated/ios/swift/QueryOptionsWithSortOrder.swift +11 -91
- package/nitrogen/generated/ios/swift/QueryOptionsWithSortOrderAndUnit.swift +11 -91
- package/nitrogen/generated/ios/swift/RelatedCoding.swift +76 -0
- package/nitrogen/generated/ios/swift/SampleType.swift +68 -0
- package/nitrogen/generated/ios/swift/SampleTypeIdentifier.swift +16 -16
- package/nitrogen/generated/ios/swift/SampleTypeIdentifierWriteable.swift +0 -16
- package/nitrogen/generated/ios/swift/StateOfMindSample.swift +586 -58
- package/nitrogen/generated/ios/swift/StateOfMindSamplesWithAnchorResponse.swift +81 -0
- package/nitrogen/generated/ios/swift/StatisticsQueryOptions.swift +7 -75
- package/nitrogen/generated/ios/swift/UserAnnotatedMedication.swift +87 -0
- package/nitrogen/generated/ios/swift/WeatherCondition.swift +144 -0
- package/nitrogen/generated/ios/swift/WorkoutQueryOptions.swift +11 -105
- package/nitrogen/generated/ios/swift/WorkoutQueryOptionsWithAnchor.swift +11 -105
- package/nitrogen/generated/ios/swift/WorkoutSample.swift +751 -78
- package/nitrogen/generated/shared/c++/AggregationStyle.hpp +64 -0
- package/nitrogen/generated/shared/c++/CategorySample.hpp +126 -23
- package/nitrogen/generated/shared/c++/CorrelationSample.hpp +134 -12
- package/nitrogen/generated/shared/c++/{PredicateWithStartAndEnd.hpp → DateFilter.hpp} +10 -10
- package/nitrogen/generated/shared/c++/ECGQueryOptionsWithAnchor.hpp +12 -31
- package/nitrogen/generated/shared/c++/ECGQueryOptionsWithSortOrder.hpp +12 -31
- package/nitrogen/generated/shared/c++/ElectrocardiogramSample.hpp +135 -36
- package/nitrogen/generated/shared/c++/FilterForSamples.hpp +124 -0
- package/nitrogen/generated/shared/c++/FilterForSamplesBase.hpp +109 -0
- package/nitrogen/generated/shared/c++/FilterForWorkouts.hpp +131 -0
- package/nitrogen/generated/shared/c++/FilterForWorkoutsBase.hpp +116 -0
- package/nitrogen/generated/shared/c++/GeneralForm.hpp +140 -0
- package/nitrogen/generated/shared/c++/HeartRateMotionContext.hpp +67 -0
- package/nitrogen/generated/shared/c++/HeartbeatSeriesSample.hpp +131 -28
- package/nitrogen/generated/shared/c++/HybridCategoryTypeModuleSpec.hpp +1 -2
- package/nitrogen/generated/shared/c++/HybridCoreModuleSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridCoreModuleSpec.hpp +10 -28
- package/nitrogen/generated/shared/c++/HybridCorrelationTypeModuleSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridCorrelationTypeModuleSpec.hpp +11 -1
- package/nitrogen/generated/shared/c++/HybridElectrocardiogramModuleSpec.hpp +1 -2
- package/nitrogen/generated/shared/c++/HybridHeartbeatSeriesModuleSpec.hpp +1 -2
- package/nitrogen/generated/shared/c++/HybridMedicationModuleSpec.cpp +24 -0
- package/nitrogen/generated/shared/c++/HybridMedicationModuleSpec.hpp +80 -0
- package/nitrogen/generated/shared/c++/HybridQuantityTypeModuleSpec.cpp +1 -1
- package/nitrogen/generated/shared/c++/HybridQuantityTypeModuleSpec.hpp +6 -25
- package/nitrogen/generated/shared/c++/HybridStateOfMindModuleSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridStateOfMindModuleSpec.hpp +9 -2
- package/nitrogen/generated/shared/c++/HybridWorkoutProxySpec.cpp +33 -5
- package/nitrogen/generated/shared/c++/HybridWorkoutProxySpec.hpp +56 -16
- package/nitrogen/generated/shared/c++/InsulinDeliveryReason.hpp +62 -0
- package/nitrogen/generated/shared/c++/MedicationConcept.hpp +93 -0
- package/nitrogen/generated/shared/c++/MedicationDoseEvent.hpp +240 -0
- package/nitrogen/generated/shared/c++/MedicationDoseEventLogStatus.hpp +66 -0
- package/nitrogen/generated/shared/c++/MedicationDoseEventScheduleType.hpp +62 -0
- package/nitrogen/generated/shared/c++/MedicationDoseEventsWithAnchorResponse.hpp +89 -0
- package/nitrogen/generated/shared/c++/ObjectTypeIdentifier.hpp +105 -105
- package/nitrogen/generated/shared/c++/PredicateWithMetadataKey.hpp +8 -8
- package/nitrogen/generated/shared/c++/QuantitySample.hpp +130 -27
- package/nitrogen/generated/shared/c++/QuantityTypeIdentifier.hpp +105 -105
- package/nitrogen/generated/shared/c++/QueryCorrelationSamplesWithAnchorResponse.hpp +89 -0
- package/nitrogen/generated/shared/c++/QueryOptionsWithAnchor.hpp +12 -31
- package/nitrogen/generated/shared/c++/QueryOptionsWithAnchorAndUnit.hpp +12 -31
- package/nitrogen/generated/shared/c++/QueryOptionsWithSortOrder.hpp +12 -31
- package/nitrogen/generated/shared/c++/QueryOptionsWithSortOrderAndUnit.hpp +12 -31
- package/nitrogen/generated/shared/c++/RelatedCoding.hpp +84 -0
- package/nitrogen/generated/shared/c++/SampleType.hpp +87 -0
- package/nitrogen/generated/shared/c++/SampleTypeIdentifier.hpp +105 -105
- package/nitrogen/generated/shared/c++/SampleTypeIdentifierWriteable.hpp +105 -121
- package/nitrogen/generated/shared/c++/StateOfMindSample.hpp +139 -36
- package/nitrogen/generated/shared/c++/StateOfMindSamplesWithAnchorResponse.hpp +89 -0
- package/nitrogen/generated/shared/c++/StatisticsQueryOptions.hpp +8 -27
- package/nitrogen/generated/shared/c++/UserAnnotatedMedication.hpp +90 -0
- package/nitrogen/generated/shared/c++/WeatherCondition.hpp +88 -0
- package/nitrogen/generated/shared/c++/WorkoutQueryOptions.hpp +12 -37
- package/nitrogen/generated/shared/c++/WorkoutQueryOptionsWithAnchor.hpp +12 -37
- package/nitrogen/generated/shared/c++/WorkoutSample.hpp +159 -35
- package/package.json +1 -1
- package/src/healthkit.ios.ts +30 -0
- package/src/healthkit.ts +68 -3
- package/src/hooks/useStatisticsForQuantity.ts +1 -1
- package/src/hooks/useSubscribeToCategorySamples.ts +31 -0
- package/src/modules.ts +4 -0
- package/src/specs/CategoryTypeModule.nitro.ts +2 -2
- package/src/specs/CoreModule.nitro.ts +3 -0
- package/src/specs/CorrelationTypeModule.nitro.ts +11 -3
- package/src/specs/ElectrocardiogramModule.nitro.ts +1 -1
- package/src/specs/HeartbeatSeriesModule.nitro.ts +1 -1
- package/src/specs/MedicationModule.nitro.ts +140 -0
- package/src/specs/QuantityTypeModule.nitro.ts +4 -7
- package/src/specs/StateOfMindModule.nitro.ts +10 -2
- package/src/types/CategoryType.ts +15 -22
- package/src/types/Constants.ts +3 -0
- package/src/types/CorrelationType.ts +10 -15
- package/src/types/ElectrocardiogramSample.ts +2 -14
- package/src/types/HeartbeatSeries.ts +2 -15
- package/src/types/QuantitySample.ts +2 -8
- package/src/types/QuantityType.ts +8 -17
- package/src/types/QuantityTypeIdentifier.ts +25 -25
- package/src/types/QueryOptions.ts +54 -43
- package/src/types/Shared.ts +74 -17
- package/src/types/StateOfMind.ts +8 -10
- package/src/types/Subscriptions.ts +19 -3
- package/src/types/WeatherCondition.ts +1 -1
- package/src/types/Workouts.ts +28 -91
- package/src/utils/getCategorySampleById.ts +1 -1
- package/src/utils/getQuantitySampleById.ts +1 -1
- package/src/utils/getWorkoutById.ts +1 -2
- package/src/utils/subscribeToCategorySamples.ts +38 -0
- package/src/utils/subscribeToQuantitySamples.ts +12 -37
- package/nitrogen/generated/ios/swift/FilterForSamplesAnd.swift +0 -94
- package/nitrogen/generated/ios/swift/FilterForSamplesOr.swift +0 -94
- package/nitrogen/generated/ios/swift/PredicateForSamples.swift +0 -21
- package/nitrogen/generated/ios/swift/PredicateForWorkouts.swift +0 -23
- package/nitrogen/generated/ios/swift/PredicateForWorkoutsAnd.swift +0 -108
- package/nitrogen/generated/ios/swift/PredicateForWorkoutsOr.swift +0 -108
- package/nitrogen/generated/ios/swift/PredicateFromWorkout.swift +0 -45
- package/nitrogen/generated/ios/swift/PredicateWithMetadataOperator.swift +0 -48
- package/nitrogen/generated/ios/swift/PredicateWithUUID.swift +0 -35
- package/nitrogen/generated/ios/swift/PredicateWithUUIDs.swift +0 -47
- package/nitrogen/generated/ios/swift/Variant_PredicateWithUUID_PredicateWithUUIDs_PredicateWithMetadataKey_PredicateWithStartAndEnd_PredicateFromWorkout_FilterForSamplesAnd_FilterForSamplesOr.swift +0 -23
- package/nitrogen/generated/ios/swift/Variant_PredicateWithUUID_PredicateWithUUIDs_PredicateWithMetadataKey_PredicateWithStartAndEnd_PredicateFromWorkout_WorkoutActivityTypePredicate_WorkoutDurationPredicate_PredicateForWorkoutsOr_PredicateForWorkoutsAnd.swift +0 -25
- package/nitrogen/generated/ios/swift/WorkoutActivityTypePredicate.swift +0 -35
- package/nitrogen/generated/shared/c++/FilterForSamplesAnd.hpp +0 -90
- package/nitrogen/generated/shared/c++/FilterForSamplesOr.hpp +0 -90
- package/nitrogen/generated/shared/c++/PredicateForWorkoutsAnd.hpp +0 -96
- package/nitrogen/generated/shared/c++/PredicateForWorkoutsOr.hpp +0 -96
- package/nitrogen/generated/shared/c++/PredicateFromWorkout.hpp +0 -77
- package/nitrogen/generated/shared/c++/PredicateWithMetadataOperator.hpp +0 -84
- package/nitrogen/generated/shared/c++/PredicateWithUUID.hpp +0 -75
- package/nitrogen/generated/shared/c++/PredicateWithUUIDs.hpp +0 -76
- package/nitrogen/generated/shared/c++/WorkoutActivityTypePredicate.hpp +0 -76
package/ios/Helpers.swift
CHANGED
|
@@ -9,689 +9,430 @@ import Foundation
|
|
|
9
9
|
import HealthKit
|
|
10
10
|
import NitroModules
|
|
11
11
|
|
|
12
|
-
func
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
return Date.init(timeIntervalSince1970: timestamp)
|
|
18
|
-
}
|
|
19
|
-
return nil
|
|
12
|
+
func getQueryLimit(_ limit: Double) -> Int {
|
|
13
|
+
if limit == .infinity || limit <= 0 || limit == .nan || limit == .signalingNaN {
|
|
14
|
+
return HKObjectQueryNoLimit
|
|
15
|
+
}
|
|
20
16
|
|
|
17
|
+
return Int(limit)
|
|
21
18
|
}
|
|
22
19
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return Int(limit)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return HKObjectQueryNoLimit
|
|
20
|
+
struct AnchoredQueryResponse {
|
|
21
|
+
var samples: [HKSample]
|
|
22
|
+
var deletedSamples: [DeletedSample]
|
|
23
|
+
var newAnchor: String
|
|
33
24
|
}
|
|
34
25
|
|
|
35
|
-
func
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return HKQuery.predicateForWorkouts(with: op, duration: durationPredicate.durationInSeconds)
|
|
59
|
-
}
|
|
60
|
-
throw RuntimeError.error(withMessage: "[react-native-healthkit] Failed to initialize unrecognized workout duration predicate operator \(durationPredicate.predicateOperator.rawValue)")
|
|
61
|
-
}
|
|
62
|
-
}
|
|
26
|
+
func sampleAnchoredQueryAsync(
|
|
27
|
+
sampleType: HKSampleType,
|
|
28
|
+
limit: Double,
|
|
29
|
+
queryAnchor: String?,
|
|
30
|
+
predicate: NSPredicate?
|
|
31
|
+
) async throws -> AnchoredQueryResponse {
|
|
32
|
+
let queryAnchor = try deserializeHKQueryAnchor(base64String: queryAnchor)
|
|
33
|
+
|
|
34
|
+
return try await withCheckedThrowingContinuation { continuation in
|
|
35
|
+
let query = HKAnchoredObjectQuery(
|
|
36
|
+
type: sampleType,
|
|
37
|
+
predicate: predicate,
|
|
38
|
+
anchor: queryAnchor,
|
|
39
|
+
limit: getQueryLimit(limit)
|
|
40
|
+
) {
|
|
41
|
+
(
|
|
42
|
+
_: HKAnchoredObjectQuery, samples: [HKSample]?, deletedSamples: [HKDeletedObject]?,
|
|
43
|
+
newAnchor:
|
|
44
|
+
HKQueryAnchor?, error: Error?
|
|
45
|
+
) in
|
|
46
|
+
if let error = error {
|
|
47
|
+
return continuation.resume(throwing: error)
|
|
48
|
+
}
|
|
63
49
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
throw RuntimeError.error(withMessage: "[react-native-healthkit] Failed to initialize workout for filter")
|
|
80
|
-
case .sixth(let activityType):
|
|
81
|
-
if let activityType = HKWorkoutActivityType.init(rawValue: UInt(activityType.workoutActivityType.rawValue)) {
|
|
82
|
-
return HKQuery.predicateForWorkouts(with: activityType)
|
|
83
|
-
} else {
|
|
84
|
-
throw RuntimeError.error(withMessage: "[react-native-healthkit] Failed to initialize unrecognized workoutActivityType with identifier \(activityType.workoutActivityType.rawValue)")
|
|
85
|
-
}
|
|
86
|
-
case .seventh(let durationPredicate):
|
|
87
|
-
if let op = NSComparisonPredicate.Operator(rawValue: UInt(durationPredicate.predicateOperator.rawValue)) {
|
|
88
|
-
return HKQuery.predicateForWorkouts(with: op, duration: durationPredicate.durationInSeconds)
|
|
89
|
-
}
|
|
90
|
-
throw RuntimeError.error(withMessage: "[react-native-healthkit] Failed to initialize unrecognized workout duration predicate operator \(durationPredicate.predicateOperator.rawValue)")
|
|
91
|
-
|
|
92
|
-
case .eigth(let or):
|
|
93
|
-
return NSCompoundPredicate.init(andPredicateWithSubpredicates: try or.OR.map { predicate in
|
|
94
|
-
return try createPredicateForWorkout(filter: predicate)
|
|
95
|
-
})
|
|
96
|
-
case .ninth(let and):
|
|
97
|
-
return NSCompoundPredicate.init(orPredicateWithSubpredicates: try and.AND
|
|
98
|
-
.map { predicate in
|
|
99
|
-
return try createPredicateForWorkout(filter: predicate)
|
|
100
|
-
})
|
|
101
|
-
}
|
|
50
|
+
if let samples = samples, let deletedSamples = deletedSamples,
|
|
51
|
+
let newAnchor = serializeAnchor(anchor: newAnchor) {
|
|
52
|
+
return continuation.resume(
|
|
53
|
+
returning: AnchoredQueryResponse(
|
|
54
|
+
samples: samples,
|
|
55
|
+
deletedSamples: deletedSamples.map({ deletedSample in
|
|
56
|
+
return serializeDeletedSample(sample: deletedSample)
|
|
57
|
+
}),
|
|
58
|
+
newAnchor: newAnchor
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return continuation.resume(
|
|
64
|
+
throwing: runtimeErrorWithPrefix("Unexpected empty response"))
|
|
102
65
|
}
|
|
103
66
|
|
|
104
|
-
|
|
67
|
+
store.execute(query)
|
|
68
|
+
}
|
|
105
69
|
}
|
|
106
70
|
|
|
107
|
-
func
|
|
108
|
-
|
|
109
|
-
let strictEndDate = dateFilter.strictEndDate ?? false
|
|
110
|
-
|
|
111
|
-
let options: HKQueryOptions = strictStartDate && strictEndDate
|
|
112
|
-
? [.strictStartDate, .strictEndDate]
|
|
113
|
-
: strictEndDate
|
|
114
|
-
? .strictEndDate
|
|
115
|
-
: strictStartDate
|
|
116
|
-
? .strictStartDate
|
|
117
|
-
: []
|
|
118
|
-
|
|
119
|
-
return HKQuery.predicateForSamples(
|
|
120
|
-
withStart: dateFilter.startDate,
|
|
121
|
-
end: dateFilter.endDate,
|
|
122
|
-
options: options
|
|
123
|
-
)
|
|
71
|
+
func serializeAnchor(anchor: HKQueryAnchor?) -> String? {
|
|
72
|
+
return toBase64(anchor)
|
|
124
73
|
}
|
|
125
74
|
|
|
126
|
-
func
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
return HKQuery.predicateForObjects(with: Set(uuids))
|
|
75
|
+
func toBase64(_ data: Any?) -> String? {
|
|
76
|
+
if let data = data {
|
|
77
|
+
let data = NSKeyedArchiver.archivedData(withRootObject: data)
|
|
78
|
+
let encoded = data.base64EncodedString()
|
|
79
|
+
|
|
80
|
+
return encoded
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return nil
|
|
137
84
|
}
|
|
138
85
|
|
|
139
|
-
func
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
86
|
+
func sampleQueryAsync(
|
|
87
|
+
sampleType: HKSampleType,
|
|
88
|
+
limit: Double,
|
|
89
|
+
predicate: NSPredicate?,
|
|
90
|
+
sortDescriptors: [NSSortDescriptor]?
|
|
91
|
+
) async throws -> [HKSample] {
|
|
92
|
+
let limit = getQueryLimit(limit)
|
|
93
|
+
return try await withCheckedThrowingContinuation { continuation in
|
|
94
|
+
let q = HKSampleQuery(
|
|
95
|
+
sampleType: sampleType,
|
|
96
|
+
predicate: predicate,
|
|
97
|
+
limit: limit,
|
|
98
|
+
sortDescriptors: sortDescriptors,
|
|
99
|
+
) { (_: HKSampleQuery, samples: [HKSample]?, error: Error?) in
|
|
100
|
+
if let error = error {
|
|
101
|
+
return continuation.resume(throwing: error)
|
|
102
|
+
}
|
|
143
103
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
case .first(let boolValue):
|
|
148
|
-
actualValue = NSNumber(value: boolValue ? 1 : 0)
|
|
149
|
-
case .second(let stringValue):
|
|
150
|
-
actualValue = stringValue
|
|
151
|
-
case .third(let doubleValue):
|
|
152
|
-
actualValue = NSNumber(value: doubleValue)
|
|
153
|
-
case .fourth(let dateValue):
|
|
154
|
-
actualValue = dateValue
|
|
155
|
-
}
|
|
104
|
+
if let samples = samples {
|
|
105
|
+
return continuation.resume(returning: samples)
|
|
106
|
+
}
|
|
156
107
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if let operatorTypeValue = metadataKey.operatorType {
|
|
160
|
-
switch operatorTypeValue {
|
|
161
|
-
case PredicateWithMetadataOperator.equalto:
|
|
162
|
-
operatorType = .equalTo
|
|
163
|
-
case PredicateWithMetadataOperator.notequalto:
|
|
164
|
-
operatorType = .notEqualTo
|
|
165
|
-
case PredicateWithMetadataOperator.greaterthan:
|
|
166
|
-
operatorType = .greaterThan
|
|
167
|
-
case PredicateWithMetadataOperator.lessthan:
|
|
168
|
-
operatorType = .lessThan
|
|
169
|
-
default:
|
|
170
|
-
throw RuntimeError.error(withMessage: "Unsupported operator: \(operatorTypeValue)")
|
|
171
|
-
}
|
|
172
|
-
} else {
|
|
173
|
-
operatorType = .equalTo
|
|
108
|
+
return continuation.resume(
|
|
109
|
+
throwing: runtimeErrorWithPrefix("Unexpected empty response"))
|
|
174
110
|
}
|
|
175
111
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
operatorType: operatorType,
|
|
179
|
-
value: actualValue
|
|
180
|
-
)
|
|
112
|
+
store.execute(q)
|
|
113
|
+
}
|
|
181
114
|
}
|
|
182
115
|
|
|
183
|
-
func
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
return try createMetadataPredicate(metadataKey: metadataKey)
|
|
192
|
-
case .fourth(let dateFilter):
|
|
193
|
-
return createDatePredicate(dateFilter: dateFilter)
|
|
194
|
-
case .fifth(let w):
|
|
195
|
-
if let w = w.workout as? WorkoutProxy {
|
|
196
|
-
return w.workoutPredicate
|
|
197
|
-
}
|
|
198
|
-
throw RuntimeError.error(withMessage: "[react-native-healthkit] Failed to initialize workout for filter")
|
|
199
|
-
case .sixth(let and):
|
|
200
|
-
return NSCompoundPredicate.init(andPredicateWithSubpredicates: try and.AND.map { predicate in
|
|
201
|
-
return try createPredicateForSamples(filter: predicate)
|
|
202
|
-
})
|
|
203
|
-
case .seventh(let or):
|
|
204
|
-
return NSCompoundPredicate.init(orPredicateWithSubpredicates: try or.OR
|
|
205
|
-
.map { predicate in
|
|
206
|
-
return try createPredicateForSamples(filter: predicate)
|
|
207
|
-
})
|
|
208
|
-
}
|
|
116
|
+
func saveAsync(sample: HKObject) async throws -> Bool {
|
|
117
|
+
return try await withCheckedThrowingContinuation { continuation in
|
|
118
|
+
store.save(sample) { (success: Bool, error: Error?) in
|
|
119
|
+
if let error = error {
|
|
120
|
+
continuation.resume(throwing: error)
|
|
121
|
+
} else {
|
|
122
|
+
continuation.resume(returning: success)
|
|
123
|
+
}
|
|
209
124
|
}
|
|
210
|
-
|
|
125
|
+
}
|
|
211
126
|
}
|
|
212
127
|
|
|
213
|
-
func
|
|
214
|
-
|
|
215
|
-
case .first(let uuidWrapper):
|
|
216
|
-
return HKQuery.predicateForObject(with: try initializeUUID(uuidWrapper.uuid))
|
|
217
|
-
case .second(let uuidsWrapper):
|
|
218
|
-
return createUUIDsPredicate(uuidsWrapper: uuidsWrapper)
|
|
219
|
-
case .third(let metadataKey):
|
|
220
|
-
return try createMetadataPredicate(metadataKey: metadataKey)
|
|
221
|
-
case .fourth(let dateFilter):
|
|
222
|
-
return createDatePredicate(dateFilter: dateFilter)
|
|
223
|
-
case .fifth(let w):
|
|
224
|
-
if let w = w.workout as? WorkoutProxy {
|
|
225
|
-
return w.workoutPredicate
|
|
226
|
-
}
|
|
227
|
-
throw RuntimeError.error(withMessage: "[react-native-healthkit] Failed to initialize workout for filter")
|
|
228
|
-
}
|
|
128
|
+
func getSortDescriptors(ascending: Bool?) -> [NSSortDescriptor] {
|
|
129
|
+
return [NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: ascending ?? false)]
|
|
229
130
|
}
|
|
230
131
|
|
|
231
|
-
func
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
case .second(let uuidsWrapper):
|
|
236
|
-
return createUUIDsPredicate(uuidsWrapper: uuidsWrapper)
|
|
237
|
-
case .third(let metadataKey):
|
|
238
|
-
return try createMetadataPredicate(metadataKey: metadataKey)
|
|
239
|
-
case .fourth(let dateFilter):
|
|
240
|
-
return createDatePredicate(dateFilter: dateFilter)
|
|
241
|
-
case .fifth(let w):
|
|
242
|
-
if let w = w.workout as? WorkoutProxy {
|
|
243
|
-
return w.workoutPredicate
|
|
244
|
-
}
|
|
245
|
-
throw RuntimeError.error(withMessage: "[react-native-healthkit] Failed to initialize workout for filter")
|
|
246
|
-
case .sixth(let and):
|
|
247
|
-
return NSCompoundPredicate.init(andPredicateWithSubpredicates: try and.AND.map { predicate in
|
|
248
|
-
return try createPredicateForSamples(filter: predicate)
|
|
249
|
-
})
|
|
250
|
-
case .seventh(let or):
|
|
251
|
-
return NSCompoundPredicate.init(orPredicateWithSubpredicates: try or.OR
|
|
252
|
-
.map { predicate in
|
|
253
|
-
return try createPredicateForSamples(filter: predicate)
|
|
254
|
-
})
|
|
132
|
+
func fromBase64(base64String: String?) throws -> Any? {
|
|
133
|
+
if let base64String = base64String {
|
|
134
|
+
if base64String.isEmpty {
|
|
135
|
+
return nil
|
|
255
136
|
}
|
|
256
|
-
}
|
|
257
137
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
return HKQuery.predicateForObject(with: try initializeUUID(uuidWrapper.uuid))
|
|
262
|
-
case .second(let uuidsWrapper):
|
|
263
|
-
return createUUIDsPredicate(uuidsWrapper: uuidsWrapper)
|
|
264
|
-
case .third(let metadataKey):
|
|
265
|
-
return try createMetadataPredicate(metadataKey: metadataKey)
|
|
266
|
-
case .fourth(let dateFilter):
|
|
267
|
-
return createDatePredicate(dateFilter: dateFilter)
|
|
268
|
-
case .fifth(let w):
|
|
269
|
-
if let w = w.workout as? WorkoutProxy {
|
|
270
|
-
return w.workoutPredicate
|
|
271
|
-
}
|
|
272
|
-
throw RuntimeError.error(withMessage: "[react-native-healthkit] Failed to initialize workout for filter")
|
|
273
|
-
case .sixth(let and):
|
|
274
|
-
return NSCompoundPredicate.init(andPredicateWithSubpredicates: try and.AND.map { predicate in
|
|
275
|
-
return try createPredicateForSamples(filter: predicate)
|
|
276
|
-
})
|
|
277
|
-
case .seventh(let or):
|
|
278
|
-
return NSCompoundPredicate.init(orPredicateWithSubpredicates: try or.OR
|
|
279
|
-
.map { predicate in
|
|
280
|
-
return try createPredicateForSamples(filter: predicate)
|
|
281
|
-
})
|
|
138
|
+
// Step 1: Decode the base64 string to a Data object
|
|
139
|
+
guard let data = Data(base64Encoded: base64String) else {
|
|
140
|
+
throw runtimeErrorWithPrefix("Invalid base64 string: \(base64String)")
|
|
282
141
|
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
func getSortDescriptors(ascending: Bool?) -> [NSSortDescriptor] {
|
|
286
|
-
return [NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: ascending ?? false)]
|
|
287
|
-
}
|
|
288
142
|
|
|
289
|
-
|
|
290
|
-
|
|
143
|
+
// Step 2: Use NSKeyedUnarchiver to unarchive the data and create an HKQueryAnchor object
|
|
144
|
+
do {
|
|
145
|
+
let unarchiver = try NSKeyedUnarchiver(forReadingFrom: data)
|
|
146
|
+
unarchiver.requiresSecureCoding = true
|
|
147
|
+
return try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data)
|
|
148
|
+
} catch {
|
|
149
|
+
throw runtimeErrorWithPrefix(
|
|
150
|
+
"Error recreating HKQueryAnchor object: \(error.localizedDescription)")
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return nil
|
|
291
154
|
}
|
|
292
155
|
|
|
293
156
|
func deserializeHKQueryAnchor(base64String: String?) throws -> HKQueryAnchor? {
|
|
294
|
-
|
|
295
|
-
if base64String.isEmpty {
|
|
296
|
-
return nil
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
// Step 1: Decode the base64 string to a Data object
|
|
300
|
-
guard let data = Data(base64Encoded: base64String) else {
|
|
301
|
-
throw RuntimeError.error(withMessage: "[react-native-healthkit] Invalid base64 string: \(base64String)")
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// Step 2: Use NSKeyedUnarchiver to unarchive the data and create an HKQueryAnchor object
|
|
305
|
-
do {
|
|
306
|
-
let unarchiver = try NSKeyedUnarchiver(forReadingFrom: data)
|
|
307
|
-
unarchiver.requiresSecureCoding = true
|
|
308
|
-
let anchor = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data)
|
|
309
|
-
|
|
310
|
-
return anchor as? HKQueryAnchor
|
|
311
|
-
} catch {
|
|
312
|
-
throw RuntimeError.error(withMessage: "[react-native-healthkit] Error recreating HKQueryAnchor object: \(error.localizedDescription)")
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
return nil
|
|
157
|
+
return try fromBase64(base64String: base64String) as? HKQueryAnchor
|
|
316
158
|
}
|
|
317
159
|
|
|
318
160
|
func initializeCategoryType(_ identifier: String) throws -> HKCategoryType {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
161
|
+
let identifier = HKCategoryTypeIdentifier(rawValue: identifier)
|
|
162
|
+
if let sampleType = HKSampleType.categoryType(forIdentifier: identifier) {
|
|
163
|
+
return sampleType
|
|
164
|
+
}
|
|
323
165
|
|
|
324
|
-
|
|
166
|
+
throw runtimeErrorWithPrefix(
|
|
167
|
+
"Failed to initialize unrecognized categoryType with identifier \(identifier)")
|
|
325
168
|
}
|
|
326
169
|
|
|
327
170
|
func initializeWorkoutActivityType(_ typeIdentifier: UInt) throws -> HKWorkoutActivityType {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
171
|
+
if let type = HKWorkoutActivityType.init(rawValue: typeIdentifier) {
|
|
172
|
+
return type
|
|
173
|
+
}
|
|
331
174
|
|
|
332
|
-
|
|
175
|
+
throw runtimeErrorWithPrefix(
|
|
176
|
+
"Failed to initialize unrecognized quantityType with identifier \(typeIdentifier)")
|
|
333
177
|
}
|
|
334
178
|
|
|
335
179
|
func initializeQuantityType(_ identifier: String) throws -> HKQuantityType {
|
|
336
|
-
|
|
180
|
+
let identifier = HKQuantityTypeIdentifier(rawValue: identifier)
|
|
337
181
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
182
|
+
if let sampleType = HKSampleType.quantityType(forIdentifier: identifier) {
|
|
183
|
+
return sampleType
|
|
184
|
+
}
|
|
341
185
|
|
|
342
|
-
|
|
186
|
+
throw runtimeErrorWithPrefix(
|
|
187
|
+
"Failed to initialize unrecognized quantityType with identifier \(identifier)")
|
|
343
188
|
}
|
|
344
189
|
|
|
345
190
|
func initializeCorrelationType(_ identifier: String) throws -> HKCorrelationType {
|
|
346
|
-
|
|
191
|
+
let identifier = HKCorrelationTypeIdentifier(rawValue: identifier)
|
|
347
192
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
193
|
+
if let sampleType = HKSampleType.correlationType(forIdentifier: identifier) {
|
|
194
|
+
return sampleType
|
|
195
|
+
}
|
|
351
196
|
|
|
352
|
-
|
|
197
|
+
throw runtimeErrorWithPrefix(
|
|
198
|
+
"Failed to initialize unrecognized correlationType with identifier \(identifier)")
|
|
353
199
|
}
|
|
354
200
|
|
|
355
201
|
func initializeSeriesType(_ identifier: String) throws -> HKSeriesType {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
202
|
+
if let seriesType = HKObjectType.seriesType(forIdentifier: identifier) {
|
|
203
|
+
return seriesType
|
|
204
|
+
}
|
|
359
205
|
|
|
360
|
-
|
|
206
|
+
throw runtimeErrorWithPrefix(
|
|
207
|
+
"Failed to initialize unrecognized seriesType with identifier \(identifier)")
|
|
361
208
|
}
|
|
362
209
|
|
|
363
210
|
func sampleTypeFrom(sampleTypeIdentifier: SampleTypeIdentifier) throws -> HKSampleType {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
211
|
+
if let sampleType = try sampleTypeFromStringNullable(
|
|
212
|
+
typeIdentifier: sampleTypeIdentifier.stringValue) {
|
|
213
|
+
return sampleType
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
throw runtimeErrorWithPrefix(
|
|
217
|
+
"Failed to initialize unrecognized sampleType with identifier \(sampleTypeIdentifier.stringValue)"
|
|
218
|
+
)
|
|
369
219
|
}
|
|
370
220
|
|
|
371
|
-
func sampleTypeFrom(sampleTypeIdentifierWriteable: SampleTypeIdentifierWriteable) throws
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
221
|
+
func sampleTypeFrom(sampleTypeIdentifierWriteable: SampleTypeIdentifierWriteable) throws
|
|
222
|
+
-> HKSampleType {
|
|
223
|
+
if let sampleType = try sampleTypeFromStringNullable(
|
|
224
|
+
typeIdentifier: sampleTypeIdentifierWriteable.stringValue) {
|
|
225
|
+
return sampleType
|
|
226
|
+
}
|
|
375
227
|
|
|
376
|
-
|
|
228
|
+
throw runtimeErrorWithPrefix(
|
|
229
|
+
"Failed to initialize unrecognized sampleType with identifier \(sampleTypeIdentifierWriteable.stringValue)"
|
|
230
|
+
)
|
|
377
231
|
}
|
|
378
232
|
|
|
379
233
|
private func sampleTypeFromStringNullable(typeIdentifier: String) throws -> HKSampleType? {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
234
|
+
if typeIdentifier.starts(with: HKQuantityTypeIdentifier_PREFIX) {
|
|
235
|
+
return try initializeQuantityType(typeIdentifier)
|
|
236
|
+
}
|
|
383
237
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
238
|
+
if typeIdentifier.starts(with: HKCategoryTypeIdentifier_PREFIX) {
|
|
239
|
+
return try initializeCategoryType(typeIdentifier)
|
|
240
|
+
}
|
|
387
241
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
242
|
+
if typeIdentifier.starts(with: HKCorrelationTypeIdentifier_PREFIX) {
|
|
243
|
+
return try initializeCorrelationType(typeIdentifier)
|
|
244
|
+
}
|
|
391
245
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
246
|
+
if typeIdentifier == HKWorkoutTypeIdentifier {
|
|
247
|
+
return HKSampleType.workoutType()
|
|
248
|
+
}
|
|
395
249
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
}
|
|
250
|
+
if #available(iOS 11.0, *) {
|
|
251
|
+
if typeIdentifier == HKWorkoutRouteTypeIdentifier {
|
|
252
|
+
return try initializeSeriesType(typeIdentifier)
|
|
400
253
|
}
|
|
254
|
+
}
|
|
401
255
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
256
|
+
if #available(iOS 13, *) {
|
|
257
|
+
if typeIdentifier == HKAudiogramTypeIdentifier {
|
|
258
|
+
return HKObjectType.audiogramSampleType()
|
|
259
|
+
}
|
|
406
260
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
261
|
+
if typeIdentifier == HKDataTypeIdentifierHeartbeatSeries {
|
|
262
|
+
return try initializeSeriesType(typeIdentifier)
|
|
263
|
+
}
|
|
410
264
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
}
|
|
265
|
+
if typeIdentifier == HKAudiogramTypeIdentifier {
|
|
266
|
+
return HKSampleType.audiogramSampleType()
|
|
414
267
|
}
|
|
268
|
+
}
|
|
415
269
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
}
|
|
270
|
+
if #available(iOS 14, *) {
|
|
271
|
+
if typeIdentifier == HKElectrocardiogramType {
|
|
272
|
+
return HKSampleType.electrocardiogramType()
|
|
420
273
|
}
|
|
274
|
+
}
|
|
421
275
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
276
|
+
#if compiler(>=6)
|
|
277
|
+
if #available(iOS 18, *) {
|
|
278
|
+
if typeIdentifier == HKStateOfMindTypeIdentifier {
|
|
279
|
+
return HKObjectType.stateOfMindType()
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
#endif
|
|
429
283
|
|
|
430
|
-
|
|
284
|
+
return nil
|
|
431
285
|
}
|
|
432
286
|
|
|
433
287
|
func objectTypesFromArray(typeIdentifiers: [ObjectTypeIdentifier]) -> Set<HKObjectType> {
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
288
|
+
var share = Set<HKObjectType>()
|
|
289
|
+
for typeIdentifier in typeIdentifiers {
|
|
290
|
+
do {
|
|
291
|
+
let objectType = try objectTypeFrom(objectTypeIdentifier: typeIdentifier)
|
|
292
|
+
share.insert(objectType)
|
|
293
|
+
} catch {
|
|
294
|
+
warnWithPrefix("objectTypesFromArray: \(error.localizedDescription)")
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return share
|
|
444
298
|
}
|
|
445
299
|
|
|
446
300
|
func initializeUUID(_ uuidString: String) throws -> UUID {
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
301
|
+
if let uuid = UUID(uuidString: uuidString) {
|
|
302
|
+
return uuid
|
|
303
|
+
}
|
|
450
304
|
|
|
451
|
-
|
|
305
|
+
throw runtimeErrorWithPrefix("Got invalid UUID: \(uuidString)")
|
|
452
306
|
}
|
|
453
307
|
|
|
454
308
|
func sampleTypesFromArray(typeIdentifiers: [SampleTypeIdentifier]) -> Set<HKSampleType> {
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
309
|
+
return Set(
|
|
310
|
+
typeIdentifiers.compactMap { typeIdentifier in
|
|
311
|
+
do {
|
|
312
|
+
let sampleType = try sampleTypeFrom(sampleTypeIdentifier: typeIdentifier)
|
|
313
|
+
return sampleType
|
|
314
|
+
} catch {
|
|
315
|
+
warnWithPrefix("sampleTypesFromArray: \(error.localizedDescription)")
|
|
316
|
+
}
|
|
317
|
+
return nil
|
|
463
318
|
})
|
|
464
319
|
}
|
|
465
320
|
|
|
466
|
-
func sampleTypesFromArray(typeIdentifiersWriteable: [SampleTypeIdentifierWriteable]) -> Set<
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
321
|
+
func sampleTypesFromArray(typeIdentifiersWriteable: [SampleTypeIdentifierWriteable]) -> Set<
|
|
322
|
+
HKSampleType
|
|
323
|
+
> {
|
|
324
|
+
return Set(
|
|
325
|
+
typeIdentifiersWriteable.compactMap { typeIdentifier in
|
|
326
|
+
do {
|
|
327
|
+
let sampleType = try sampleTypeFrom(sampleTypeIdentifierWriteable: typeIdentifier)
|
|
328
|
+
return sampleType
|
|
329
|
+
} catch {
|
|
330
|
+
warnWithPrefix("sampleTypesFromArray: \(error.localizedDescription)")
|
|
331
|
+
}
|
|
332
|
+
return nil
|
|
475
333
|
})
|
|
476
334
|
}
|
|
477
335
|
|
|
478
336
|
// objectType is wider than sampleType, so it uses it under the hood
|
|
479
337
|
func objectTypeFrom(objectTypeIdentifier: ObjectTypeIdentifier) throws -> HKObjectType {
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
338
|
+
let typeIdentifier = objectTypeIdentifier.stringValue
|
|
339
|
+
if let sampleType = try sampleTypeFromStringNullable(typeIdentifier: typeIdentifier) {
|
|
340
|
+
return sampleType
|
|
341
|
+
}
|
|
484
342
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
}
|
|
343
|
+
if typeIdentifier.starts(with: HKCharacteristicTypeIdentifier_PREFIX) {
|
|
344
|
+
let identifier = HKCharacteristicTypeIdentifier.init(rawValue: typeIdentifier)
|
|
345
|
+
if let type = HKObjectType.characteristicType(forIdentifier: identifier) as HKObjectType? {
|
|
346
|
+
return type
|
|
490
347
|
}
|
|
348
|
+
}
|
|
491
349
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
350
|
+
if typeIdentifier == HKActivitySummaryTypeIdentifier {
|
|
351
|
+
return HKObjectType.activitySummaryType()
|
|
352
|
+
}
|
|
495
353
|
|
|
496
|
-
|
|
354
|
+
throw runtimeErrorWithPrefix(
|
|
355
|
+
"Failed initializing unrecognized objectType identifier " + typeIdentifier)
|
|
497
356
|
}
|
|
498
357
|
|
|
499
358
|
func hkStatisticsOptionsFromOptions(_ options: NSArray) -> HKStatisticsOptions {
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
}
|
|
359
|
+
var opts = HKStatisticsOptions()
|
|
360
|
+
|
|
361
|
+
for o in options {
|
|
362
|
+
guard let str = o as? String else { continue }
|
|
363
|
+
|
|
364
|
+
switch str {
|
|
365
|
+
case "cumulativeSum":
|
|
366
|
+
opts.insert(.cumulativeSum)
|
|
367
|
+
case "discreteAverage":
|
|
368
|
+
opts.insert(.discreteAverage)
|
|
369
|
+
case "discreteMax":
|
|
370
|
+
opts.insert(.discreteMax)
|
|
371
|
+
case "discreteMin":
|
|
372
|
+
opts.insert(.discreteMin)
|
|
373
|
+
case "duration":
|
|
374
|
+
if #available(iOS 13, *) {
|
|
375
|
+
opts.insert(.duration)
|
|
376
|
+
}
|
|
377
|
+
case "mostRecent":
|
|
378
|
+
if #available(iOS 13, *) {
|
|
379
|
+
opts.insert(.mostRecent)
|
|
380
|
+
}
|
|
381
|
+
case "separateBySource":
|
|
382
|
+
opts.insert(.separateBySource)
|
|
383
|
+
default:
|
|
384
|
+
continue
|
|
527
385
|
}
|
|
386
|
+
}
|
|
528
387
|
|
|
529
|
-
|
|
388
|
+
return opts
|
|
530
389
|
}
|
|
531
390
|
|
|
532
391
|
func componentsFromInterval(_ interval: NSDictionary) -> DateComponents {
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
392
|
+
let componentKeys: [String: WritableKeyPath<DateComponents, Int?>] = [
|
|
393
|
+
"minute": \.minute,
|
|
394
|
+
"hour": \.hour,
|
|
395
|
+
"day": \.day,
|
|
396
|
+
"month": \.month,
|
|
397
|
+
"year": \.year,
|
|
398
|
+
]
|
|
399
|
+
|
|
400
|
+
var intervalComponents = DateComponents()
|
|
401
|
+
for (key, keyPath) in componentKeys {
|
|
402
|
+
if let value = interval[key] as? Int {
|
|
403
|
+
intervalComponents[keyPath: keyPath] = value
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return intervalComponents
|
|
548
407
|
}
|
|
549
408
|
|
|
550
409
|
func parseWorkoutConfiguration(_ config: WorkoutConfiguration) -> HKWorkoutConfiguration {
|
|
551
|
-
|
|
410
|
+
let configuration = HKWorkoutConfiguration()
|
|
552
411
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
412
|
+
if let activityType = HKWorkoutActivityType(rawValue: UInt(config.activityType.rawValue)) {
|
|
413
|
+
configuration.activityType = activityType
|
|
414
|
+
}
|
|
556
415
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
416
|
+
if let locationTypeRaw = config.locationType,
|
|
417
|
+
let locationType = HKWorkoutSessionLocationType(rawValue: Int(locationTypeRaw.rawValue)) {
|
|
418
|
+
configuration.locationType = locationType
|
|
419
|
+
}
|
|
561
420
|
|
|
562
|
-
|
|
421
|
+
return configuration
|
|
563
422
|
}
|
|
564
423
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
.activeEnergyBurned,
|
|
580
|
-
.flightsClimbed,
|
|
581
|
-
.nikeFuel,
|
|
582
|
-
.appleExerciseTime,
|
|
583
|
-
.pushCount,
|
|
584
|
-
.distanceSwimming,
|
|
585
|
-
.swimmingStrokeCount,
|
|
586
|
-
.vo2Max,
|
|
587
|
-
.distanceDownhillSnowSports,
|
|
588
|
-
.appleStandTime,
|
|
589
|
-
.walkingSpeed,
|
|
590
|
-
.walkingDoubleSupportPercentage,
|
|
591
|
-
.walkingAsymmetryPercentage,
|
|
592
|
-
.walkingStepLength,
|
|
593
|
-
.sixMinuteWalkTestDistance,
|
|
594
|
-
.stairAscentSpeed,
|
|
595
|
-
.stairDescentSpeed,
|
|
596
|
-
.heartRate,
|
|
597
|
-
.bodyTemperature,
|
|
598
|
-
.basalBodyTemperature,
|
|
599
|
-
.bloodPressureSystolic,
|
|
600
|
-
.bloodPressureDiastolic,
|
|
601
|
-
.respiratoryRate,
|
|
602
|
-
.restingHeartRate,
|
|
603
|
-
.walkingHeartRateAverage,
|
|
604
|
-
.heartRateVariabilitySDNN,
|
|
605
|
-
.oxygenSaturation,
|
|
606
|
-
.peripheralPerfusionIndex,
|
|
607
|
-
.bloodGlucose,
|
|
608
|
-
.numberOfTimesFallen,
|
|
609
|
-
.electrodermalActivity,
|
|
610
|
-
.inhalerUsage,
|
|
611
|
-
.insulinDelivery,
|
|
612
|
-
.bloodAlcoholContent,
|
|
613
|
-
.forcedVitalCapacity,
|
|
614
|
-
.forcedExpiratoryVolume1,
|
|
615
|
-
.peakExpiratoryFlowRate,
|
|
616
|
-
.environmentalAudioExposure,
|
|
617
|
-
.headphoneAudioExposure,
|
|
618
|
-
.dietaryFatTotal,
|
|
619
|
-
.dietaryFatPolyunsaturated,
|
|
620
|
-
.dietaryFatMonounsaturated,
|
|
621
|
-
.dietaryFatSaturated,
|
|
622
|
-
.dietaryCholesterol,
|
|
623
|
-
.dietarySodium,
|
|
624
|
-
.dietaryCarbohydrates,
|
|
625
|
-
.dietaryFiber,
|
|
626
|
-
.dietarySugar,
|
|
627
|
-
.dietaryEnergyConsumed,
|
|
628
|
-
.dietaryProtein,
|
|
629
|
-
.dietaryVitaminA,
|
|
630
|
-
.dietaryVitaminB6,
|
|
631
|
-
.dietaryVitaminB12,
|
|
632
|
-
.dietaryVitaminC,
|
|
633
|
-
.dietaryVitaminD,
|
|
634
|
-
.dietaryVitaminE,
|
|
635
|
-
.dietaryVitaminK,
|
|
636
|
-
.dietaryCalcium,
|
|
637
|
-
.dietaryIron,
|
|
638
|
-
.dietaryThiamin,
|
|
639
|
-
.dietaryRiboflavin,
|
|
640
|
-
.dietaryNiacin,
|
|
641
|
-
.dietaryFolate,
|
|
642
|
-
.dietaryBiotin,
|
|
643
|
-
.dietaryPantothenicAcid,
|
|
644
|
-
.dietaryPhosphorus,
|
|
645
|
-
.dietaryIodine,
|
|
646
|
-
.dietaryMagnesium,
|
|
647
|
-
.dietaryZinc,
|
|
648
|
-
.dietarySelenium,
|
|
649
|
-
.dietaryCopper,
|
|
650
|
-
.dietaryManganese,
|
|
651
|
-
.dietaryChromium,
|
|
652
|
-
.dietaryMolybdenum,
|
|
653
|
-
.dietaryChloride,
|
|
654
|
-
.dietaryPotassium,
|
|
655
|
-
.dietaryCaffeine,
|
|
656
|
-
.dietaryWater,
|
|
657
|
-
.uvExposure
|
|
658
|
-
// Add more identifiers as needed for your iOS version
|
|
659
|
-
]
|
|
660
|
-
let supported = allIdentifiers.compactMap { identifier in
|
|
661
|
-
HKObjectType.quantityType(forIdentifier: identifier) != nil ? identifier.rawValue : nil
|
|
662
|
-
}
|
|
663
|
-
let missing = allIdentifiers.filter { HKObjectType.quantityType(forIdentifier: $0) == nil }
|
|
664
|
-
if !missing.isEmpty {
|
|
665
|
-
print("[react-native-healthkit] Warning: The following HKQuantityTypeIdentifiers are not available on this iOS version: \(missing.map { $0.rawValue })")
|
|
666
|
-
}
|
|
667
|
-
// --- New logic: Warn if any available identifier is not in the hardcoded list ---
|
|
668
|
-
// Try common HealthKit identifier strings (brute-force, as Apple does not provide a list)
|
|
669
|
-
let knownPrefixes = [
|
|
670
|
-
"HKQuantityTypeIdentifier",
|
|
671
|
-
"HKQuantityTypeIdentifierDietary",
|
|
672
|
-
"HKQuantityTypeIdentifierEnvironmental",
|
|
673
|
-
"HKQuantityTypeIdentifierBlood",
|
|
674
|
-
"HKQuantityTypeIdentifierBody",
|
|
675
|
-
"HKQuantityTypeIdentifierDistance",
|
|
676
|
-
"HKQuantityTypeIdentifierHeart",
|
|
677
|
-
"HKQuantityTypeIdentifierRespiratory",
|
|
678
|
-
"HKQuantityTypeIdentifierWalking",
|
|
679
|
-
"HKQuantityTypeIdentifierSwimming",
|
|
680
|
-
"HKQuantityTypeIdentifierApple"
|
|
681
|
-
]
|
|
682
|
-
var foundButNotListed: [String] = []
|
|
683
|
-
// Try all possible identifier strings (brute-force for demonstration, not exhaustive)
|
|
684
|
-
for codePoint in 0..<300 {
|
|
685
|
-
for prefix in knownPrefixes {
|
|
686
|
-
let candidate = prefix + String(codePoint)
|
|
687
|
-
if let type = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier(rawValue: candidate)),
|
|
688
|
-
!allIdentifiers.contains(where: { $0.rawValue == candidate }) {
|
|
689
|
-
foundButNotListed.append(candidate)
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
if !foundButNotListed.isEmpty {
|
|
694
|
-
print("[react-native-healthkit] Warning: The following HKQuantityTypeIdentifiers are available on this iOS version but NOT included in the hardcoded list: \(foundButNotListed)")
|
|
695
|
-
}
|
|
696
|
-
return supported
|
|
424
|
+
func anyMapToDictionary(_ anyMap: AnyMap) -> [String: Any] {
|
|
425
|
+
var dict = [String: Any]()
|
|
426
|
+
anyMap.getAllKeys().forEach { key in
|
|
427
|
+
dict[key] = getAnyMapValue(anyMap, key: key)
|
|
428
|
+
}
|
|
429
|
+
return dict
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
func runtimeErrorWithPrefix(_ withMessage: String) -> Error {
|
|
433
|
+
return RuntimeError.error(withMessage: "[react-native-healthkit] \(withMessage)")
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
func warnWithPrefix(_ withMessage: String) {
|
|
437
|
+
print("[react-native-healthkit] \(withMessage)")
|
|
697
438
|
}
|