@kingstinct/react-native-healthkit 10.1.0 → 11.1.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/README.md +2 -2
- package/ios/CoreModule.swift +5 -15
- package/ios/CorrelationTypeModule.swift +7 -2
- package/ios/ElectrocardiogramModule.swift +210 -0
- package/ios/QuantityTypeModule.swift +113 -124
- package/ios/Serializers.swift +39 -66
- package/ios/WorkoutProxy.swift +38 -20
- package/ios/WorkoutsModule.swift +7 -18
- package/lib/commonjs/healthkit.ios.js +6 -2
- package/lib/commonjs/healthkit.js +10 -2
- package/lib/commonjs/hooks/useMostRecentWorkout.js +2 -9
- package/lib/commonjs/hooks/useWorkoutById.js +1 -4
- package/lib/commonjs/modules.js +2 -1
- package/lib/commonjs/specs/ElectrocardiogramModule.nitro.js +2 -0
- package/lib/commonjs/types/ElectrocardiogramSample.js +2 -0
- package/lib/commonjs/utils/getMostRecentWorkout.js +1 -3
- package/lib/commonjs/utils/getWorkoutById.js +1 -3
- package/lib/module/healthkit.ios.js +5 -1
- package/lib/module/healthkit.js +8 -0
- package/lib/module/hooks/useMostRecentWorkout.js +3 -10
- package/lib/module/hooks/useWorkoutById.js +1 -4
- package/lib/module/modules.js +1 -0
- package/lib/module/specs/ElectrocardiogramModule.nitro.js +1 -0
- package/lib/module/types/ElectrocardiogramSample.js +1 -0
- package/lib/module/utils/getMostRecentWorkout.js +1 -3
- package/lib/module/utils/getWorkoutById.js +1 -3
- package/lib/typescript/healthkit.d.ts +3 -1
- package/lib/typescript/healthkit.ios.d.ts +5 -1
- package/lib/typescript/hooks/useMostRecentWorkout.d.ts +1 -4
- package/lib/typescript/modules.d.ts +2 -0
- package/lib/typescript/specs/ElectrocardiogramModule.nitro.d.ts +8 -0
- package/lib/typescript/specs/WorkoutProxy.nitro.d.ts +11 -0
- package/lib/typescript/types/ElectrocardiogramSample.d.ts +39 -0
- package/lib/typescript/types/Workouts.d.ts +0 -8
- package/lib/typescript/utils/getMostRecentWorkout.d.ts +1 -2
- package/lib/typescript/utils/getWorkoutById.d.ts +1 -2
- package/nitrogen/generated/ios/ReactNativeHealthkit-Swift-Cxx-Bridge.cpp +136 -87
- package/nitrogen/generated/ios/ReactNativeHealthkit-Swift-Cxx-Bridge.hpp +924 -493
- package/nitrogen/generated/ios/ReactNativeHealthkit-Swift-Cxx-Umbrella.hpp +29 -0
- package/nitrogen/generated/ios/ReactNativeHealthkitAutolinking.mm +16 -8
- package/nitrogen/generated/ios/ReactNativeHealthkitAutolinking.swift +31 -16
- package/nitrogen/generated/ios/c++/HybridCategoryTypeModuleSpecSwift.hpp +6 -4
- package/nitrogen/generated/ios/c++/HybridCharacteristicTypeModuleSpecSwift.hpp +4 -2
- package/nitrogen/generated/ios/c++/HybridCoreModuleSpecSwift.hpp +7 -5
- package/nitrogen/generated/ios/c++/HybridCorrelationTypeModuleSpecSwift.hpp +6 -4
- package/nitrogen/generated/ios/c++/HybridElectrocardiogramModuleSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridElectrocardiogramModuleSpecSwift.hpp +152 -0
- package/nitrogen/generated/ios/c++/HybridHeartbeatSeriesModuleSpecSwift.hpp +7 -5
- package/nitrogen/generated/ios/c++/HybridQuantityTypeModuleSpecSwift.hpp +5 -3
- package/nitrogen/generated/ios/c++/HybridSourceProxySpecSwift.hpp +3 -1
- package/nitrogen/generated/ios/c++/HybridStateOfMindModuleSpecSwift.hpp +7 -5
- package/nitrogen/generated/ios/c++/HybridWorkoutProxySpecSwift.hpp +50 -22
- package/nitrogen/generated/ios/c++/HybridWorkoutsModuleSpecSwift.hpp +9 -7
- package/nitrogen/generated/ios/swift/CategorySample.swift +4 -2
- package/nitrogen/generated/ios/swift/CategorySampleForSaving.swift +2 -1
- package/nitrogen/generated/ios/swift/CorrelationObject.swift +2 -0
- package/nitrogen/generated/ios/swift/DeletedSample.swift +2 -1
- package/nitrogen/generated/ios/swift/Device.swift +16 -8
- package/nitrogen/generated/ios/swift/ECGQueryOptionsWithAnchor.swift +179 -0
- package/nitrogen/generated/ios/swift/ECGQueryOptionsWithSortOrder.swift +184 -0
- package/nitrogen/generated/ios/swift/ElectrocardiogramClassification.swift +60 -0
- package/nitrogen/generated/ios/swift/ElectrocardiogramLead.swift +40 -0
- package/nitrogen/generated/ios/swift/ElectrocardiogramSample.swift +298 -0
- package/nitrogen/generated/ios/swift/ElectrocardiogramSamplesWithAnchorResponse.swift +81 -0
- package/nitrogen/generated/ios/swift/ElectrocardiogramSymptomsStatus.swift +44 -0
- package/nitrogen/generated/ios/swift/ElectrocardiogramVoltage.swift +57 -0
- package/nitrogen/generated/ios/swift/FilterForSamples.swift +2 -0
- package/nitrogen/generated/ios/swift/Func_void_AuthorizationRequestStatus.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_BiologicalSex.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_BloodType.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_CategorySamplesWithAnchorResponse.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_ElectrocardiogramSamplesWithAnchorResponse.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_FitzpatrickSkinType.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_HeartbeatSeriesSamplesWithAnchorResponse.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_OnChangeCallbackArgs.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_QuantitySamplesWithAnchorResponse.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_QueryStatisticsResponse.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_QueryWorkoutSamplesWithAnchorResponse.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_WheelchairUse.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_bool.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_double.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_std__optional_QueryStatisticsResponse_.swift +54 -0
- package/nitrogen/generated/ios/swift/Func_void_std__optional_WorkoutPlan_.swift +3 -1
- package/nitrogen/generated/ios/swift/Func_void_std__optional_std__chrono__system_clock__time_point_.swift +3 -1
- package/nitrogen/generated/ios/swift/{Func_void_std__shared_ptr_margelo__nitro__healthkit__HybridWorkoutProxySpec_.swift → Func_void_std__shared_ptr_HybridWorkoutProxySpec_.swift} +9 -8
- package/nitrogen/generated/ios/swift/Func_void_std__unordered_map_std__string__QueryStatisticsResponse_.swift +55 -0
- package/nitrogen/generated/ios/swift/Func_void_std__unordered_map_std__string__bool_.swift +2 -1
- package/nitrogen/generated/ios/swift/Func_void_std__vector_CategorySample_.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_CorrelationSample_.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_ElectrocardiogramSample_.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_HeartbeatSeriesSample_.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_IdentifierWithUnit_.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_QuantitySample_.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_QueryStatisticsResponse_.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_StateOfMindSample_.swift +1 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_WorkoutRoute_.swift +1 -0
- package/nitrogen/generated/ios/swift/{Func_void_std__vector_std__shared_ptr_margelo__nitro__healthkit__HybridSourceProxySpec__.swift → Func_void_std__vector_std__shared_ptr_HybridSourceProxySpec__.swift} +9 -8
- package/nitrogen/generated/ios/swift/{Func_void_std__vector_std__shared_ptr_margelo__nitro__healthkit__HybridWorkoutProxySpec__.swift → Func_void_std__vector_std__shared_ptr_HybridWorkoutProxySpec__.swift} +9 -8
- package/nitrogen/generated/ios/swift/HeartbeatSeriesSample.swift +6 -3
- package/nitrogen/generated/ios/swift/HybridCategoryTypeModuleSpec.swift +2 -1
- package/nitrogen/generated/ios/swift/HybridCategoryTypeModuleSpec_cxx.swift +17 -7
- package/nitrogen/generated/ios/swift/HybridCharacteristicTypeModuleSpec.swift +2 -1
- package/nitrogen/generated/ios/swift/HybridCharacteristicTypeModuleSpec_cxx.swift +15 -6
- package/nitrogen/generated/ios/swift/HybridCoreModuleSpec.swift +2 -1
- package/nitrogen/generated/ios/swift/HybridCoreModuleSpec_cxx.swift +24 -15
- package/nitrogen/generated/ios/swift/HybridCorrelationTypeModuleSpec.swift +2 -1
- package/nitrogen/generated/ios/swift/HybridCorrelationTypeModuleSpec_cxx.swift +15 -6
- package/nitrogen/generated/ios/swift/HybridElectrocardiogramModuleSpec.swift +50 -0
- package/nitrogen/generated/ios/swift/HybridElectrocardiogramModuleSpec_cxx.swift +162 -0
- package/nitrogen/generated/ios/swift/HybridHeartbeatSeriesModuleSpec.swift +2 -1
- package/nitrogen/generated/ios/swift/HybridHeartbeatSeriesModuleSpec_cxx.swift +17 -7
- package/nitrogen/generated/ios/swift/HybridQuantityTypeModuleSpec.swift +2 -1
- package/nitrogen/generated/ios/swift/HybridQuantityTypeModuleSpec_cxx.swift +21 -9
- package/nitrogen/generated/ios/swift/HybridSourceProxySpec.swift +2 -1
- package/nitrogen/generated/ios/swift/HybridSourceProxySpec_cxx.swift +17 -7
- package/nitrogen/generated/ios/swift/HybridStateOfMindModuleSpec.swift +2 -1
- package/nitrogen/generated/ios/swift/HybridStateOfMindModuleSpec_cxx.swift +19 -8
- package/nitrogen/generated/ios/swift/HybridWorkoutProxySpec.swift +8 -5
- package/nitrogen/generated/ios/swift/HybridWorkoutProxySpec_cxx.swift +108 -41
- package/nitrogen/generated/ios/swift/HybridWorkoutsModuleSpec.swift +2 -1
- package/nitrogen/generated/ios/swift/HybridWorkoutsModuleSpec_cxx.swift +31 -22
- package/nitrogen/generated/ios/swift/OnChangeCallbackArgs.swift +2 -1
- package/nitrogen/generated/ios/swift/PredicateForSamples.swift +2 -0
- package/nitrogen/generated/ios/swift/PredicateForWorkouts.swift +2 -0
- package/nitrogen/generated/ios/swift/PredicateFromWorkout.swift +3 -3
- package/nitrogen/generated/ios/swift/PredicateWithMetadataKey.swift +2 -1
- package/nitrogen/generated/ios/swift/PredicateWithStartAndEnd.swift +4 -2
- package/nitrogen/generated/ios/swift/QuantitySample.swift +4 -2
- package/nitrogen/generated/ios/swift/QuantitySampleForSaving.swift +2 -1
- package/nitrogen/generated/ios/swift/QueryOptionsWithAnchor.swift +4 -2
- package/nitrogen/generated/ios/swift/QueryOptionsWithAnchorAndUnit.swift +6 -3
- package/nitrogen/generated/ios/swift/QueryOptionsWithSortOrder.swift +2 -1
- package/nitrogen/generated/ios/swift/QueryOptionsWithSortOrderAndUnit.swift +4 -2
- package/nitrogen/generated/ios/swift/QueryStatisticsResponse.swift +18 -9
- package/nitrogen/generated/ios/swift/QueryWorkoutSamplesWithAnchorResponse.swift +7 -7
- package/nitrogen/generated/ios/swift/SampleForSaving.swift +2 -0
- package/nitrogen/generated/ios/swift/SourceRevision.swift +13 -9
- package/nitrogen/generated/ios/swift/StateOfMindSample.swift +6 -3
- package/nitrogen/generated/ios/swift/StatisticsQueryOptions.swift +4 -2
- package/nitrogen/generated/ios/swift/Variant_PredicateWithUUID_PredicateWithUUIDs_PredicateWithMetadataKey_PredicateWithStartAndEnd_PredicateFromWorkout_FilterForSamplesAnd_FilterForSamplesOr.swift +2 -0
- package/nitrogen/generated/ios/swift/Variant_PredicateWithUUID_PredicateWithUUIDs_PredicateWithMetadataKey_PredicateWithStartAndEnd_PredicateFromWorkout_WorkoutActivityTypePredicate_WorkoutDurationPredicate_PredicateForWorkoutsOr_PredicateForWorkoutsAnd.swift +2 -0
- package/nitrogen/generated/ios/swift/Variant_String_Double_Bool_Date.swift +2 -0
- package/nitrogen/generated/ios/swift/WorkoutQueryOptions.swift +4 -61
- package/nitrogen/generated/ios/swift/WorkoutQueryOptionsWithAnchor.swift +6 -62
- package/nitrogen/generated/ios/swift/WorkoutRoute.swift +2 -1
- package/nitrogen/generated/ios/swift/WorkoutSample.swift +12 -123
- package/nitrogen/generated/shared/c++/AuthorizationRequestStatus.hpp +9 -11
- package/nitrogen/generated/shared/c++/AuthorizationStatus.hpp +9 -11
- package/nitrogen/generated/shared/c++/BiologicalSex.hpp +9 -11
- package/nitrogen/generated/shared/c++/BloodType.hpp +9 -11
- package/nitrogen/generated/shared/c++/CategorySample.hpp +14 -16
- package/nitrogen/generated/shared/c++/CategorySampleForSaving.hpp +11 -13
- package/nitrogen/generated/shared/c++/CategorySamplesWithAnchorResponse.hpp +11 -13
- package/nitrogen/generated/shared/c++/CategoryTypeIdentifier.hpp +131 -133
- package/nitrogen/generated/shared/c++/ComparisonPredicateOperator.hpp +26 -13
- package/nitrogen/generated/shared/c++/CorrelationSample.hpp +12 -14
- package/nitrogen/generated/shared/c++/CorrelationTypeIdentifier.hpp +7 -9
- package/nitrogen/generated/shared/c++/DeletedSample.hpp +5 -7
- package/nitrogen/generated/shared/c++/Device.hpp +5 -7
- package/nitrogen/generated/shared/c++/ECGQueryOptionsWithAnchor.hpp +101 -0
- package/nitrogen/generated/shared/c++/ECGQueryOptionsWithSortOrder.hpp +100 -0
- package/nitrogen/generated/shared/c++/ElectrocardiogramClassification.hpp +96 -0
- package/nitrogen/generated/shared/c++/ElectrocardiogramLead.hpp +76 -0
- package/nitrogen/generated/shared/c++/ElectrocardiogramSample.hpp +135 -0
- package/nitrogen/generated/shared/c++/ElectrocardiogramSamplesWithAnchorResponse.hpp +81 -0
- package/nitrogen/generated/shared/c++/ElectrocardiogramSymptomsStatus.hpp +80 -0
- package/nitrogen/generated/shared/c++/ElectrocardiogramVoltage.hpp +76 -0
- package/nitrogen/generated/shared/c++/FilterForSamplesAnd.hpp +9 -11
- package/nitrogen/generated/shared/c++/FilterForSamplesOr.hpp +9 -11
- package/nitrogen/generated/shared/c++/FitzpatrickSkinType.hpp +9 -11
- package/nitrogen/generated/shared/c++/Heartbeat.hpp +4 -6
- package/nitrogen/generated/shared/c++/HeartbeatSeriesSample.hpp +15 -17
- package/nitrogen/generated/shared/c++/HeartbeatSeriesSamplesWithAnchorResponse.hpp +11 -13
- package/nitrogen/generated/shared/c++/HybridCategoryTypeModuleSpec.hpp +2 -2
- package/nitrogen/generated/shared/c++/HybridCharacteristicTypeModuleSpec.hpp +1 -1
- package/nitrogen/generated/shared/c++/HybridCoreModuleSpec.hpp +4 -4
- package/nitrogen/generated/shared/c++/HybridCorrelationTypeModuleSpec.hpp +2 -2
- package/nitrogen/generated/shared/c++/HybridElectrocardiogramModuleSpec.cpp +22 -0
- package/nitrogen/generated/shared/c++/HybridElectrocardiogramModuleSpec.hpp +76 -0
- package/nitrogen/generated/shared/c++/HybridHeartbeatSeriesModuleSpec.hpp +3 -3
- package/nitrogen/generated/shared/c++/HybridQuantityTypeModuleSpec.hpp +3 -3
- package/nitrogen/generated/shared/c++/HybridStateOfMindModuleSpec.hpp +3 -3
- package/nitrogen/generated/shared/c++/HybridWorkoutProxySpec.cpp +6 -4
- package/nitrogen/generated/shared/c++/HybridWorkoutProxySpec.hpp +18 -9
- package/nitrogen/generated/shared/c++/HybridWorkoutsModuleSpec.hpp +4 -4
- package/nitrogen/generated/shared/c++/IdentifierWithUnit.hpp +4 -6
- package/nitrogen/generated/shared/c++/IntervalComponents.hpp +4 -6
- package/nitrogen/generated/shared/c++/LocationForSaving.hpp +4 -6
- package/nitrogen/generated/shared/c++/ObjectTypeIdentifier.hpp +397 -399
- package/nitrogen/generated/shared/c++/OnChangeCallbackArgs.hpp +8 -10
- package/nitrogen/generated/shared/c++/PredicateForWorkoutsAnd.hpp +9 -11
- package/nitrogen/generated/shared/c++/PredicateForWorkoutsOr.hpp +9 -11
- package/nitrogen/generated/shared/c++/PredicateFromWorkout.hpp +6 -8
- package/nitrogen/generated/shared/c++/PredicateWithMetadataKey.hpp +9 -11
- package/nitrogen/generated/shared/c++/PredicateWithMetadataOperator.hpp +11 -13
- package/nitrogen/generated/shared/c++/PredicateWithStartAndEnd.hpp +5 -7
- package/nitrogen/generated/shared/c++/PredicateWithUUID.hpp +4 -6
- package/nitrogen/generated/shared/c++/PredicateWithUUIDs.hpp +5 -7
- package/nitrogen/generated/shared/c++/Quantity.hpp +4 -6
- package/nitrogen/generated/shared/c++/QuantityDateInterval.hpp +4 -6
- package/nitrogen/generated/shared/c++/QuantitySample.hpp +14 -16
- package/nitrogen/generated/shared/c++/QuantitySampleForSaving.hpp +11 -13
- package/nitrogen/generated/shared/c++/QuantitySamplesWithAnchorResponse.hpp +11 -13
- package/nitrogen/generated/shared/c++/QuantityTypeIdentifier.hpp +241 -243
- package/nitrogen/generated/shared/c++/QueryOptionsWithAnchor.hpp +9 -11
- package/nitrogen/generated/shared/c++/QueryOptionsWithAnchorAndUnit.hpp +9 -11
- package/nitrogen/generated/shared/c++/QueryOptionsWithSortOrder.hpp +8 -10
- package/nitrogen/generated/shared/c++/QueryOptionsWithSortOrderAndUnit.hpp +9 -11
- package/nitrogen/generated/shared/c++/QueryStatisticsResponse.hpp +26 -28
- package/nitrogen/generated/shared/c++/QueryWorkoutSamplesWithAnchorResponse.hpp +10 -12
- package/nitrogen/generated/shared/c++/SampleTypeIdentifier.hpp +383 -385
- package/nitrogen/generated/shared/c++/SampleTypeIdentifierWriteable.hpp +373 -375
- package/nitrogen/generated/shared/c++/Source.hpp +4 -6
- package/nitrogen/generated/shared/c++/SourceRevision.hpp +7 -9
- package/nitrogen/generated/shared/c++/StateOfMindAssociation.hpp +10 -12
- package/nitrogen/generated/shared/c++/StateOfMindKind.hpp +14 -13
- package/nitrogen/generated/shared/c++/StateOfMindLabel.hpp +10 -12
- package/nitrogen/generated/shared/c++/StateOfMindSample.hpp +24 -26
- package/nitrogen/generated/shared/c++/StateOfMindValenceClassification.hpp +10 -12
- package/nitrogen/generated/shared/c++/StatisticsOptions.hpp +17 -19
- package/nitrogen/generated/shared/c++/StatisticsQueryOptions.hpp +9 -11
- package/nitrogen/generated/shared/c++/UpdateFrequency.hpp +10 -12
- package/nitrogen/generated/shared/c++/WheelchairUse.hpp +9 -11
- package/nitrogen/generated/shared/c++/WorkoutActivity.hpp +4 -6
- package/nitrogen/generated/shared/c++/WorkoutActivityType.hpp +96 -13
- package/nitrogen/generated/shared/c++/WorkoutActivityTypePredicate.hpp +7 -9
- package/nitrogen/generated/shared/c++/WorkoutConfiguration.hpp +11 -13
- package/nitrogen/generated/shared/c++/WorkoutDurationPredicate.hpp +7 -9
- package/nitrogen/generated/shared/c++/WorkoutEvent.hpp +7 -9
- package/nitrogen/generated/shared/c++/WorkoutEventType.hpp +10 -12
- package/nitrogen/generated/shared/c++/WorkoutPlan.hpp +7 -9
- package/nitrogen/generated/shared/c++/WorkoutQueryOptions.hpp +10 -21
- package/nitrogen/generated/shared/c++/WorkoutQueryOptionsWithAnchor.hpp +11 -21
- package/nitrogen/generated/shared/c++/WorkoutRoute.hpp +9 -11
- package/nitrogen/generated/shared/c++/WorkoutRouteLocation.hpp +4 -6
- package/nitrogen/generated/shared/c++/WorkoutSample.hpp +25 -43
- package/nitrogen/generated/shared/c++/WorkoutSessionLocationType.hpp +10 -12
- package/nitrogen/generated/shared/c++/WorkoutTotals.hpp +4 -6
- package/package.json +11 -11
- package/src/healthkit.ios.ts +9 -0
- package/src/healthkit.ts +16 -0
- package/src/hooks/useMostRecentWorkout.ts +3 -17
- package/src/hooks/useWorkoutById.ts +1 -4
- package/src/modules.ts +6 -0
- package/src/specs/ElectrocardiogramModule.nitro.ts +18 -0
- package/src/specs/WorkoutProxy.nitro.ts +18 -1
- package/src/types/ElectrocardiogramSample.ts +60 -0
- package/src/types/Workouts.ts +0 -8
- package/src/utils/getMostRecentWorkout.ts +1 -6
- package/src/utils/getWorkoutById.ts +1 -6
package/README.md
CHANGED
|
@@ -104,7 +104,7 @@ Some imperative examples:
|
|
|
104
104
|
|
|
105
105
|
useEffect(() => {
|
|
106
106
|
if (hasRequestedAuthorization) {
|
|
107
|
-
const unsubscribe = subscribeToChanges(
|
|
107
|
+
const unsubscribe = subscribeToChanges('HKQuantityTypeIdentifierHeartRate', () => {
|
|
108
108
|
// refetch data as needed
|
|
109
109
|
});
|
|
110
110
|
|
|
@@ -113,7 +113,7 @@ Some imperative examples:
|
|
|
113
113
|
}, [hasRequestedAuthorization]);
|
|
114
114
|
|
|
115
115
|
/* write data */
|
|
116
|
-
await requestAuthorization([], [
|
|
116
|
+
await requestAuthorization([], ['HKQuantityTypeIdentifierInsulinDelivery']); // request write permission for insulin delivery
|
|
117
117
|
|
|
118
118
|
saveQuantitySample(
|
|
119
119
|
'HKQuantityTypeIdentifierInsulinDelivery',
|
package/ios/CoreModule.swift
CHANGED
|
@@ -304,25 +304,17 @@ class CoreModule: HybridCoreModuleSpec {
|
|
|
304
304
|
|
|
305
305
|
let queryId = UUID().uuidString
|
|
306
306
|
|
|
307
|
-
func responder(
|
|
308
|
-
query: HKObserverQuery,
|
|
309
|
-
handler: @escaping HKObserverQueryCompletionHandler,
|
|
310
|
-
error: Error?
|
|
311
|
-
) {
|
|
312
|
-
DispatchQueue.main.async {
|
|
313
|
-
callback(OnChangeCallbackArgs(typeIdentifier: typeIdentifier, errorMessage: error?.localizedDescription))
|
|
314
|
-
handler()
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
|
|
318
307
|
let query = HKObserverQuery(
|
|
319
308
|
sampleType: sampleType,
|
|
320
309
|
predicate: predicate
|
|
321
310
|
) {
|
|
322
|
-
(
|
|
311
|
+
(_: HKObserverQuery, handler: @escaping HKObserverQueryCompletionHandler, error: Error?)
|
|
323
312
|
in
|
|
324
313
|
|
|
325
|
-
|
|
314
|
+
DispatchQueue.main.async {
|
|
315
|
+
callback(OnChangeCallbackArgs(typeIdentifier: typeIdentifier, errorMessage: error?.localizedDescription))
|
|
316
|
+
handler()
|
|
317
|
+
}
|
|
326
318
|
|
|
327
319
|
}
|
|
328
320
|
|
|
@@ -330,8 +322,6 @@ class CoreModule: HybridCoreModuleSpec {
|
|
|
330
322
|
|
|
331
323
|
self._runningQueries.updateValue(query, forKey: queryId)
|
|
332
324
|
|
|
333
|
-
// resolve(queryId)
|
|
334
|
-
|
|
335
325
|
return queryId
|
|
336
326
|
}
|
|
337
327
|
|
|
@@ -14,7 +14,8 @@ class CorrelationTypeModule: HybridCorrelationTypeModuleSpec {
|
|
|
14
14
|
var initializedSamples = Set<HKSample>()
|
|
15
15
|
|
|
16
16
|
for sample in samples {
|
|
17
|
-
|
|
17
|
+
switch sample {
|
|
18
|
+
case .second(let quantitySample):
|
|
18
19
|
let quantityTypeId = HKQuantityTypeIdentifier(rawValue: quantitySample.quantityType.stringValue)
|
|
19
20
|
guard let quantityType = HKSampleType.quantityType(forIdentifier: quantityTypeId) else {
|
|
20
21
|
continue
|
|
@@ -31,7 +32,7 @@ class CorrelationTypeModule: HybridCorrelationTypeModuleSpec {
|
|
|
31
32
|
)
|
|
32
33
|
initializedSamples.insert(hkQuantitySample)
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
case .first(let categorySample):
|
|
35
36
|
let categoryType = try initializeCategoryType(categorySample.categoryType.stringValue)
|
|
36
37
|
|
|
37
38
|
let hkCategorySample = HKCategorySample(
|
|
@@ -45,6 +46,10 @@ class CorrelationTypeModule: HybridCorrelationTypeModuleSpec {
|
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
|
|
49
|
+
if initializedSamples.isEmpty {
|
|
50
|
+
throw RuntimeError.error(withMessage: "[react-native-healthkit] No valid samples to create correlation sample")
|
|
51
|
+
}
|
|
52
|
+
|
|
48
53
|
let correlation = HKCorrelation(
|
|
49
54
|
type: correlationType,
|
|
50
55
|
start: start,
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import HealthKit
|
|
2
|
+
import NitroModules
|
|
3
|
+
|
|
4
|
+
// MARK: - Helpers
|
|
5
|
+
|
|
6
|
+
func getElectrocardiogramByID(
|
|
7
|
+
seriesUUID: UUID
|
|
8
|
+
) async -> HKElectrocardiogram? {
|
|
9
|
+
let predicate = HKQuery.predicateForObject(with: seriesUUID)
|
|
10
|
+
|
|
11
|
+
let samples = try? await withCheckedThrowingContinuation { (continuation: CheckedContinuation<[HKSample], Error>) in
|
|
12
|
+
let query = HKSampleQuery(
|
|
13
|
+
sampleType: HKObjectType.electrocardiogramType(),
|
|
14
|
+
predicate: predicate,
|
|
15
|
+
limit: 1,
|
|
16
|
+
sortDescriptors: nil
|
|
17
|
+
) { _, results, error in
|
|
18
|
+
if let error { continuation.resume(throwing: error); return }
|
|
19
|
+
guard let results else {
|
|
20
|
+
continuation.resume(throwing: RuntimeError.error(withMessage: "Empty response"))
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
continuation.resume(returning: results)
|
|
24
|
+
}
|
|
25
|
+
store.execute(query)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return (samples as? [HKElectrocardiogram])?.first
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@available(iOS 14.0, *)
|
|
32
|
+
class ElectrocardiogramModule: HybridElectrocardiogramModuleSpec {
|
|
33
|
+
|
|
34
|
+
// Query (simple)
|
|
35
|
+
func queryElectrocardiogramSamples(
|
|
36
|
+
options: ECGQueryOptionsWithSortOrder?
|
|
37
|
+
) throws -> Promise<[ElectrocardiogramSample]> {
|
|
38
|
+
let predicate = try createPredicate(filter: options?.filter)
|
|
39
|
+
let queryLimit = getQueryLimit(options?.limit)
|
|
40
|
+
let ascending = options?.ascending ?? false
|
|
41
|
+
let includeVoltages = options?.includeVoltages ?? false
|
|
42
|
+
|
|
43
|
+
return Promise.async {
|
|
44
|
+
try await withCheckedThrowingContinuation { continuation in
|
|
45
|
+
let query = HKSampleQuery(
|
|
46
|
+
sampleType: HKObjectType.electrocardiogramType(),
|
|
47
|
+
predicate: predicate,
|
|
48
|
+
limit: queryLimit,
|
|
49
|
+
sortDescriptors: [
|
|
50
|
+
NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: ascending)
|
|
51
|
+
]
|
|
52
|
+
) { _, samples, error in
|
|
53
|
+
if let error { continuation.resume(throwing: error); return }
|
|
54
|
+
guard let samples = samples as? [HKElectrocardiogram], !samples.isEmpty else {
|
|
55
|
+
continuation.resume(returning: [])
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
Task {
|
|
60
|
+
do {
|
|
61
|
+
var out: [ElectrocardiogramSample] = []
|
|
62
|
+
out.reserveCapacity(samples.count)
|
|
63
|
+
for s in samples {
|
|
64
|
+
let serialized = try await self.serializeECGSample(sample: s, includeVoltages: includeVoltages)
|
|
65
|
+
out.append(serialized)
|
|
66
|
+
}
|
|
67
|
+
continuation.resume(returning: out)
|
|
68
|
+
} catch {
|
|
69
|
+
continuation.resume(throwing: error)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
store.execute(query)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Query (anchored)
|
|
79
|
+
func queryElectrocardiogramSamplesWithAnchor(
|
|
80
|
+
options: ECGQueryOptionsWithAnchor
|
|
81
|
+
) throws -> Promise<ElectrocardiogramSamplesWithAnchorResponse> {
|
|
82
|
+
let predicate = try createPredicate(filter: options.filter)
|
|
83
|
+
let queryLimit = getQueryLimit(options.limit)
|
|
84
|
+
let queryAnchor = try deserializeHKQueryAnchor(base64String: options.anchor)
|
|
85
|
+
let includeVoltages = options.includeVoltages
|
|
86
|
+
|
|
87
|
+
return Promise.async {
|
|
88
|
+
try await withCheckedThrowingContinuation { continuation in
|
|
89
|
+
let query = HKAnchoredObjectQuery(
|
|
90
|
+
type: HKObjectType.electrocardiogramType(),
|
|
91
|
+
predicate: predicate,
|
|
92
|
+
anchor: queryAnchor,
|
|
93
|
+
limit: queryLimit
|
|
94
|
+
) { _, samples, deleted, newAnchor, error in
|
|
95
|
+
if let error { continuation.resume(throwing: error); return }
|
|
96
|
+
|
|
97
|
+
Task {
|
|
98
|
+
do {
|
|
99
|
+
let typed = (samples as? [HKElectrocardiogram]) ?? []
|
|
100
|
+
var out: [ElectrocardiogramSample] = []
|
|
101
|
+
out.reserveCapacity(typed.count)
|
|
102
|
+
for s in typed {
|
|
103
|
+
let serialized = try await self.serializeECGSample(sample: s, includeVoltages: includeVoltages)
|
|
104
|
+
out.append(serialized)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
let response = ElectrocardiogramSamplesWithAnchorResponse(
|
|
108
|
+
samples: out,
|
|
109
|
+
deletedSamples: (deleted ?? []).map { serializeDeletedSample(sample: $0) },
|
|
110
|
+
newAnchor: serializeAnchor(anchor: newAnchor) ?? ""
|
|
111
|
+
)
|
|
112
|
+
continuation.resume(returning: response)
|
|
113
|
+
} catch {
|
|
114
|
+
continuation.resume(throwing: error)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
store.execute(query)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// MARK: - Serialization
|
|
124
|
+
|
|
125
|
+
private func serializeECGSample(sample: HKElectrocardiogram, includeVoltages: Bool) async throws -> ElectrocardiogramSample {
|
|
126
|
+
// Convert quantities
|
|
127
|
+
let bpmUnit = HKUnit.count().unitDivided(by: .minute())
|
|
128
|
+
let hzUnit = HKUnit.hertz()
|
|
129
|
+
let avgHR = sample.averageHeartRate?.doubleValue(for: bpmUnit)
|
|
130
|
+
let freqHz = sample.samplingFrequency?.doubleValue(for: hzUnit)
|
|
131
|
+
|
|
132
|
+
// Optional: waveform
|
|
133
|
+
let voltages: [ElectrocardiogramVoltage]? = includeVoltages
|
|
134
|
+
? try await getECGVoltages(sample: sample)
|
|
135
|
+
: nil
|
|
136
|
+
|
|
137
|
+
// Algorithm version is stored in metadata under HKAppleECGAlgorithmVersion
|
|
138
|
+
let algorithmVersion = sample.metadata?[HKMetadataKeyAlgorithmVersion] as? String
|
|
139
|
+
|
|
140
|
+
return ElectrocardiogramSample(
|
|
141
|
+
uuid: sample.uuid.uuidString,
|
|
142
|
+
device: serializeDevice(hkDevice: sample.device),
|
|
143
|
+
startDate: sample.startDate,
|
|
144
|
+
endDate: sample.endDate,
|
|
145
|
+
classification: serializeClassification(sample.classification),
|
|
146
|
+
symptomsStatus: serializeSymptomsStatus(sample.symptomsStatus),
|
|
147
|
+
averageHeartRateBpm: avgHR,
|
|
148
|
+
samplingFrequencyHz: freqHz,
|
|
149
|
+
numberOfVoltageMeasurements: sample.numberOfVoltageMeasurements,
|
|
150
|
+
algorithmVersion: algorithmVersion,
|
|
151
|
+
voltages: voltages,
|
|
152
|
+
metadata: serializeMetadata(sample.metadata),
|
|
153
|
+
sourceRevision: serializeSourceRevision(sample.sourceRevision)
|
|
154
|
+
)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
private func getECGVoltages(sample: HKElectrocardiogram) async throws -> [ElectrocardiogramVoltage] {
|
|
158
|
+
try await withCheckedThrowingContinuation { continuation in
|
|
159
|
+
var all: [ElectrocardiogramVoltage] = []
|
|
160
|
+
all.reserveCapacity(sample.numberOfVoltageMeasurements)
|
|
161
|
+
|
|
162
|
+
// Stream measurements
|
|
163
|
+
let q = HKElectrocardiogramQuery(sample) { _, result in
|
|
164
|
+
switch result {
|
|
165
|
+
case .error(let error):
|
|
166
|
+
continuation.resume(throwing: error)
|
|
167
|
+
|
|
168
|
+
case .measurement(let m):
|
|
169
|
+
// Lead I-like from Apple Watch
|
|
170
|
+
if let v = m.quantity(for: .appleWatchSimilarToLeadI)?.doubleValue(for: .volt()) {
|
|
171
|
+
let item = ElectrocardiogramVoltage(
|
|
172
|
+
timeSinceSampleStart: m.timeSinceSampleStart,
|
|
173
|
+
voltage: v,
|
|
174
|
+
lead: ElectrocardiogramLead(fromString: "appleWatchSimilarToLeadI")!
|
|
175
|
+
)
|
|
176
|
+
all.append(item)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
case .done:
|
|
180
|
+
continuation.resume(returning: all)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
store.execute(q)
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// MARK: - Enum mappers
|
|
188
|
+
|
|
189
|
+
private func serializeClassification(_ classification: HKElectrocardiogram.Classification) -> ElectrocardiogramClassification {
|
|
190
|
+
switch classification {
|
|
191
|
+
case .notSet: return ElectrocardiogramClassification(fromString: "notSet")!
|
|
192
|
+
case .sinusRhythm: return ElectrocardiogramClassification(fromString: "sinusRhythm")!
|
|
193
|
+
case .atrialFibrillation: return ElectrocardiogramClassification(fromString: "atrialFibrillation")!
|
|
194
|
+
case .inconclusiveLowHeartRate: return ElectrocardiogramClassification(fromString: "inconclusiveLowHeartRate")!
|
|
195
|
+
case .inconclusiveHighHeartRate: return ElectrocardiogramClassification(fromString: "inconclusiveHighHeartRate")!
|
|
196
|
+
case .inconclusivePoorReading: return ElectrocardiogramClassification(fromString: "inconclusivePoorReading")!
|
|
197
|
+
case .inconclusiveOther: return ElectrocardiogramClassification(fromString: "inconclusiveOther")!
|
|
198
|
+
@unknown default: return ElectrocardiogramClassification(fromString: "inconclusiveOther")!
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
private func serializeSymptomsStatus(_ symptoms: HKElectrocardiogram.SymptomsStatus) -> ElectrocardiogramSymptomsStatus {
|
|
203
|
+
switch symptoms {
|
|
204
|
+
case .notSet: return ElectrocardiogramSymptomsStatus(fromString: "notSet")!
|
|
205
|
+
case .none: return ElectrocardiogramSymptomsStatus(fromString: "none")!
|
|
206
|
+
case .present: return ElectrocardiogramSymptomsStatus(fromString: "present")!
|
|
207
|
+
@unknown default: return ElectrocardiogramSymptomsStatus(fromString: "notSet")!
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
@@ -49,6 +49,75 @@ func queryQuantitySamplesInternal(
|
|
|
49
49
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
func emptyStatisticsResponse(from: Date, to: Date) -> QueryStatisticsResponse {
|
|
53
|
+
var response = QueryStatisticsResponse()
|
|
54
|
+
|
|
55
|
+
response.startDate = from
|
|
56
|
+
response.endDate = to
|
|
57
|
+
|
|
58
|
+
return response
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
func serializeStatistics(gottenStats: HKStatistics, unit: HKUnit) -> QueryStatisticsResponse {
|
|
62
|
+
var response = QueryStatisticsResponse()
|
|
63
|
+
|
|
64
|
+
response.startDate = gottenStats.startDate
|
|
65
|
+
response.endDate = gottenStats.endDate
|
|
66
|
+
|
|
67
|
+
if let averageQuantity = gottenStats.averageQuantity() {
|
|
68
|
+
response.averageQuantity = Quantity(
|
|
69
|
+
unit: unit.unitString,
|
|
70
|
+
quantity: averageQuantity.doubleValue(for: unit)
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
if let maximumQuantity = gottenStats.maximumQuantity() {
|
|
74
|
+
response.maximumQuantity = Quantity(
|
|
75
|
+
unit: unit.unitString,
|
|
76
|
+
quantity: maximumQuantity.doubleValue(for: unit)
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
if let minimumQuantity = gottenStats.minimumQuantity() {
|
|
80
|
+
response.minimumQuantity = Quantity(
|
|
81
|
+
unit: unit.unitString,
|
|
82
|
+
quantity: minimumQuantity.doubleValue(for: unit)
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
if let sumQuantity = gottenStats.sumQuantity() {
|
|
86
|
+
response.sumQuantity = Quantity(
|
|
87
|
+
unit: unit.unitString,
|
|
88
|
+
quantity: sumQuantity.doubleValue(for: unit)
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if #available(iOS 12, *) {
|
|
93
|
+
if let mostRecent = gottenStats.mostRecentQuantity() {
|
|
94
|
+
response.mostRecentQuantity = Quantity(
|
|
95
|
+
unit: unit.unitString,
|
|
96
|
+
quantity: mostRecent.doubleValue(for: unit)
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if let mostRecentDateInterval = gottenStats.mostRecentQuantityDateInterval() {
|
|
101
|
+
response.mostRecentQuantityDateInterval = QuantityDateInterval(
|
|
102
|
+
from: mostRecentDateInterval.start,
|
|
103
|
+
to: mostRecentDateInterval.end
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if #available(iOS 13, *) {
|
|
109
|
+
if let duration = gottenStats.duration() {
|
|
110
|
+
let durationUnit = HKUnit.second()
|
|
111
|
+
response.duration = Quantity(
|
|
112
|
+
unit: durationUnit.unitString,
|
|
113
|
+
quantity: duration.doubleValue(for: durationUnit)
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return response
|
|
119
|
+
}
|
|
120
|
+
|
|
52
121
|
func saveQuantitySampleInternal(
|
|
53
122
|
typeIdentifier: HKQuantityType,
|
|
54
123
|
unitString: String,
|
|
@@ -140,6 +209,26 @@ func buildStatisticsOptions(statistics: [StatisticsOptions]) -> HKStatisticsOpti
|
|
|
140
209
|
return opts
|
|
141
210
|
}
|
|
142
211
|
|
|
212
|
+
/// Handles HealthKit's `errorNoData` by resuming the continuation with a fallback value if provided,
|
|
213
|
+
/// otherwise resumes with `nil` for Optional result types. For other errors, resumes by throwing.
|
|
214
|
+
/// - Parameters:
|
|
215
|
+
/// - error: The error returned by HealthKit.
|
|
216
|
+
/// - continuation: The continuation to resume.
|
|
217
|
+
/// - noDataFallback: Optional closure producing a fallback value to use when the error is `errorNoData`.
|
|
218
|
+
func handleHKNoDataOrThrow<T>(
|
|
219
|
+
error: Error,
|
|
220
|
+
continuation: CheckedContinuation<T, Error>,
|
|
221
|
+
noDataFallback: (() -> T)
|
|
222
|
+
) {
|
|
223
|
+
let nsError = error as NSError
|
|
224
|
+
if nsError.domain == HKError.errorDomain,
|
|
225
|
+
nsError.code == HKError.Code.errorNoData.rawValue {
|
|
226
|
+
continuation.resume(returning: noDataFallback())
|
|
227
|
+
} else {
|
|
228
|
+
continuation.resume(throwing: error)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
143
232
|
class QuantityTypeModule: HybridQuantityTypeModuleSpec {
|
|
144
233
|
func deleteQuantitySamples(identifier: QuantityTypeIdentifier, filter: FilterForSamples) throws -> Promise<Bool> {
|
|
145
234
|
let sampleType = try initializeQuantityType(identifier.stringValue)
|
|
@@ -180,71 +269,17 @@ class QuantityTypeModule: HybridQuantityTypeModuleSpec {
|
|
|
180
269
|
) { (_, stats: HKStatistics?, error: Error?) in
|
|
181
270
|
DispatchQueue.main.async {
|
|
182
271
|
if let error = error {
|
|
183
|
-
|
|
184
|
-
|
|
272
|
+
return handleHKNoDataOrThrow(error: error, continuation: continuation) {
|
|
273
|
+
QueryStatisticsResponse()
|
|
274
|
+
}
|
|
185
275
|
}
|
|
186
276
|
|
|
187
277
|
guard let gottenStats = stats else {
|
|
188
278
|
let emptyResponse = QueryStatisticsResponse()
|
|
189
|
-
continuation.resume(returning: emptyResponse)
|
|
190
|
-
return
|
|
279
|
+
return continuation.resume(returning: emptyResponse)
|
|
191
280
|
}
|
|
192
281
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
response.startDate = gottenStats.startDate
|
|
196
|
-
response.endDate = gottenStats.endDate
|
|
197
|
-
|
|
198
|
-
if let averageQuantity = gottenStats.averageQuantity() {
|
|
199
|
-
response.averageQuantity = Quantity(
|
|
200
|
-
unit: unit.unitString,
|
|
201
|
-
quantity: averageQuantity.doubleValue(for: unit)
|
|
202
|
-
)
|
|
203
|
-
}
|
|
204
|
-
if let maximumQuantity = gottenStats.maximumQuantity() {
|
|
205
|
-
response.maximumQuantity = Quantity(
|
|
206
|
-
unit: unit.unitString,
|
|
207
|
-
quantity: maximumQuantity.doubleValue(for: unit)
|
|
208
|
-
)
|
|
209
|
-
}
|
|
210
|
-
if let minimumQuantity = gottenStats.minimumQuantity() {
|
|
211
|
-
response.minimumQuantity = Quantity(
|
|
212
|
-
unit: unit.unitString,
|
|
213
|
-
quantity: minimumQuantity.doubleValue(for: unit)
|
|
214
|
-
)
|
|
215
|
-
}
|
|
216
|
-
if let sumQuantity = gottenStats.sumQuantity() {
|
|
217
|
-
response.sumQuantity = Quantity(
|
|
218
|
-
unit: unit.unitString,
|
|
219
|
-
quantity: sumQuantity.doubleValue(for: unit)
|
|
220
|
-
)
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
if #available(iOS 12, *) {
|
|
224
|
-
if let mostRecent = gottenStats.mostRecentQuantity() {
|
|
225
|
-
response.mostRecentQuantity = Quantity(
|
|
226
|
-
unit: unit.unitString,
|
|
227
|
-
quantity: mostRecent.doubleValue(for: unit)
|
|
228
|
-
)
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
if let mostRecentDateInterval = gottenStats.mostRecentQuantityDateInterval() {
|
|
232
|
-
response.mostRecentQuantityDateInterval = QuantityDateInterval(
|
|
233
|
-
from: mostRecentDateInterval.start,
|
|
234
|
-
to: mostRecentDateInterval.end
|
|
235
|
-
)
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
if #available(iOS 13, *) {
|
|
240
|
-
if let duration = gottenStats.duration() {
|
|
241
|
-
let durationUnit = HKUnit.second()
|
|
242
|
-
response.duration = Quantity(
|
|
243
|
-
unit: durationUnit.unitString,
|
|
244
|
-
quantity: duration.doubleValue(for: durationUnit)
|
|
245
|
-
)
|
|
246
|
-
}
|
|
247
|
-
}
|
|
282
|
+
let response = serializeStatistics(gottenStats: gottenStats, unit: unit)
|
|
248
283
|
|
|
249
284
|
continuation.resume(returning: response)
|
|
250
285
|
}
|
|
@@ -300,8 +335,9 @@ class QuantityTypeModule: HybridQuantityTypeModuleSpec {
|
|
|
300
335
|
|
|
301
336
|
query.initialResultsHandler = { (_, results: HKStatisticsCollection?, error: Error?) in
|
|
302
337
|
if let error = error {
|
|
303
|
-
|
|
304
|
-
|
|
338
|
+
return handleHKNoDataOrThrow(error: error, continuation: continuation) {
|
|
339
|
+
[]
|
|
340
|
+
}
|
|
305
341
|
}
|
|
306
342
|
|
|
307
343
|
guard let statistics = results else {
|
|
@@ -326,61 +362,7 @@ class QuantityTypeModule: HybridQuantityTypeModuleSpec {
|
|
|
326
362
|
}
|
|
327
363
|
|
|
328
364
|
statistics.enumerateStatistics(from: enumerateFrom, to: enumerateTo) { stats, _ in
|
|
329
|
-
var response =
|
|
330
|
-
|
|
331
|
-
response.startDate = stats.startDate
|
|
332
|
-
response.endDate = stats.endDate
|
|
333
|
-
|
|
334
|
-
if let averageQuantity = stats.averageQuantity() {
|
|
335
|
-
response.averageQuantity = Quantity(
|
|
336
|
-
unit: unit.unitString,
|
|
337
|
-
quantity: averageQuantity.doubleValue(for: unit)
|
|
338
|
-
)
|
|
339
|
-
}
|
|
340
|
-
if let maximumQuantity = stats.maximumQuantity() {
|
|
341
|
-
response.maximumQuantity = Quantity(
|
|
342
|
-
unit: unit.unitString,
|
|
343
|
-
quantity: maximumQuantity.doubleValue(for: unit)
|
|
344
|
-
)
|
|
345
|
-
}
|
|
346
|
-
if let minimumQuantity = stats.minimumQuantity() {
|
|
347
|
-
response.minimumQuantity = Quantity(
|
|
348
|
-
unit: unit.unitString,
|
|
349
|
-
quantity: minimumQuantity.doubleValue(for: unit)
|
|
350
|
-
)
|
|
351
|
-
}
|
|
352
|
-
if let sumQuantity = stats.sumQuantity() {
|
|
353
|
-
response.sumQuantity = Quantity(
|
|
354
|
-
unit: unit.unitString,
|
|
355
|
-
quantity: sumQuantity.doubleValue(for: unit)
|
|
356
|
-
)
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
if #available(iOS 12, *) {
|
|
360
|
-
if let mostRecent = stats.mostRecentQuantity() {
|
|
361
|
-
response.mostRecentQuantity = Quantity(
|
|
362
|
-
unit: unit.unitString,
|
|
363
|
-
quantity: mostRecent.doubleValue(for: unit)
|
|
364
|
-
)
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
if let mostRecentDateInterval = stats.mostRecentQuantityDateInterval() {
|
|
368
|
-
response.mostRecentQuantityDateInterval = QuantityDateInterval(
|
|
369
|
-
from: mostRecentDateInterval.start,
|
|
370
|
-
to: mostRecentDateInterval.end
|
|
371
|
-
)
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
if #available(iOS 13, *) {
|
|
376
|
-
if let duration = stats.duration() {
|
|
377
|
-
let durationUnit = HKUnit.second()
|
|
378
|
-
response.duration = Quantity(
|
|
379
|
-
unit: durationUnit.unitString,
|
|
380
|
-
quantity: duration.doubleValue(for: durationUnit)
|
|
381
|
-
)
|
|
382
|
-
}
|
|
383
|
-
}
|
|
365
|
+
var response = serializeStatistics(gottenStats: stats, unit: unit)
|
|
384
366
|
|
|
385
367
|
responseArray.append(response)
|
|
386
368
|
}
|
|
@@ -419,18 +401,25 @@ class QuantityTypeModule: HybridQuantityTypeModuleSpec {
|
|
|
419
401
|
error: Error?
|
|
420
402
|
) in
|
|
421
403
|
if let error = error {
|
|
422
|
-
|
|
423
|
-
|
|
404
|
+
return handleHKNoDataOrThrow(error: error, continuation: continuation) {
|
|
405
|
+
QuantitySamplesWithAnchorResponse(
|
|
406
|
+
samples: [],
|
|
407
|
+
deletedSamples: [],
|
|
408
|
+
newAnchor: ""
|
|
409
|
+
)
|
|
410
|
+
}
|
|
424
411
|
}
|
|
425
412
|
|
|
413
|
+
let deletedSamples = deletedSamples?.map { serializeDeletedSample(sample: $0) } ?? []
|
|
414
|
+
let newAnchor = serializeAnchor(anchor: newAnchor) ?? ""
|
|
415
|
+
|
|
426
416
|
guard let samples = samples else {
|
|
427
417
|
let response = QuantitySamplesWithAnchorResponse(
|
|
428
418
|
samples: [],
|
|
429
|
-
deletedSamples: deletedSamples
|
|
430
|
-
newAnchor:
|
|
419
|
+
deletedSamples: deletedSamples,
|
|
420
|
+
newAnchor: newAnchor
|
|
431
421
|
)
|
|
432
|
-
continuation.resume(returning: response)
|
|
433
|
-
return
|
|
422
|
+
return continuation.resume(returning: response)
|
|
434
423
|
}
|
|
435
424
|
|
|
436
425
|
let quantitySamples = samples.compactMap { sample in
|
|
@@ -449,8 +438,8 @@ class QuantityTypeModule: HybridQuantityTypeModuleSpec {
|
|
|
449
438
|
|
|
450
439
|
let response = QuantitySamplesWithAnchorResponse(
|
|
451
440
|
samples: quantitySamples,
|
|
452
|
-
deletedSamples: deletedSamples
|
|
453
|
-
newAnchor:
|
|
441
|
+
deletedSamples: deletedSamples,
|
|
442
|
+
newAnchor: newAnchor,
|
|
454
443
|
)
|
|
455
444
|
|
|
456
445
|
continuation.resume(returning: response)
|