@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/CoreModule.swift
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import HealthKit
|
|
2
2
|
import NitroModules
|
|
3
|
+
|
|
3
4
|
//
|
|
4
5
|
// Core.swift
|
|
5
6
|
// Pods
|
|
@@ -11,368 +12,411 @@ var store = HKHealthStore.init()
|
|
|
11
12
|
|
|
12
13
|
// Thread-safe cache with concurrent read/exclusive write access
|
|
13
14
|
private let quantityTypeCacheQueue = DispatchQueue(
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
label: "com.kingstinct.healthkit.cache",
|
|
16
|
+
attributes: .concurrent
|
|
16
17
|
)
|
|
17
18
|
private var quantityTypeUnitCache = [HKQuantityType: HKUnit]()
|
|
18
19
|
|
|
19
20
|
func getUnitToUse(unitOverride: String?, quantityType: HKQuantityType) async throws -> HKUnit {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
if !quantityType.is(compatibleWith: unit) {
|
|
24
|
-
throw RuntimeError.error(withMessage: "[react-native-healthkit] Unit \(unitOverride) is incompatible with \(quantityType.identifier)")
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return unit
|
|
28
|
-
}
|
|
21
|
+
if let unitOverride = unitOverride {
|
|
22
|
+
let unit = HKUnit(from: unitOverride)
|
|
29
23
|
|
|
30
|
-
if
|
|
31
|
-
|
|
24
|
+
if !quantityType.is(compatibleWith: unit) {
|
|
25
|
+
throw runtimeErrorWithPrefix(
|
|
26
|
+
"Unit \(unitOverride) is incompatible with quantityType \(quantityType.identifier)")
|
|
32
27
|
}
|
|
33
28
|
|
|
34
|
-
|
|
35
|
-
}
|
|
29
|
+
return unit
|
|
30
|
+
}
|
|
36
31
|
|
|
37
|
-
|
|
32
|
+
if let preferredUnit = try await getPreferredUnitsInternal(quantityTypes: [quantityType]).first?
|
|
33
|
+
.value {
|
|
34
|
+
return preferredUnit
|
|
35
|
+
}
|
|
38
36
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
let itemsInCache = quantityTypeCacheQueue.sync {
|
|
42
|
-
return quantityTypeUnitCache.filter {
|
|
43
|
-
quantityTypes.contains($0.key)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
if itemsInCache.count == quantityTypes.count {
|
|
47
|
-
return itemsInCache
|
|
48
|
-
}
|
|
49
|
-
}
|
|
37
|
+
throw runtimeErrorWithPrefix("getUnitToUse: Must specify a unit for \(quantityType.identifier)")
|
|
38
|
+
}
|
|
50
39
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
(typePerUnits: [HKQuantityType: HKUnit], error: Error?) in
|
|
54
|
-
if let error = error {
|
|
55
|
-
return continuation.resume(throwing: error)
|
|
56
|
-
}
|
|
40
|
+
func getPreferredUnitsInternal(quantityTypes: [HKQuantityType], forceUpdate: Bool? = false)
|
|
41
|
+
async throws -> [HKQuantityType: HKUnit] {
|
|
57
42
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
quantityTypeUnitCache.updateValue(unit, forKey: type)
|
|
62
|
-
}
|
|
63
|
-
}
|
|
43
|
+
if quantityTypes.count == 0 {
|
|
44
|
+
return [:]
|
|
45
|
+
}
|
|
64
46
|
|
|
65
|
-
|
|
47
|
+
if forceUpdate != true {
|
|
48
|
+
// Thread-safe read: concurrent reads are allowed
|
|
49
|
+
let itemsInCache = quantityTypeCacheQueue.sync {
|
|
50
|
+
return quantityTypeUnitCache.filter {
|
|
51
|
+
quantityTypes.contains($0.key)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if itemsInCache.count == quantityTypes.count {
|
|
55
|
+
return itemsInCache
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return try await withCheckedThrowingContinuation { continuation in
|
|
60
|
+
store.preferredUnits(for: Set(quantityTypes)) {
|
|
61
|
+
(typePerUnits: [HKQuantityType: HKUnit], error: Error?) in
|
|
62
|
+
if let error = error {
|
|
63
|
+
return continuation.resume(throwing: error)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Thread-safe write: barrier ensures exclusive access
|
|
67
|
+
quantityTypeCacheQueue.sync(flags: .barrier) {
|
|
68
|
+
typePerUnits.forEach { (type: HKQuantityType, unit: HKUnit) in
|
|
69
|
+
quantityTypeUnitCache.updateValue(unit, forKey: type)
|
|
66
70
|
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return continuation.resume(returning: typePerUnits)
|
|
67
74
|
}
|
|
75
|
+
}
|
|
68
76
|
}
|
|
69
77
|
|
|
70
78
|
class CoreModule: HybridCoreModuleSpec {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
for objectTypeIdentifier in objectTypeIdentifiers {
|
|
75
|
-
dict[objectTypeIdentifier.stringValue] = isObjectTypeAvailable(objectTypeIdentifier: objectTypeIdentifier)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return dict
|
|
79
|
-
}
|
|
79
|
+
func currentAppSource() -> any HybridSourceProxySpec {
|
|
80
|
+
return SourceProxy(source: HKSource.default())
|
|
81
|
+
}
|
|
80
82
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
83
|
+
func areObjectTypesAvailable(objectTypeIdentifiers: [ObjectTypeIdentifier]) -> [String: Bool] {
|
|
84
|
+
var dict = [String: Bool]()
|
|
84
85
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return true
|
|
89
|
-
} catch {
|
|
90
|
-
return false
|
|
91
|
-
}
|
|
86
|
+
for objectTypeIdentifier in objectTypeIdentifiers {
|
|
87
|
+
dict[objectTypeIdentifier.stringValue] = isObjectTypeAvailable(
|
|
88
|
+
objectTypeIdentifier: objectTypeIdentifier)
|
|
92
89
|
}
|
|
93
90
|
|
|
94
|
-
|
|
95
|
-
|
|
91
|
+
return dict
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
func areObjectTypesAvailableAsync(objectTypeIdentifiers: [ObjectTypeIdentifier]) -> Promise<
|
|
95
|
+
[String: Bool]
|
|
96
|
+
> {
|
|
97
|
+
return Promise.resolved(
|
|
98
|
+
withResult: areObjectTypesAvailable(objectTypeIdentifiers: objectTypeIdentifiers))
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
func isObjectTypeAvailable(objectTypeIdentifier: ObjectTypeIdentifier) -> Bool {
|
|
102
|
+
do {
|
|
103
|
+
_ = try objectTypeFrom(objectTypeIdentifier: objectTypeIdentifier)
|
|
104
|
+
return true
|
|
105
|
+
} catch {
|
|
106
|
+
return false
|
|
96
107
|
}
|
|
108
|
+
}
|
|
97
109
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
110
|
+
func isObjectTypeAvailableAsync(objectTypeIdentifier: ObjectTypeIdentifier) -> Promise<Bool> {
|
|
111
|
+
return Promise.resolved(
|
|
112
|
+
withResult: isObjectTypeAvailable(objectTypeIdentifier: objectTypeIdentifier))
|
|
113
|
+
}
|
|
102
114
|
|
|
103
|
-
|
|
115
|
+
func authorizationStatusFor(
|
|
116
|
+
type: ObjectTypeIdentifier
|
|
117
|
+
) throws -> AuthorizationStatus {
|
|
118
|
+
let objectType = try objectTypeFrom(objectTypeIdentifier: type)
|
|
104
119
|
|
|
105
|
-
|
|
106
|
-
return authStatus
|
|
107
|
-
}
|
|
120
|
+
let authStatus = store.authorizationStatus(for: objectType)
|
|
108
121
|
|
|
109
|
-
|
|
122
|
+
if let authStatus = AuthorizationStatus(rawValue: Int32(authStatus.rawValue)) {
|
|
123
|
+
return authStatus
|
|
110
124
|
}
|
|
111
125
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
126
|
+
throw runtimeErrorWithPrefix(
|
|
127
|
+
"Got unrecognized AuthorizationStatus rawValue: \(authStatus.rawValue)")
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
func getRequestStatusForAuthorization(toCheck: AuthDataTypes) -> Promise<
|
|
131
|
+
AuthorizationRequestStatus
|
|
132
|
+
> {
|
|
133
|
+
return Promise.async {
|
|
134
|
+
let toShare = sampleTypesFromArray(typeIdentifiersWriteable: toCheck.toShare ?? [])
|
|
135
|
+
let toRead = objectTypesFromArray(typeIdentifiers: toCheck.toRead ?? [])
|
|
136
|
+
|
|
137
|
+
return try await withCheckedThrowingContinuation { continuation in
|
|
138
|
+
if toShare.isEmpty && toRead.isEmpty {
|
|
139
|
+
warnWithPrefix("Both toRead and toShare are empty, returning 'unnecessary' status")
|
|
140
|
+
return continuation.resume(
|
|
141
|
+
returning: .unnecessary
|
|
142
|
+
)
|
|
134
143
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
} else {
|
|
147
|
-
continuation.resume(returning: status)
|
|
148
|
-
}
|
|
149
|
-
}
|
|
144
|
+
return store.getRequestStatusForAuthorization(toShare: toShare, read: toRead) {
|
|
145
|
+
status, error in
|
|
146
|
+
if let error = error {
|
|
147
|
+
continuation.resume(throwing: error)
|
|
148
|
+
} else {
|
|
149
|
+
if let authStatus = AuthorizationRequestStatus(rawValue: Int32(status.rawValue)) {
|
|
150
|
+
continuation.resume(returning: authStatus)
|
|
151
|
+
} else {
|
|
152
|
+
continuation.resume(
|
|
153
|
+
throwing: runtimeErrorWithPrefix(
|
|
154
|
+
"Unrecognized authStatus returned: \(status.rawValue)"))
|
|
150
155
|
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
func querySources(identifier: SampleTypeIdentifier) throws -> Promise<[HybridSourceProxySpec]> {
|
|
155
|
-
let sampleType = try sampleTypeFrom(sampleTypeIdentifier: identifier)
|
|
156
|
-
|
|
157
|
-
return Promise.async {
|
|
158
|
-
try await withCheckedThrowingContinuation { continuation in
|
|
159
|
-
let query = HKSourceQuery(
|
|
160
|
-
sampleType: sampleType,
|
|
161
|
-
samplePredicate: nil
|
|
162
|
-
) { (_: HKSourceQuery, sources: Set<HKSource>?, error: Error?) in
|
|
163
|
-
if let error = error {
|
|
164
|
-
continuation.resume(throwing: error)
|
|
165
|
-
return
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
guard let sources = sources else {
|
|
169
|
-
return continuation.resume(throwing: RuntimeError.error(withMessage: "[react-native-healthkit] Empty response for sample type \(identifier.stringValue)"))
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
let serializedSources = sources.map { source -> SourceProxy in
|
|
173
156
|
|
|
174
|
-
|
|
175
|
-
source: source
|
|
176
|
-
)
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
continuation.resume(returning: serializedSources)
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
store.execute(query)
|
|
183
|
-
}
|
|
157
|
+
}
|
|
184
158
|
}
|
|
159
|
+
}
|
|
185
160
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
} else {
|
|
204
|
-
throw RuntimeError.error(withMessage: "Invalid update frequency value: \(updateFrequency)")
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
func requestAuthorization(toRequest: AuthDataTypes) -> Promise<Bool> {
|
|
164
|
+
return Promise.async {
|
|
165
|
+
let share = sampleTypesFromArray(typeIdentifiersWriteable: toRequest.toShare ?? [])
|
|
166
|
+
let toRead = objectTypesFromArray(typeIdentifiers: toRequest.toRead ?? [])
|
|
167
|
+
|
|
168
|
+
return try await withCheckedThrowingContinuation { continuation in
|
|
169
|
+
store.requestAuthorization(toShare: share, read: toRead) { status, error in
|
|
170
|
+
if let error = error {
|
|
171
|
+
continuation.resume(throwing: error)
|
|
172
|
+
} else {
|
|
173
|
+
continuation.resume(returning: status)
|
|
174
|
+
}
|
|
205
175
|
}
|
|
176
|
+
}
|
|
206
177
|
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
func querySources(identifier: SampleTypeIdentifier, filter: FilterForSamples?) -> Promise<
|
|
181
|
+
[HybridSourceProxySpec]
|
|
182
|
+
> {
|
|
183
|
+
return Promise.async {
|
|
184
|
+
let sampleType = try sampleTypeFrom(sampleTypeIdentifier: identifier)
|
|
185
|
+
let predicate = createPredicateForSamples(filter)
|
|
186
|
+
|
|
187
|
+
return try await withCheckedThrowingContinuation { continuation in
|
|
188
|
+
let query = HKSourceQuery(
|
|
189
|
+
sampleType: sampleType,
|
|
190
|
+
samplePredicate: predicate
|
|
191
|
+
) { (_: HKSourceQuery, sources: Set<HKSource>?, error: Error?) in
|
|
192
|
+
if let error = error {
|
|
193
|
+
continuation.resume(throwing: error)
|
|
194
|
+
return
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
guard let sources = sources else {
|
|
198
|
+
return continuation.resume(
|
|
199
|
+
throwing: runtimeErrorWithPrefix(
|
|
200
|
+
"Empty response for sample type \(identifier.stringValue)"))
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
let serializedSources = sources.map { source -> SourceProxy in
|
|
204
|
+
|
|
205
|
+
return SourceProxy(
|
|
206
|
+
source: source
|
|
207
|
+
)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
continuation.resume(returning: serializedSources)
|
|
211
|
+
}
|
|
207
212
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
213
|
+
store.execute(query)
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
func enableBackgroundDelivery(
|
|
219
|
+
typeIdentifier: ObjectTypeIdentifier, updateFrequency: UpdateFrequency
|
|
220
|
+
) -> Promise<Bool> {
|
|
221
|
+
return Promise.async {
|
|
222
|
+
if let frequency = HKUpdateFrequency(rawValue: Int(updateFrequency.rawValue)) {
|
|
223
|
+
let type = try objectTypeFrom(objectTypeIdentifier: typeIdentifier)
|
|
224
|
+
return try await withCheckedThrowingContinuation { continuation in
|
|
225
|
+
store.enableBackgroundDelivery(
|
|
226
|
+
for: type,
|
|
227
|
+
frequency: frequency
|
|
228
|
+
) { (success, error) in
|
|
229
|
+
if let err = error {
|
|
230
|
+
return continuation.resume(throwing: err)
|
|
222
231
|
}
|
|
232
|
+
return continuation.resume(returning: success)
|
|
233
|
+
}
|
|
223
234
|
}
|
|
235
|
+
} else {
|
|
236
|
+
throw runtimeErrorWithPrefix("Invalid update frequency rawValue: \(updateFrequency)")
|
|
237
|
+
}
|
|
224
238
|
}
|
|
225
239
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
func disableBackgroundDelivery(
|
|
243
|
+
typeIdentifier: ObjectTypeIdentifier
|
|
244
|
+
) -> Promise<Bool> {
|
|
245
|
+
return Promise.async {
|
|
246
|
+
let type = try objectTypeFrom(objectTypeIdentifier: typeIdentifier)
|
|
247
|
+
return try await withCheckedThrowingContinuation { continuation in
|
|
248
|
+
store.disableBackgroundDelivery(
|
|
249
|
+
for: type
|
|
250
|
+
) { (success, error) in
|
|
251
|
+
if let err = error {
|
|
252
|
+
return continuation.resume(throwing: err)
|
|
253
|
+
}
|
|
254
|
+
return continuation.resume(returning: success)
|
|
236
255
|
}
|
|
256
|
+
}
|
|
237
257
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
func disableAllBackgroundDelivery() -> Promise<Bool> {
|
|
261
|
+
return Promise.async {
|
|
262
|
+
try await withCheckedThrowingContinuation { continuation in
|
|
263
|
+
store.disableAllBackgroundDelivery(completion: { (success, error) in
|
|
264
|
+
guard let err = error else {
|
|
265
|
+
return continuation.resume(returning: success)
|
|
266
|
+
}
|
|
267
|
+
return continuation.resume(throwing: err)
|
|
268
|
+
})
|
|
269
|
+
}
|
|
243
270
|
}
|
|
271
|
+
}
|
|
244
272
|
|
|
245
|
-
|
|
246
|
-
|
|
273
|
+
func unsubscribeQueryAsync(queryId: String) -> Promise<Bool> {
|
|
274
|
+
return Promise.async {
|
|
275
|
+
return try self.unsubscribeQuery(queryId: queryId)
|
|
247
276
|
}
|
|
277
|
+
}
|
|
248
278
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
279
|
+
func isHealthDataAvailableAsync() -> Promise<Bool> {
|
|
280
|
+
return Promise.resolved(withResult: HKHealthStore.isHealthDataAvailable())
|
|
281
|
+
}
|
|
252
282
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
283
|
+
func isProtectedDataAvailableAsync() -> Promise<Bool> {
|
|
284
|
+
return Promise.resolved(withResult: UIApplication.shared.isProtectedDataAvailable)
|
|
285
|
+
}
|
|
256
286
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
287
|
+
func isHealthDataAvailable() -> Bool {
|
|
288
|
+
return HKHealthStore.isHealthDataAvailable()
|
|
289
|
+
}
|
|
260
290
|
|
|
261
|
-
|
|
262
|
-
|
|
291
|
+
func isProtectedDataAvailable() -> Bool {
|
|
292
|
+
return UIApplication.shared.isProtectedDataAvailable
|
|
293
|
+
}
|
|
263
294
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
295
|
+
func getPreferredUnits(identifiers: [QuantityTypeIdentifier], forceUpdate: Bool?) -> Promise<
|
|
296
|
+
[IdentifierWithUnit]
|
|
297
|
+
> {
|
|
298
|
+
return Promise.async {
|
|
299
|
+
let quantityTypes = identifiers.compactMap { identifier in
|
|
300
|
+
do {
|
|
301
|
+
let quantityType = try initializeQuantityType(identifier.stringValue)
|
|
267
302
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
303
|
+
return quantityType
|
|
304
|
+
} catch {
|
|
305
|
+
warnWithPrefix("getPreferredUnits: \(error.localizedDescription)")
|
|
306
|
+
return nil
|
|
307
|
+
}
|
|
308
|
+
}
|
|
274
309
|
|
|
275
|
-
|
|
310
|
+
let typePerUnits = try await getPreferredUnitsInternal(
|
|
311
|
+
quantityTypes: quantityTypes, forceUpdate: forceUpdate)
|
|
276
312
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
313
|
+
let dic = typePerUnits.map { typePerUnit in
|
|
314
|
+
return IdentifierWithUnit(
|
|
315
|
+
typeIdentifier: typePerUnit.key.identifier,
|
|
316
|
+
unit: typePerUnit.value.unitString
|
|
317
|
+
)
|
|
318
|
+
}
|
|
283
319
|
|
|
284
|
-
|
|
285
|
-
}
|
|
320
|
+
return dic
|
|
286
321
|
}
|
|
322
|
+
}
|
|
287
323
|
|
|
288
|
-
|
|
324
|
+
var _runningQueries: [String: HKQuery] = [:]
|
|
289
325
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
326
|
+
func deleteObjects(objectTypeIdentifier: ObjectTypeIdentifier, filter: FilterForSamples)
|
|
327
|
+
-> Promise<Double> {
|
|
328
|
+
return Promise.async {
|
|
329
|
+
if let predicate = createPredicateForSamples(filter) {
|
|
293
330
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
}
|
|
302
|
-
}
|
|
331
|
+
let of = try objectTypeFrom(objectTypeIdentifier: objectTypeIdentifier)
|
|
332
|
+
return try await withCheckedThrowingContinuation { continuation in
|
|
333
|
+
store.deleteObjects(of: of, predicate: predicate) { (_, count, error) in
|
|
334
|
+
if let error = error {
|
|
335
|
+
continuation.resume(throwing: error)
|
|
336
|
+
} else {
|
|
337
|
+
continuation.resume(returning: Double(count))
|
|
303
338
|
}
|
|
339
|
+
}
|
|
304
340
|
}
|
|
341
|
+
}
|
|
342
|
+
throw runtimeErrorWithPrefix("Unable to create predicate for deleting objects")
|
|
305
343
|
}
|
|
306
344
|
|
|
307
|
-
|
|
308
|
-
typeIdentifier: SampleTypeIdentifier,
|
|
309
|
-
callback: @escaping (OnChangeCallbackArgs) -> Void
|
|
310
|
-
) throws -> String {
|
|
311
|
-
let sampleType = try sampleTypeFrom(sampleTypeIdentifier: typeIdentifier)
|
|
345
|
+
}
|
|
312
346
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
347
|
+
func subscribeToObserverQuery(
|
|
348
|
+
typeIdentifier: SampleTypeIdentifier,
|
|
349
|
+
callback: @escaping (OnChangeCallbackArgs) -> Void
|
|
350
|
+
) throws -> String {
|
|
351
|
+
let sampleType = try sampleTypeFrom(sampleTypeIdentifier: typeIdentifier)
|
|
318
352
|
|
|
319
|
-
|
|
353
|
+
let predicate = HKQuery.predicateForSamples(
|
|
354
|
+
withStart: Date.init(),
|
|
355
|
+
end: nil,
|
|
356
|
+
options: HKQueryOptions.strictStartDate
|
|
357
|
+
)
|
|
320
358
|
|
|
321
|
-
|
|
322
|
-
sampleType: sampleType,
|
|
323
|
-
predicate: predicate
|
|
324
|
-
) {
|
|
325
|
-
(_: HKObserverQuery, handler: @escaping HKObserverQueryCompletionHandler, error: Error?)
|
|
326
|
-
in
|
|
359
|
+
let queryId = UUID().uuidString
|
|
327
360
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
store.execute(query)
|
|
361
|
+
let query = HKObserverQuery(
|
|
362
|
+
sampleType: sampleType,
|
|
363
|
+
predicate: predicate
|
|
364
|
+
) {
|
|
365
|
+
(_: HKObserverQuery, handler: @escaping HKObserverQueryCompletionHandler, error: Error?)
|
|
366
|
+
in
|
|
336
367
|
|
|
337
|
-
|
|
368
|
+
DispatchQueue.main.async {
|
|
369
|
+
callback(
|
|
370
|
+
OnChangeCallbackArgs(
|
|
371
|
+
typeIdentifier: typeIdentifier, errorMessage: error?.localizedDescription))
|
|
372
|
+
handler()
|
|
373
|
+
}
|
|
338
374
|
|
|
339
|
-
return queryId
|
|
340
375
|
}
|
|
341
376
|
|
|
342
|
-
|
|
343
|
-
guard let query = self._runningQueries[queryId] else {
|
|
344
|
-
throw RuntimeError.error(withMessage: "[react-native-healthkit] Query with id \(queryId) not found")
|
|
345
|
-
}
|
|
377
|
+
store.execute(query)
|
|
346
378
|
|
|
347
|
-
|
|
379
|
+
self._runningQueries.updateValue(query, forKey: queryId)
|
|
348
380
|
|
|
349
|
-
|
|
381
|
+
return queryId
|
|
382
|
+
}
|
|
350
383
|
|
|
351
|
-
|
|
384
|
+
func unsubscribeQuery(queryId: String) throws -> Bool {
|
|
385
|
+
guard let query = self._runningQueries[queryId] else {
|
|
386
|
+
warnWithPrefix("unsubscribeQuery: Query with id \(queryId) not found")
|
|
387
|
+
|
|
388
|
+
return false
|
|
352
389
|
}
|
|
353
390
|
|
|
354
|
-
|
|
355
|
-
let successCount = self.unsubscribeQueries(queryIds: queryIds)
|
|
391
|
+
store.stop(query)
|
|
356
392
|
|
|
357
|
-
|
|
358
|
-
}
|
|
393
|
+
self._runningQueries.removeValue(forKey: queryId)
|
|
359
394
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
if let query = self._runningQueries[queryId] {
|
|
363
|
-
store.stop(query)
|
|
395
|
+
return true
|
|
396
|
+
}
|
|
364
397
|
|
|
365
|
-
|
|
398
|
+
func unsubscribeQueriesAsync(queryIds: [String]) -> Promise<Double> {
|
|
399
|
+
return Promise.async {
|
|
400
|
+
return self.unsubscribeQueries(queryIds: queryIds)
|
|
401
|
+
}
|
|
402
|
+
}
|
|
366
403
|
|
|
367
|
-
|
|
368
|
-
|
|
404
|
+
func unsubscribeQueries(queryIds: [String]) -> Double {
|
|
405
|
+
let successCounts = queryIds.map { queryId in
|
|
406
|
+
if let query = self._runningQueries[queryId] {
|
|
407
|
+
store.stop(query)
|
|
369
408
|
|
|
370
|
-
|
|
409
|
+
self._runningQueries.removeValue(forKey: queryId)
|
|
371
410
|
|
|
372
|
-
|
|
373
|
-
|
|
411
|
+
return true
|
|
412
|
+
}
|
|
374
413
|
|
|
375
|
-
|
|
414
|
+
warnWithPrefix("unsubscribeQueries: Query with id \(queryId) not found, skipping unsubscribe")
|
|
415
|
+
|
|
416
|
+
return false
|
|
376
417
|
}
|
|
377
418
|
|
|
419
|
+
return Double(successCounts.filter { $0 }.count)
|
|
420
|
+
}
|
|
421
|
+
|
|
378
422
|
}
|