@kingstinct/react-native-healthkit 6.1.0 → 7.0.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 +7 -5
- package/app.plugin.js +69 -0
- package/ios/Constants.swift +28 -0
- package/ios/Helpers.swift +152 -0
- package/ios/ReactNativeHealthkit.m +24 -0
- package/ios/ReactNativeHealthkit.swift +534 -728
- package/ios/Serializers.swift +206 -0
- package/lib/commonjs/hooks/useHealthkitAuthorization.js +0 -6
- package/lib/commonjs/hooks/useHealthkitAuthorization.js.map +1 -1
- package/lib/commonjs/hooks/useHealthkitAuthorization.test.js +2 -9
- package/lib/commonjs/hooks/useHealthkitAuthorization.test.js.map +1 -1
- package/lib/commonjs/hooks/useIsHealthDataAvailable.js +0 -6
- package/lib/commonjs/hooks/useIsHealthDataAvailable.js.map +1 -1
- package/lib/commonjs/hooks/useIsHealthDataAvailable.test.js +1 -6
- package/lib/commonjs/hooks/useIsHealthDataAvailable.test.js.map +1 -1
- package/lib/commonjs/hooks/useMostRecentCategorySample.js +1 -7
- package/lib/commonjs/hooks/useMostRecentCategorySample.js.map +1 -1
- package/lib/commonjs/hooks/useMostRecentQuantitySample.js +0 -10
- package/lib/commonjs/hooks/useMostRecentQuantitySample.js.map +1 -1
- package/lib/commonjs/hooks/useMostRecentWorkout.js +0 -10
- package/lib/commonjs/hooks/useMostRecentWorkout.js.map +1 -1
- package/lib/commonjs/hooks/useSources.js +0 -5
- package/lib/commonjs/hooks/useSources.js.map +1 -1
- package/lib/commonjs/hooks/useStatisticsForQuantity.js +1 -7
- package/lib/commonjs/hooks/useStatisticsForQuantity.js.map +1 -1
- package/lib/commonjs/hooks/useSubscribeToChanges.js +0 -8
- package/lib/commonjs/hooks/useSubscribeToChanges.js.map +1 -1
- package/lib/commonjs/index.ios.js +6 -33
- package/lib/commonjs/index.ios.js.map +1 -1
- package/lib/commonjs/index.js +7 -11
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/jest.setup.js +3 -1
- package/lib/commonjs/jest.setup.js.map +1 -1
- package/lib/commonjs/native-types.js +166 -250
- package/lib/commonjs/native-types.js.map +1 -1
- package/lib/commonjs/test-utils.js +1 -3
- package/lib/commonjs/test-utils.js.map +1 -1
- package/lib/commonjs/types.js +0 -2
- package/lib/commonjs/types.js.map +1 -1
- package/lib/commonjs/utils/deleteQuantitySample.js +0 -4
- package/lib/commonjs/utils/deleteQuantitySample.js.map +1 -1
- package/lib/commonjs/utils/deleteSamples.js +0 -4
- package/lib/commonjs/utils/deleteSamples.js.map +1 -1
- package/lib/commonjs/utils/deserializeCategorySample.js +2 -3
- package/lib/commonjs/utils/deserializeCategorySample.js.map +1 -1
- package/lib/commonjs/utils/deserializeCategorySample.test.js +3 -5
- package/lib/commonjs/utils/deserializeCategorySample.test.js.map +1 -1
- package/lib/commonjs/utils/deserializeCorrelation.js +2 -7
- package/lib/commonjs/utils/deserializeCorrelation.js.map +1 -1
- package/lib/commonjs/utils/deserializeHeartbeatSeriesSample.js +2 -3
- package/lib/commonjs/utils/deserializeHeartbeatSeriesSample.js.map +1 -1
- package/lib/commonjs/utils/deserializeSample.js +2 -3
- package/lib/commonjs/utils/deserializeSample.js.map +1 -1
- package/lib/commonjs/utils/deserializeWorkout.js +2 -3
- package/lib/commonjs/utils/deserializeWorkout.js.map +1 -1
- package/lib/commonjs/utils/ensureMetadata.js +0 -2
- package/lib/commonjs/utils/ensureMetadata.js.map +1 -1
- package/lib/commonjs/utils/ensureUnit.js +0 -5
- package/lib/commonjs/utils/ensureUnit.js.map +1 -1
- package/lib/commonjs/utils/getDateOfBirth.js +0 -4
- package/lib/commonjs/utils/getDateOfBirth.js.map +1 -1
- package/lib/commonjs/utils/getMostRecentCategorySample.js +1 -5
- package/lib/commonjs/utils/getMostRecentCategorySample.js.map +1 -1
- package/lib/commonjs/utils/getMostRecentQuantitySample.js +1 -5
- package/lib/commonjs/utils/getMostRecentQuantitySample.js.map +1 -1
- package/lib/commonjs/utils/getMostRecentWorkout.js +0 -4
- package/lib/commonjs/utils/getMostRecentWorkout.js.map +1 -1
- package/lib/commonjs/utils/getPreferredUnit.js +0 -4
- package/lib/commonjs/utils/getPreferredUnit.js.map +1 -1
- package/lib/commonjs/utils/getPreferredUnits.js +0 -4
- package/lib/commonjs/utils/getPreferredUnits.js.map +1 -1
- package/lib/commonjs/utils/getPreferredUnitsTyped.js +0 -11
- package/lib/commonjs/utils/getPreferredUnitsTyped.js.map +1 -1
- package/lib/commonjs/utils/getRequestStatusForAuthorization.js +4 -6
- package/lib/commonjs/utils/getRequestStatusForAuthorization.js.map +1 -1
- package/lib/commonjs/utils/prepareOptions.js +0 -4
- package/lib/commonjs/utils/prepareOptions.js.map +1 -1
- package/lib/commonjs/utils/queryCategorySamples.js +3 -14
- package/lib/commonjs/utils/queryCategorySamples.js.map +1 -1
- package/lib/commonjs/utils/queryCategorySamplesWithAnchor.js +22 -0
- package/lib/commonjs/utils/queryCategorySamplesWithAnchor.js.map +1 -0
- package/lib/commonjs/utils/queryCorrelationSamples.js +1 -7
- package/lib/commonjs/utils/queryCorrelationSamples.js.map +1 -1
- package/lib/commonjs/utils/queryHeartbeatSeriesSamples.js +3 -13
- package/lib/commonjs/utils/queryHeartbeatSeriesSamples.js.map +1 -1
- package/lib/commonjs/utils/queryHeartbeatSeriesSamplesWithAnchor.js +22 -0
- package/lib/commonjs/utils/queryHeartbeatSeriesSamplesWithAnchor.js.map +1 -0
- package/lib/commonjs/utils/queryQuantitySamples.js +3 -15
- package/lib/commonjs/utils/queryQuantitySamples.js.map +1 -1
- package/lib/commonjs/utils/queryQuantitySamplesWithAnchor.js +24 -0
- package/lib/commonjs/utils/queryQuantitySamplesWithAnchor.js.map +1 -0
- package/lib/commonjs/utils/querySources.js +0 -4
- package/lib/commonjs/utils/querySources.js.map +1 -1
- package/lib/commonjs/utils/queryStatisticsForQuantity.js +3 -7
- package/lib/commonjs/utils/queryStatisticsForQuantity.js.map +1 -1
- package/lib/commonjs/utils/queryWorkouts.js +1 -8
- package/lib/commonjs/utils/queryWorkouts.js.map +1 -1
- package/lib/commonjs/utils/requestAuthorization.js +4 -6
- package/lib/commonjs/utils/requestAuthorization.js.map +1 -1
- package/lib/commonjs/utils/saveCategorySample.js +0 -4
- package/lib/commonjs/utils/saveCategorySample.js.map +1 -1
- package/lib/commonjs/utils/saveCorrelationSample.js +3 -7
- package/lib/commonjs/utils/saveCorrelationSample.js.map +1 -1
- package/lib/commonjs/utils/saveQuantitySample.js +0 -4
- package/lib/commonjs/utils/saveQuantitySample.js.map +1 -1
- package/lib/commonjs/utils/saveWorkoutSample.js +3 -8
- package/lib/commonjs/utils/saveWorkoutSample.js.map +1 -1
- package/lib/commonjs/utils/serializeDate.js +0 -2
- package/lib/commonjs/utils/serializeDate.js.map +1 -1
- package/lib/commonjs/utils/serializeDate.test.js +0 -2
- package/lib/commonjs/utils/serializeDate.test.js.map +1 -1
- package/lib/commonjs/utils/subscribeToChanges.js +0 -7
- package/lib/commonjs/utils/subscribeToChanges.js.map +1 -1
- package/lib/module/hooks/useHealthkitAuthorization.js +0 -2
- package/lib/module/hooks/useHealthkitAuthorization.js.map +1 -1
- package/lib/module/hooks/useHealthkitAuthorization.test.js +1 -1
- package/lib/module/hooks/useHealthkitAuthorization.test.js.map +1 -1
- package/lib/module/hooks/useIsHealthDataAvailable.js +0 -3
- package/lib/module/hooks/useIsHealthDataAvailable.js.map +1 -1
- package/lib/module/hooks/useIsHealthDataAvailable.test.js +1 -1
- package/lib/module/hooks/useIsHealthDataAvailable.test.js.map +1 -1
- package/lib/module/hooks/useMostRecentCategorySample.js +1 -3
- package/lib/module/hooks/useMostRecentCategorySample.js.map +1 -1
- package/lib/module/hooks/useMostRecentQuantitySample.js +0 -5
- package/lib/module/hooks/useMostRecentQuantitySample.js.map +1 -1
- package/lib/module/hooks/useMostRecentWorkout.js +0 -5
- package/lib/module/hooks/useMostRecentWorkout.js.map +1 -1
- package/lib/module/hooks/useSources.js +0 -2
- package/lib/module/hooks/useSources.js.map +1 -1
- package/lib/module/hooks/useStatisticsForQuantity.js +1 -3
- package/lib/module/hooks/useStatisticsForQuantity.js.map +1 -1
- package/lib/module/hooks/useSubscribeToChanges.js +0 -5
- package/lib/module/hooks/useSubscribeToChanges.js.map +1 -1
- package/lib/module/index.ios.js +6 -0
- package/lib/module/index.ios.js.map +1 -1
- package/lib/module/index.js +8 -8
- package/lib/module/index.js.map +1 -1
- package/lib/module/jest.setup.js +3 -0
- package/lib/module/jest.setup.js.map +1 -1
- package/lib/module/native-types.js +134 -201
- package/lib/module/native-types.js.map +1 -1
- package/lib/module/test-utils.js +0 -2
- package/lib/module/test-utils.js.map +1 -1
- package/lib/module/types.js.map +1 -1
- package/lib/module/utils/deleteQuantitySample.js +0 -2
- package/lib/module/utils/deleteQuantitySample.js.map +1 -1
- package/lib/module/utils/deleteSamples.js +0 -2
- package/lib/module/utils/deleteSamples.js.map +1 -1
- package/lib/module/utils/deserializeCategorySample.js +2 -2
- package/lib/module/utils/deserializeCategorySample.js.map +1 -1
- package/lib/module/utils/deserializeCategorySample.test.js +3 -2
- package/lib/module/utils/deserializeCategorySample.test.js.map +1 -1
- package/lib/module/utils/deserializeCorrelation.js +2 -4
- package/lib/module/utils/deserializeCorrelation.js.map +1 -1
- package/lib/module/utils/deserializeHeartbeatSeriesSample.js +2 -2
- package/lib/module/utils/deserializeHeartbeatSeriesSample.js.map +1 -1
- package/lib/module/utils/deserializeSample.js +2 -2
- package/lib/module/utils/deserializeSample.js.map +1 -1
- package/lib/module/utils/deserializeWorkout.js +2 -2
- package/lib/module/utils/deserializeWorkout.js.map +1 -1
- package/lib/module/utils/ensureMetadata.js +0 -1
- package/lib/module/utils/ensureMetadata.js.map +1 -1
- package/lib/module/utils/ensureUnit.js +0 -3
- package/lib/module/utils/ensureUnit.js.map +1 -1
- package/lib/module/utils/getDateOfBirth.js +0 -2
- package/lib/module/utils/getDateOfBirth.js.map +1 -1
- package/lib/module/utils/getMostRecentCategorySample.js +1 -3
- package/lib/module/utils/getMostRecentCategorySample.js.map +1 -1
- package/lib/module/utils/getMostRecentQuantitySample.js +1 -3
- package/lib/module/utils/getMostRecentQuantitySample.js.map +1 -1
- package/lib/module/utils/getMostRecentWorkout.js +0 -2
- package/lib/module/utils/getMostRecentWorkout.js.map +1 -1
- package/lib/module/utils/getPreferredUnit.js +0 -2
- package/lib/module/utils/getPreferredUnit.js.map +1 -1
- package/lib/module/utils/getPreferredUnits.js +0 -2
- package/lib/module/utils/getPreferredUnits.js.map +1 -1
- package/lib/module/utils/getPreferredUnitsTyped.js +0 -8
- package/lib/module/utils/getPreferredUnitsTyped.js.map +1 -1
- package/lib/module/utils/getRequestStatusForAuthorization.js +4 -4
- package/lib/module/utils/getRequestStatusForAuthorization.js.map +1 -1
- package/lib/module/utils/prepareOptions.js +0 -2
- package/lib/module/utils/prepareOptions.js.map +1 -1
- package/lib/module/utils/queryCategorySamples.js +3 -10
- package/lib/module/utils/queryCategorySamples.js.map +1 -1
- package/lib/module/utils/queryCategorySamplesWithAnchor.js +14 -0
- package/lib/module/utils/queryCategorySamplesWithAnchor.js.map +1 -0
- package/lib/module/utils/queryCorrelationSamples.js +1 -3
- package/lib/module/utils/queryCorrelationSamples.js.map +1 -1
- package/lib/module/utils/queryHeartbeatSeriesSamples.js +3 -9
- package/lib/module/utils/queryHeartbeatSeriesSamples.js.map +1 -1
- package/lib/module/utils/queryHeartbeatSeriesSamplesWithAnchor.js +14 -0
- package/lib/module/utils/queryHeartbeatSeriesSamplesWithAnchor.js.map +1 -0
- package/lib/module/utils/queryQuantitySamples.js +3 -10
- package/lib/module/utils/queryQuantitySamples.js.map +1 -1
- package/lib/module/utils/queryQuantitySamplesWithAnchor.js +16 -0
- package/lib/module/utils/queryQuantitySamplesWithAnchor.js.map +1 -0
- package/lib/module/utils/querySources.js +0 -2
- package/lib/module/utils/querySources.js.map +1 -1
- package/lib/module/utils/queryStatisticsForQuantity.js +3 -4
- package/lib/module/utils/queryStatisticsForQuantity.js.map +1 -1
- package/lib/module/utils/queryWorkouts.js +1 -3
- package/lib/module/utils/queryWorkouts.js.map +1 -1
- package/lib/module/utils/requestAuthorization.js +4 -4
- package/lib/module/utils/requestAuthorization.js.map +1 -1
- package/lib/module/utils/saveCategorySample.js +0 -2
- package/lib/module/utils/saveCategorySample.js.map +1 -1
- package/lib/module/utils/saveCorrelationSample.js +3 -4
- package/lib/module/utils/saveCorrelationSample.js.map +1 -1
- package/lib/module/utils/saveQuantitySample.js +0 -2
- package/lib/module/utils/saveQuantitySample.js.map +1 -1
- package/lib/module/utils/saveWorkoutSample.js +3 -5
- package/lib/module/utils/saveWorkoutSample.js.map +1 -1
- package/lib/module/utils/serializeDate.js +0 -1
- package/lib/module/utils/serializeDate.js.map +1 -1
- package/lib/module/utils/serializeDate.test.js.map +1 -1
- package/lib/module/utils/subscribeToChanges.js +0 -3
- package/lib/module/utils/subscribeToChanges.js.map +1 -1
- package/lib/typescript/src/hooks/useMostRecentCategorySample.d.ts +2 -3
- package/lib/typescript/src/hooks/useMostRecentQuantitySample.d.ts +2 -3
- package/lib/typescript/src/index.ios.d.ts +4 -1
- package/lib/typescript/src/native-types.d.ts +66 -63
- package/lib/typescript/src/types.d.ts +3 -3
- package/lib/typescript/src/utils/deleteQuantitySample.d.ts +1 -1
- package/lib/typescript/src/utils/deleteSamples.d.ts +1 -1
- package/lib/typescript/src/utils/getMostRecentCategorySample.d.ts +1 -1
- package/lib/typescript/src/utils/getMostRecentQuantitySample.d.ts +1 -1
- package/lib/typescript/src/utils/getMostRecentWorkout.d.ts +1 -1
- package/lib/typescript/src/utils/getPreferredUnit.d.ts +1 -1
- package/lib/typescript/src/utils/getPreferredUnits.d.ts +1 -1
- package/lib/typescript/src/utils/queryCategorySamples.d.ts +3 -8
- package/lib/typescript/src/utils/queryCategorySamplesWithAnchor.d.ts +10 -0
- package/lib/typescript/src/utils/queryCorrelationSamples.d.ts +1 -1
- package/lib/typescript/src/utils/queryHeartbeatSeriesSamples.d.ts +2 -2
- package/lib/typescript/src/utils/queryHeartbeatSeriesSamplesWithAnchor.d.ts +10 -0
- package/lib/typescript/src/utils/queryQuantitySamples.d.ts +4 -9
- package/lib/typescript/src/utils/queryQuantitySamplesWithAnchor.d.ts +12 -0
- package/lib/typescript/src/utils/querySources.d.ts +1 -1
- package/package.json +20 -18
- package/src/hooks/useHealthkitAuthorization.test.ts +1 -1
- package/src/hooks/useIsHealthDataAvailable.test.ts +1 -1
- package/src/hooks/useMostRecentCategorySample.ts +3 -4
- package/src/hooks/useMostRecentQuantitySample.ts +2 -3
- package/src/hooks/useStatisticsForQuantity.ts +1 -1
- package/src/index.ios.tsx +6 -0
- package/src/index.tsx +10 -5
- package/src/jest.setup.ts +3 -0
- package/src/native-types.ts +28 -7
- package/src/utils/deserializeCategorySample.test.ts +1 -1
- package/src/utils/getMostRecentCategorySample.ts +1 -1
- package/src/utils/getMostRecentQuantitySample.ts +1 -1
- package/src/utils/queryCategorySamples.ts +6 -18
- package/src/utils/queryCategorySamplesWithAnchor.ts +39 -0
- package/src/utils/queryCorrelationSamples.ts +2 -2
- package/src/utils/queryHeartbeatSeriesSamples.ts +3 -8
- package/src/utils/queryHeartbeatSeriesSamplesWithAnchor.ts +33 -0
- package/src/utils/queryQuantitySamples.ts +8 -18
- package/src/utils/queryQuantitySamplesWithAnchor.ts +46 -0
- package/src/utils/queryStatisticsForQuantity.ts +1 -1
- package/src/utils/queryWorkouts.ts +1 -1
- package/src/utils/saveCorrelationSample.ts +1 -1
- package/src/utils/saveWorkoutSample.ts +1 -1
- package/android/.project +0 -34
- package/android/.settings/org.eclipse.buildship.core.prefs +0 -13
- package/android/build.gradle +0 -130
- package/android/gradle.properties +0 -4
- package/android/src/main/AndroidManifest.xml +0 -4
- package/android/src/main/java/com/kingstinctreactnativehealthkit/ReactNativeHealthkitModule.kt +0 -24
- package/android/src/main/java/com/kingstinctreactnativehealthkit/ReactNativeHealthkitPackage.kt +0 -20
|
@@ -1,41 +1,22 @@
|
|
|
1
|
-
import HealthKit
|
|
2
|
-
import CoreLocation
|
|
3
|
-
|
|
4
|
-
let INIT_ERROR = "HEALTHKIT_INIT_ERROR"
|
|
5
|
-
let INIT_ERROR_MESSAGE = "HealthKit not initialized"
|
|
6
|
-
let TYPE_IDENTIFIER_ERROR = "HEALTHKIT_TYPE_IDENTIFIER_NOT_RECOGNIZED_ERROR"
|
|
7
|
-
let GENERIC_ERROR = "HEALTHKIT_ERROR"
|
|
8
|
-
|
|
9
|
-
let HKCharacteristicTypeIdentifier_PREFIX = "HKCharacteristicTypeIdentifier"
|
|
10
|
-
let HKQuantityTypeIdentifier_PREFIX = "HKQuantityTypeIdentifier"
|
|
11
|
-
let HKCategoryTypeIdentifier_PREFIX = "HKCategoryTypeIdentifier"
|
|
12
|
-
let HKCorrelationTypeIdentifier_PREFIX = "HKCorrelationTypeIdentifier"
|
|
13
|
-
let HKActivitySummaryTypeIdentifier = "HKActivitySummaryTypeIdentifier"
|
|
14
|
-
let HKAudiogramTypeIdentifier = "HKAudiogramTypeIdentifier"
|
|
15
|
-
let HKWorkoutTypeIdentifier = "HKWorkoutTypeIdentifier"
|
|
16
|
-
let HKWorkoutRouteTypeIdentifier = "HKWorkoutRouteTypeIdentifier"
|
|
17
|
-
let HKDataTypeIdentifierHeartbeatSeries = "HKDataTypeIdentifierHeartbeatSeries"
|
|
18
|
-
|
|
19
|
-
let SpeedUnit = HKUnit(from: "m/s") // HKUnit.meter().unitDivided(by: HKUnit.second())
|
|
20
|
-
// Support for MET data: HKAverageMETs 8.24046 kcal/hr·kg
|
|
21
|
-
let METUnit = HKUnit(from: "kcal/hr·kg")
|
|
1
|
+
import HealthKit
|
|
2
|
+
import CoreLocation
|
|
22
3
|
|
|
23
4
|
@objc(ReactNativeHealthkit)
|
|
24
5
|
@available(iOS 10.0, *)
|
|
25
6
|
class ReactNativeHealthkit: RCTEventEmitter {
|
|
26
|
-
var _store
|
|
27
|
-
var _runningQueries
|
|
28
|
-
var _dateFormatter
|
|
7
|
+
var _store: HKHealthStore?
|
|
8
|
+
var _runningQueries: [String: HKQuery]
|
|
9
|
+
var _dateFormatter: ISO8601DateFormatter
|
|
29
10
|
var _hasListeners = false
|
|
30
11
|
|
|
31
12
|
override init() {
|
|
32
|
-
self._runningQueries =
|
|
33
|
-
self._dateFormatter = ISO8601DateFormatter()
|
|
13
|
+
self._runningQueries = [String: HKQuery]()
|
|
14
|
+
self._dateFormatter = ISO8601DateFormatter()
|
|
34
15
|
|
|
35
|
-
if
|
|
36
|
-
self._store = HKHealthStore.init()
|
|
16
|
+
if HKHealthStore.isHealthDataAvailable() {
|
|
17
|
+
self._store = HKHealthStore.init()
|
|
37
18
|
}
|
|
38
|
-
super.init()
|
|
19
|
+
super.init()
|
|
39
20
|
}
|
|
40
21
|
|
|
41
22
|
deinit {
|
|
@@ -46,7 +27,7 @@ class ReactNativeHealthkit: RCTEventEmitter {
|
|
|
46
27
|
}
|
|
47
28
|
}
|
|
48
29
|
|
|
49
|
-
override func stopObserving()
|
|
30
|
+
override func stopObserving() {
|
|
50
31
|
self._hasListeners = false
|
|
51
32
|
if let store = _store {
|
|
52
33
|
for query in self._runningQueries {
|
|
@@ -55,336 +36,169 @@ class ReactNativeHealthkit: RCTEventEmitter {
|
|
|
55
36
|
}
|
|
56
37
|
}
|
|
57
38
|
|
|
58
|
-
override func startObserving()
|
|
39
|
+
override func startObserving() {
|
|
59
40
|
self._hasListeners = true
|
|
60
41
|
}
|
|
61
42
|
|
|
62
|
-
|
|
63
43
|
@objc(canAccessProtectedData:withRejecter:)
|
|
64
|
-
func canAccessProtectedData(resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock)
|
|
65
|
-
resolve(UIApplication.shared.isProtectedDataAvailable)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
func objectTypeFromString(typeIdentifier: String) -> HKObjectType? {
|
|
70
|
-
if(typeIdentifier.starts(with: HKCharacteristicTypeIdentifier_PREFIX)){
|
|
71
|
-
let identifier = HKCharacteristicTypeIdentifier.init(rawValue: typeIdentifier);
|
|
72
|
-
return HKObjectType.characteristicType(forIdentifier: identifier) as HKObjectType?
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if(typeIdentifier.starts(with: HKQuantityTypeIdentifier_PREFIX)){
|
|
76
|
-
let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier);
|
|
77
|
-
return HKObjectType.quantityType(forIdentifier: identifier) as HKObjectType?
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if(typeIdentifier.starts(with: HKCategoryTypeIdentifier_PREFIX)){
|
|
81
|
-
let identifier = HKCategoryTypeIdentifier.init(rawValue: typeIdentifier);
|
|
82
|
-
return HKObjectType.categoryType(forIdentifier: identifier) as HKObjectType?
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
if(typeIdentifier.starts(with: HKCorrelationTypeIdentifier_PREFIX)){
|
|
86
|
-
let identifier = HKCorrelationTypeIdentifier.init(rawValue: typeIdentifier);
|
|
87
|
-
return HKObjectType.correlationType(forIdentifier: identifier) as HKObjectType?
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if(typeIdentifier == HKActivitySummaryTypeIdentifier){
|
|
91
|
-
return HKObjectType.activitySummaryType();
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if #available(iOS 13, *) {
|
|
95
|
-
if(typeIdentifier == HKAudiogramTypeIdentifier){
|
|
96
|
-
return HKObjectType.audiogramSampleType();
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if(typeIdentifier == HKDataTypeIdentifierHeartbeatSeries){
|
|
100
|
-
return HKObjectType.seriesType(forIdentifier: typeIdentifier);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if(typeIdentifier == HKWorkoutTypeIdentifier){
|
|
105
|
-
return HKObjectType.workoutType()
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
if #available(iOS 11.0, *){
|
|
109
|
-
if typeIdentifier == HKWorkoutRouteTypeIdentifier{
|
|
110
|
-
return HKObjectType.seriesType(forIdentifier: typeIdentifier);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return nil;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
func sampleTypeFromString(typeIdentifier: String) -> HKSampleType? {
|
|
118
|
-
if(typeIdentifier.starts(with: HKQuantityTypeIdentifier_PREFIX)){
|
|
119
|
-
let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier);
|
|
120
|
-
return HKSampleType.quantityType(forIdentifier: identifier) as HKSampleType?
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if(typeIdentifier.starts(with: HKCategoryTypeIdentifier_PREFIX)){
|
|
124
|
-
let identifier = HKCategoryTypeIdentifier.init(rawValue: typeIdentifier);
|
|
125
|
-
return HKSampleType.categoryType(forIdentifier: identifier) as HKSampleType?
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if(typeIdentifier.starts(with: HKCorrelationTypeIdentifier_PREFIX)){
|
|
129
|
-
let identifier = HKCorrelationTypeIdentifier.init(rawValue: typeIdentifier);
|
|
130
|
-
return HKSampleType.correlationType(forIdentifier: identifier) as HKSampleType?
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
if #available(iOS 13, *) {
|
|
134
|
-
if(typeIdentifier == HKAudiogramTypeIdentifier){
|
|
135
|
-
return HKSampleType.audiogramSampleType();
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
if(typeIdentifier == HKWorkoutTypeIdentifier){
|
|
140
|
-
return HKSampleType.workoutType();
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return nil;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
func objectTypesFromDictionary(typeIdentifiers: NSDictionary) -> Set<HKObjectType> {
|
|
147
|
-
var share = Set<HKObjectType>();
|
|
148
|
-
for item in typeIdentifiers {
|
|
149
|
-
if(item.value as! Bool){
|
|
150
|
-
let objectType = objectTypeFromString(typeIdentifier: item.key as! String);
|
|
151
|
-
if(objectType != nil){
|
|
152
|
-
share.insert(objectType!);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
return share;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
func sampleTypesFromDictionary(typeIdentifiers: NSDictionary) -> Set<HKSampleType> {
|
|
160
|
-
var share = Set<HKSampleType>();
|
|
161
|
-
for item in typeIdentifiers {
|
|
162
|
-
if(item.value as! Bool){
|
|
163
|
-
let sampleType = sampleTypeFromString(typeIdentifier: item.key as! String);
|
|
164
|
-
if(sampleType != nil){
|
|
165
|
-
share.insert(sampleType!);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
return share;
|
|
44
|
+
func canAccessProtectedData(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
45
|
+
resolve(UIApplication.shared.isProtectedDataAvailable)
|
|
170
46
|
}
|
|
171
47
|
|
|
172
48
|
@objc(isHealthDataAvailable:withRejecter:)
|
|
173
|
-
func isHealthDataAvailable(resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock)
|
|
49
|
+
func isHealthDataAvailable(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
174
50
|
resolve(HKHealthStore.isHealthDataAvailable())
|
|
175
51
|
}
|
|
176
52
|
|
|
177
53
|
@available(iOS 12.0, *)
|
|
178
54
|
@objc(supportsHealthRecords:withRejecter:)
|
|
179
|
-
func supportsHealthRecords(resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock)
|
|
55
|
+
func supportsHealthRecords(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
|
|
180
56
|
guard let store = _store else {
|
|
181
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
57
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
182
58
|
}
|
|
183
|
-
resolve(store.supportsHealthRecords())
|
|
59
|
+
resolve(store.supportsHealthRecords())
|
|
184
60
|
}
|
|
185
61
|
|
|
186
62
|
@available(iOS 12.0, *)
|
|
187
63
|
@objc(getRequestStatusForAuthorization:read:resolve:withRejecter:)
|
|
188
|
-
func getRequestStatusForAuthorization(toShare: NSDictionary, read: NSDictionary, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock)
|
|
64
|
+
func getRequestStatusForAuthorization(toShare: NSDictionary, read: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
189
65
|
guard let store = _store else {
|
|
190
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
66
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
191
67
|
}
|
|
192
|
-
let share = sampleTypesFromDictionary(typeIdentifiers: toShare)
|
|
193
|
-
let toRead = objectTypesFromDictionary(typeIdentifiers: read)
|
|
68
|
+
let share = sampleTypesFromDictionary(typeIdentifiers: toShare)
|
|
69
|
+
let toRead = objectTypesFromDictionary(typeIdentifiers: read)
|
|
194
70
|
store.getRequestStatusForAuthorization(toShare: share, read: toRead) { (status: HKAuthorizationRequestStatus, error: Error?) in
|
|
195
71
|
guard let err = error else {
|
|
196
|
-
return resolve(status.rawValue)
|
|
72
|
+
return resolve(status.rawValue)
|
|
197
73
|
}
|
|
198
|
-
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
74
|
+
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
199
75
|
}
|
|
200
76
|
}
|
|
201
77
|
|
|
202
78
|
@objc(getPreferredUnits:resolve:reject:)
|
|
203
|
-
func getPreferredUnits(forIdentifiers: NSArray, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock)
|
|
79
|
+
func getPreferredUnits(forIdentifiers: NSArray, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
204
80
|
guard let store = _store else {
|
|
205
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
81
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
206
82
|
}
|
|
207
|
-
var quantityTypes = Set<HKQuantityType>()
|
|
83
|
+
var quantityTypes = Set<HKQuantityType>()
|
|
208
84
|
for identifierString in forIdentifiers {
|
|
209
|
-
let identifier = HKQuantityTypeIdentifier.init(rawValue: identifierString as! String)
|
|
210
|
-
let type = HKSampleType.quantityType(forIdentifier: identifier)
|
|
211
|
-
if
|
|
212
|
-
quantityTypes.insert(type!)
|
|
85
|
+
let identifier = HKQuantityTypeIdentifier.init(rawValue: identifierString as! String)
|
|
86
|
+
let type = HKSampleType.quantityType(forIdentifier: identifier)
|
|
87
|
+
if type != nil {
|
|
88
|
+
quantityTypes.insert(type!)
|
|
213
89
|
}
|
|
214
90
|
}
|
|
215
91
|
|
|
216
|
-
store.preferredUnits(for: quantityTypes) { (typePerUnits: [HKQuantityType
|
|
217
|
-
let dic: NSMutableDictionary = NSMutableDictionary()
|
|
92
|
+
store.preferredUnits(for: quantityTypes) { (typePerUnits: [HKQuantityType: HKUnit], _: Error?) in
|
|
93
|
+
let dic: NSMutableDictionary = NSMutableDictionary()
|
|
218
94
|
|
|
219
95
|
for typePerUnit in typePerUnits {
|
|
220
|
-
dic.setObject(typePerUnit.value.unitString, forKey: typePerUnit.key.identifier as NSCopying)
|
|
96
|
+
dic.setObject(typePerUnit.value.unitString, forKey: typePerUnit.key.identifier as NSCopying)
|
|
221
97
|
}
|
|
222
98
|
|
|
223
|
-
resolve(dic)
|
|
99
|
+
resolve(dic)
|
|
224
100
|
}
|
|
225
101
|
}
|
|
226
102
|
|
|
227
|
-
func serializeQuantity(unit: HKUnit, quantity: HKQuantity?) -> Dictionary<String, Any>? {
|
|
228
|
-
guard let q = quantity else {
|
|
229
|
-
return nil;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
return [
|
|
233
|
-
"quantity": q.doubleValue(for: unit),
|
|
234
|
-
"unit": unit.unitString
|
|
235
|
-
]
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
func serializeQuantitySample(sample: HKQuantitySample, unit: HKUnit) -> NSDictionary {
|
|
239
|
-
let endDate = _dateFormatter.string(from: sample.endDate)
|
|
240
|
-
let startDate = _dateFormatter.string(from: sample.startDate);
|
|
241
|
-
|
|
242
|
-
let quantity = sample.quantity.doubleValue(for: unit);
|
|
243
|
-
|
|
244
|
-
return [
|
|
245
|
-
"uuid": sample.uuid.uuidString,
|
|
246
|
-
"device": self.serializeDevice(_device: sample.device) as Any,
|
|
247
|
-
"quantityType": sample.quantityType.identifier,
|
|
248
|
-
"endDate": endDate,
|
|
249
|
-
"startDate": startDate,
|
|
250
|
-
"quantity": quantity,
|
|
251
|
-
"unit": unit.unitString,
|
|
252
|
-
"metadata": self.serializeMetadata(metadata: sample.metadata),
|
|
253
|
-
"sourceRevision": self.serializeSourceRevision(_sourceRevision: sample.sourceRevision) as Any,
|
|
254
|
-
]
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
func serializeDeletedSample(sample: HKDeletedObject) -> NSDictionary {
|
|
258
|
-
return [
|
|
259
|
-
"uuid": sample.uuid.uuidString,
|
|
260
|
-
"metadata": self.serializeMetadata(metadata: sample.metadata)
|
|
261
|
-
]
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
func serializeCategorySample(sample: HKCategorySample) -> NSDictionary {
|
|
265
|
-
let endDate = _dateFormatter.string(from: sample.endDate)
|
|
266
|
-
let startDate = _dateFormatter.string(from: sample.startDate);
|
|
267
|
-
|
|
268
|
-
return [
|
|
269
|
-
"uuid": sample.uuid.uuidString,
|
|
270
|
-
"device": self.serializeDevice(_device: sample.device) as Any,
|
|
271
|
-
"categoryType": sample.categoryType.identifier,
|
|
272
|
-
"endDate": endDate,
|
|
273
|
-
"startDate": startDate,
|
|
274
|
-
"value": sample.value,
|
|
275
|
-
"metadata": self.serializeMetadata(metadata: sample.metadata),
|
|
276
|
-
"sourceRevision": self.serializeSourceRevision(_sourceRevision: sample.sourceRevision) as Any,
|
|
277
|
-
]
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
func serializeSource(source: HKSource) -> NSDictionary {
|
|
281
|
-
|
|
282
|
-
return [
|
|
283
|
-
"bundleIdentifier": source.bundleIdentifier,
|
|
284
|
-
"name": source.name
|
|
285
|
-
]
|
|
286
|
-
}
|
|
287
|
-
|
|
288
103
|
@objc(getBiologicalSex:withRejecter:)
|
|
289
|
-
func getBiologicalSex(resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock)
|
|
104
|
+
func getBiologicalSex(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
290
105
|
guard let store = _store else {
|
|
291
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
106
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
292
107
|
}
|
|
293
108
|
|
|
294
109
|
do {
|
|
295
|
-
let bioSex = try store.biologicalSex()
|
|
296
|
-
resolve(bioSex.biologicalSex.rawValue)
|
|
110
|
+
let bioSex = try store.biologicalSex()
|
|
111
|
+
resolve(bioSex.biologicalSex.rawValue)
|
|
297
112
|
} catch {
|
|
298
|
-
reject(GENERIC_ERROR, error.localizedDescription, error)
|
|
113
|
+
reject(GENERIC_ERROR, error.localizedDescription, error)
|
|
299
114
|
}
|
|
300
115
|
}
|
|
301
116
|
|
|
302
117
|
@objc(getDateOfBirth:withRejecter:)
|
|
303
|
-
func getDateOfBirth(resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock)
|
|
118
|
+
func getDateOfBirth(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
304
119
|
guard let store = _store else {
|
|
305
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
120
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
306
121
|
}
|
|
307
122
|
|
|
308
123
|
do {
|
|
309
|
-
let dateOfBirth = try store.dateOfBirth()
|
|
310
|
-
resolve(_dateFormatter.string(from: dateOfBirth))
|
|
124
|
+
let dateOfBirth = try store.dateOfBirth()
|
|
125
|
+
resolve(_dateFormatter.string(from: dateOfBirth))
|
|
311
126
|
} catch {
|
|
312
|
-
reject(GENERIC_ERROR, error.localizedDescription, error)
|
|
127
|
+
reject(GENERIC_ERROR, error.localizedDescription, error)
|
|
313
128
|
}
|
|
314
129
|
}
|
|
315
130
|
|
|
316
131
|
@objc(getBloodType:withRejecter:)
|
|
317
|
-
func getBloodType(resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock)
|
|
132
|
+
func getBloodType(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
318
133
|
guard let store = _store else {
|
|
319
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
134
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
320
135
|
}
|
|
321
136
|
|
|
322
137
|
do {
|
|
323
|
-
let bloodType = try store.bloodType()
|
|
324
|
-
resolve(bloodType.bloodType.rawValue)
|
|
138
|
+
let bloodType = try store.bloodType()
|
|
139
|
+
resolve(bloodType.bloodType.rawValue)
|
|
325
140
|
} catch {
|
|
326
|
-
reject(GENERIC_ERROR, error.localizedDescription, error)
|
|
141
|
+
reject(GENERIC_ERROR, error.localizedDescription, error)
|
|
327
142
|
}
|
|
328
143
|
}
|
|
329
144
|
|
|
330
145
|
@objc(getFitzpatrickSkinType:withRejecter:)
|
|
331
|
-
func getFitzpatrickSkinType(resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock)
|
|
146
|
+
func getFitzpatrickSkinType(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
332
147
|
guard let store = _store else {
|
|
333
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
148
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
334
149
|
}
|
|
335
150
|
|
|
336
151
|
do {
|
|
337
|
-
let fitzpatrickSkinType = try store.fitzpatrickSkinType()
|
|
338
|
-
resolve(fitzpatrickSkinType.skinType.rawValue)
|
|
152
|
+
let fitzpatrickSkinType = try store.fitzpatrickSkinType()
|
|
153
|
+
resolve(fitzpatrickSkinType.skinType.rawValue)
|
|
339
154
|
} catch {
|
|
340
|
-
reject(GENERIC_ERROR, error.localizedDescription, error)
|
|
155
|
+
reject(GENERIC_ERROR, error.localizedDescription, error)
|
|
341
156
|
}
|
|
342
157
|
}
|
|
343
158
|
|
|
344
|
-
|
|
345
159
|
@available(iOS 10.0, *)
|
|
346
160
|
@objc(getWheelchairUse:withRejecter:)
|
|
347
|
-
func getWheelchairUse(resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock)
|
|
161
|
+
func getWheelchairUse(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
348
162
|
guard let store = _store else {
|
|
349
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
163
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
350
164
|
}
|
|
351
165
|
|
|
352
166
|
do {
|
|
353
|
-
let wheelchairUse = try store.wheelchairUse()
|
|
354
|
-
resolve(wheelchairUse.wheelchairUse.rawValue)
|
|
167
|
+
let wheelchairUse = try store.wheelchairUse()
|
|
168
|
+
resolve(wheelchairUse.wheelchairUse.rawValue)
|
|
355
169
|
} catch {
|
|
356
|
-
reject(GENERIC_ERROR, error.localizedDescription, error)
|
|
170
|
+
reject(GENERIC_ERROR, error.localizedDescription, error)
|
|
357
171
|
}
|
|
358
172
|
}
|
|
359
173
|
|
|
360
174
|
@objc(authorizationStatusFor:withResolver:withRejecter:)
|
|
361
|
-
func authorizationStatusFor(typeIdentifier: String, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock)
|
|
175
|
+
func authorizationStatusFor(typeIdentifier: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
362
176
|
guard let store = _store else {
|
|
363
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
177
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
364
178
|
}
|
|
365
179
|
|
|
366
180
|
guard let objectType = objectTypeFromString(typeIdentifier: typeIdentifier) else {
|
|
367
|
-
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
181
|
+
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
368
182
|
}
|
|
369
183
|
|
|
370
|
-
let authStatus = store.authorizationStatus(for: objectType)
|
|
371
|
-
resolve(authStatus.rawValue)
|
|
184
|
+
let authStatus = store.authorizationStatus(for: objectType)
|
|
185
|
+
resolve(authStatus.rawValue)
|
|
372
186
|
}
|
|
373
187
|
|
|
374
188
|
@objc(saveQuantitySample:unitString:value:start:end:metadata:resolve:reject:)
|
|
375
|
-
func saveQuantitySample(typeIdentifier: String, unitString: String, value: Double, start: Date, end: Date, metadata:
|
|
189
|
+
func saveQuantitySample(typeIdentifier: String, unitString: String, value: Double, start: Date, end: Date, metadata: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
376
190
|
guard let store = _store else {
|
|
377
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
191
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
378
192
|
}
|
|
379
193
|
|
|
380
|
-
let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier)
|
|
194
|
+
let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier)
|
|
381
195
|
|
|
382
196
|
guard let type = HKObjectType.quantityType(forIdentifier: identifier) else {
|
|
383
|
-
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
197
|
+
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
384
198
|
}
|
|
385
199
|
|
|
386
|
-
let unit = HKUnit.init(from: unitString)
|
|
387
|
-
let quantity = HKQuantity.init(unit: unit, doubleValue: value)
|
|
200
|
+
let unit = HKUnit.init(from: unitString)
|
|
201
|
+
let quantity = HKQuantity.init(unit: unit, doubleValue: value)
|
|
388
202
|
let sample = HKQuantitySample.init(
|
|
389
203
|
type: type,
|
|
390
204
|
quantity: quantity,
|
|
@@ -395,72 +209,72 @@ class ReactNativeHealthkit: RCTEventEmitter {
|
|
|
395
209
|
|
|
396
210
|
store.save(sample) { (success: Bool, error: Error?) in
|
|
397
211
|
guard let err = error else {
|
|
398
|
-
return resolve(success)
|
|
212
|
+
return resolve(success)
|
|
399
213
|
}
|
|
400
|
-
reject(GENERIC_ERROR, err.localizedDescription, error)
|
|
214
|
+
reject(GENERIC_ERROR, err.localizedDescription, error)
|
|
401
215
|
}
|
|
402
216
|
}
|
|
403
217
|
|
|
404
218
|
@objc(deleteQuantitySample:uuid:resolve:reject:)
|
|
405
|
-
func deleteQuantitySample(typeIdentifier: String, uuid: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock){
|
|
219
|
+
func deleteQuantitySample(typeIdentifier: String, uuid: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
406
220
|
guard let store = _store else {
|
|
407
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
221
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
408
222
|
}
|
|
409
223
|
|
|
410
|
-
let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier)
|
|
411
|
-
let sampleUuid = UUID.init(uuidString: uuid)
|
|
224
|
+
let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier)
|
|
225
|
+
let sampleUuid = UUID.init(uuidString: uuid)!
|
|
412
226
|
|
|
413
227
|
guard let sampleType = HKObjectType.quantityType(forIdentifier: identifier) else {
|
|
414
|
-
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
228
|
+
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
415
229
|
}
|
|
416
230
|
|
|
417
|
-
let samplePredicate = HKQuery.predicateForObject(with: sampleUuid)
|
|
231
|
+
let samplePredicate = HKQuery.predicateForObject(with: sampleUuid)
|
|
418
232
|
|
|
419
|
-
store.deleteObjects(of: sampleType, predicate: samplePredicate) { (success: Bool,
|
|
233
|
+
store.deleteObjects(of: sampleType, predicate: samplePredicate) { (success: Bool, _: Int, error: Error?) in
|
|
420
234
|
guard let err = error else {
|
|
421
|
-
return resolve(success)
|
|
235
|
+
return resolve(success)
|
|
422
236
|
}
|
|
423
|
-
reject(GENERIC_ERROR, err.localizedDescription, error)
|
|
237
|
+
reject(GENERIC_ERROR, err.localizedDescription, error)
|
|
424
238
|
}
|
|
425
239
|
}
|
|
426
240
|
|
|
427
241
|
@objc(deleteSamples:start:end:resolve:reject:)
|
|
428
|
-
func deleteSamples(typeIdentifier: String, start: Date, end: Date, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock){
|
|
242
|
+
func deleteSamples(typeIdentifier: String, start: Date, end: Date, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
429
243
|
guard let store = _store else {
|
|
430
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
244
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
431
245
|
}
|
|
432
246
|
|
|
433
|
-
let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier)
|
|
247
|
+
let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier)
|
|
434
248
|
|
|
435
249
|
guard let sampleType = HKObjectType.quantityType(forIdentifier: identifier) else {
|
|
436
|
-
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
250
|
+
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
437
251
|
}
|
|
438
252
|
|
|
439
|
-
let samplePredicate = HKQuery.predicateForSamples(withStart: start, end: end, options: HKQueryOptions.strictStartDate)
|
|
253
|
+
let samplePredicate = HKQuery.predicateForSamples(withStart: start, end: end, options: HKQueryOptions.strictStartDate)
|
|
440
254
|
|
|
441
|
-
store.deleteObjects(of: sampleType, predicate: samplePredicate) { (success: Bool,
|
|
255
|
+
store.deleteObjects(of: sampleType, predicate: samplePredicate) { (success: Bool, _: Int, error: Error?) in
|
|
442
256
|
guard let err = error else {
|
|
443
|
-
return resolve(success)
|
|
257
|
+
return resolve(success)
|
|
444
258
|
}
|
|
445
|
-
reject(GENERIC_ERROR, err.localizedDescription, error)
|
|
259
|
+
reject(GENERIC_ERROR, err.localizedDescription, error)
|
|
446
260
|
}
|
|
447
261
|
}
|
|
448
262
|
|
|
449
263
|
@objc(saveCorrelationSample:samples:start:end:metadata:resolve:reject:)
|
|
450
|
-
func saveCorrelationSample(typeIdentifier: String, samples:
|
|
264
|
+
func saveCorrelationSample(typeIdentifier: String, samples: [[String: Any]], start: Date, end: Date, metadata: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
451
265
|
guard let store = _store else {
|
|
452
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
266
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
453
267
|
}
|
|
454
268
|
|
|
455
|
-
let identifier = HKCorrelationTypeIdentifier.init(rawValue: typeIdentifier)
|
|
269
|
+
let identifier = HKCorrelationTypeIdentifier.init(rawValue: typeIdentifier)
|
|
456
270
|
|
|
457
271
|
guard let type = HKObjectType.correlationType(forIdentifier: identifier) else {
|
|
458
|
-
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
272
|
+
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
459
273
|
}
|
|
460
274
|
|
|
461
|
-
var initializedSamples = Set<HKSample>()
|
|
275
|
+
var initializedSamples = Set<HKSample>()
|
|
462
276
|
for sample in samples {
|
|
463
|
-
if
|
|
277
|
+
if sample.keys.contains("quantityType") {
|
|
464
278
|
let typeId = HKQuantityTypeIdentifier.init(rawValue: sample["quantityType"] as! String)
|
|
465
279
|
if let type = HKSampleType.quantityType(forIdentifier: typeId) {
|
|
466
280
|
let unitStr = sample["unit"] as! String
|
|
@@ -472,14 +286,14 @@ class ReactNativeHealthkit: RCTEventEmitter {
|
|
|
472
286
|
let quantitySample = HKQuantitySample.init(type: type, quantity: quantity, start: start, end: end, metadata: metadata)
|
|
473
287
|
initializedSamples.insert(quantitySample)
|
|
474
288
|
}
|
|
475
|
-
} else if
|
|
289
|
+
} else if sample.keys.contains("categoryType") {
|
|
476
290
|
let typeId = HKCategoryTypeIdentifier.init(rawValue: sample["categoryType"] as! String)
|
|
477
291
|
if let type = HKSampleType.categoryType(forIdentifier: typeId) {
|
|
478
292
|
let value = sample["value"] as! Int
|
|
479
293
|
let metadata = sample["metadata"] as? [String: Any]
|
|
480
294
|
|
|
481
295
|
let categorySample = HKCategorySample.init(type: type, value: value, start: start, end: end, metadata: metadata)
|
|
482
|
-
initializedSamples.insert(categorySample)
|
|
296
|
+
initializedSamples.insert(categorySample)
|
|
483
297
|
}
|
|
484
298
|
}
|
|
485
299
|
|
|
@@ -489,23 +303,23 @@ class ReactNativeHealthkit: RCTEventEmitter {
|
|
|
489
303
|
|
|
490
304
|
store.save(correlation) { (success: Bool, error: Error?) in
|
|
491
305
|
guard let err = error else {
|
|
492
|
-
return resolve(success)
|
|
306
|
+
return resolve(success)
|
|
493
307
|
}
|
|
494
|
-
reject(GENERIC_ERROR, err.localizedDescription, error)
|
|
308
|
+
reject(GENERIC_ERROR, err.localizedDescription, error)
|
|
495
309
|
}
|
|
496
310
|
}
|
|
497
311
|
|
|
498
312
|
@objc(saveWorkoutSample:quantities:start:end:metadata:resolve:reject:)
|
|
499
|
-
func saveWorkoutSample(typeIdentifier: UInt, quantities:
|
|
313
|
+
func saveWorkoutSample(typeIdentifier: UInt, quantities: [[String: Any]], start: Date, end: Date, metadata: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
500
314
|
guard let store = _store else {
|
|
501
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
315
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
502
316
|
}
|
|
503
317
|
|
|
504
318
|
guard let type = HKWorkoutActivityType.init(rawValue: typeIdentifier) else {
|
|
505
|
-
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier.description, nil)
|
|
319
|
+
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier.description, nil)
|
|
506
320
|
}
|
|
507
321
|
|
|
508
|
-
var initializedSamples = [HKSample]()
|
|
322
|
+
var initializedSamples = [HKSample]()
|
|
509
323
|
var totalEnergyBurned: HKQuantity?
|
|
510
324
|
var totalDistance: HKQuantity?
|
|
511
325
|
var totalSwimmingStrokeCount: HKQuantity?
|
|
@@ -520,78 +334,76 @@ class ReactNativeHealthkit: RCTEventEmitter {
|
|
|
520
334
|
|
|
521
335
|
let unit = HKUnit.init(from: unitStr)
|
|
522
336
|
let quantity = HKQuantity.init(unit: unit, doubleValue: quantityVal)
|
|
523
|
-
if
|
|
524
|
-
totalEnergyBurned = quantity
|
|
337
|
+
if quantity.is(compatibleWith: HKUnit.kilocalorie()) {
|
|
338
|
+
totalEnergyBurned = quantity
|
|
525
339
|
}
|
|
526
|
-
if
|
|
527
|
-
totalDistance = quantity
|
|
340
|
+
if quantity.is(compatibleWith: HKUnit.meter()) {
|
|
341
|
+
totalDistance = quantity
|
|
528
342
|
}
|
|
529
|
-
if
|
|
530
|
-
totalSwimmingStrokeCount = quantity
|
|
343
|
+
if typeId == HKQuantityTypeIdentifier.swimmingStrokeCount {
|
|
344
|
+
totalSwimmingStrokeCount = quantity
|
|
531
345
|
}
|
|
532
|
-
if
|
|
533
|
-
totalFlightsClimbed = quantity
|
|
346
|
+
if typeId == HKQuantityTypeIdentifier.flightsClimbed {
|
|
347
|
+
totalFlightsClimbed = quantity
|
|
534
348
|
}
|
|
535
349
|
let quantitySample = HKQuantitySample.init(type: type, quantity: quantity, start: start, end: end, metadata: metadata)
|
|
536
350
|
initializedSamples.append(quantitySample)
|
|
537
351
|
}
|
|
538
352
|
}
|
|
539
353
|
|
|
540
|
-
var workout: HKWorkout
|
|
354
|
+
var workout: HKWorkout?
|
|
541
355
|
|
|
542
|
-
|
|
543
|
-
if(totalSwimmingStrokeCount != nil){
|
|
356
|
+
if totalSwimmingStrokeCount != nil {
|
|
544
357
|
workout = HKWorkout.init(activityType: type, start: start, end: end, workoutEvents: nil, totalEnergyBurned: totalEnergyBurned, totalDistance: totalDistance, totalSwimmingStrokeCount: totalSwimmingStrokeCount, device: nil, metadata: metadata)
|
|
545
358
|
} else {
|
|
546
359
|
if #available(iOS 11, *) {
|
|
547
|
-
if
|
|
360
|
+
if totalFlightsClimbed != nil {
|
|
548
361
|
workout = HKWorkout.init(activityType: type, start: start, end: end, workoutEvents: nil, totalEnergyBurned: totalEnergyBurned, totalDistance: totalDistance, totalFlightsClimbed: totalFlightsClimbed, device: nil, metadata: metadata)
|
|
549
362
|
}
|
|
550
363
|
}
|
|
551
364
|
}
|
|
552
365
|
|
|
553
|
-
if
|
|
366
|
+
if workout == nil {
|
|
554
367
|
workout = HKWorkout.init(activityType: type, start: start, end: end, workoutEvents: nil, totalEnergyBurned: totalEnergyBurned, totalDistance: totalDistance, metadata: metadata)
|
|
555
368
|
}
|
|
556
369
|
|
|
557
370
|
store.save(workout!) { (success: Bool, error: Error?) in
|
|
558
371
|
guard let err = error else {
|
|
559
|
-
if
|
|
372
|
+
if success {
|
|
560
373
|
store.add(initializedSamples, to: workout!) { (success, error: Error?) in
|
|
561
374
|
guard let err = error else {
|
|
562
|
-
return resolve(success)
|
|
375
|
+
return resolve(success)
|
|
563
376
|
}
|
|
564
|
-
reject(GENERIC_ERROR, err.localizedDescription, error)
|
|
377
|
+
reject(GENERIC_ERROR, err.localizedDescription, error)
|
|
565
378
|
}
|
|
566
|
-
return
|
|
379
|
+
return
|
|
567
380
|
}
|
|
568
|
-
return resolve(success)
|
|
381
|
+
return resolve(success)
|
|
569
382
|
}
|
|
570
|
-
reject(GENERIC_ERROR, err.localizedDescription, error)
|
|
383
|
+
reject(GENERIC_ERROR, err.localizedDescription, error)
|
|
571
384
|
}
|
|
572
385
|
|
|
573
|
-
|
|
574
386
|
}
|
|
575
387
|
|
|
576
388
|
@objc(saveCategorySample:value:start:end:metadata:resolve:reject:)
|
|
577
|
-
func saveCategorySample(typeIdentifier: String, value: Double, start: Date, end: Date, metadata: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock){
|
|
389
|
+
func saveCategorySample(typeIdentifier: String, value: Double, start: Date, end: Date, metadata: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
578
390
|
guard let store = _store else {
|
|
579
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
391
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
580
392
|
}
|
|
581
393
|
|
|
582
|
-
let identifier = HKCategoryTypeIdentifier.init(rawValue: typeIdentifier)
|
|
394
|
+
let identifier = HKCategoryTypeIdentifier.init(rawValue: typeIdentifier)
|
|
583
395
|
|
|
584
396
|
guard let type = HKObjectType.categoryType(forIdentifier: identifier) else {
|
|
585
|
-
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
397
|
+
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
586
398
|
}
|
|
587
399
|
|
|
588
|
-
let sample = HKCategorySample.init(type: type, value: Int(value), start: start, end: end, metadata: metadata as?
|
|
400
|
+
let sample = HKCategorySample.init(type: type, value: Int(value), start: start, end: end, metadata: metadata as? [String: Any])
|
|
589
401
|
|
|
590
402
|
store.save(sample) { (success: Bool, error: Error?) in
|
|
591
403
|
guard let err = error else {
|
|
592
|
-
return resolve(success)
|
|
404
|
+
return resolve(success)
|
|
593
405
|
}
|
|
594
|
-
reject(GENERIC_ERROR, err.localizedDescription, error)
|
|
406
|
+
reject(GENERIC_ERROR, err.localizedDescription, error)
|
|
595
407
|
}
|
|
596
408
|
}
|
|
597
409
|
|
|
@@ -600,508 +412,337 @@ class ReactNativeHealthkit: RCTEventEmitter {
|
|
|
600
412
|
}
|
|
601
413
|
|
|
602
414
|
@objc(enableBackgroundDelivery:updateFrequency:resolve:reject:)
|
|
603
|
-
func enableBackgroundDelivery(typeIdentifier: String, updateFrequency: Int, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock){
|
|
415
|
+
func enableBackgroundDelivery(typeIdentifier: String, updateFrequency: Int, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
604
416
|
guard let store = _store else {
|
|
605
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
417
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
606
418
|
}
|
|
607
419
|
|
|
608
420
|
guard let sampleType = objectTypeFromString(typeIdentifier: typeIdentifier) else {
|
|
609
|
-
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
421
|
+
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
610
422
|
}
|
|
611
423
|
|
|
612
424
|
guard let frequency = HKUpdateFrequency.init(rawValue: updateFrequency) else {
|
|
613
|
-
return reject("UpdateFrequency not valid", "UpdateFrequency not valid", nil)
|
|
425
|
+
return reject("UpdateFrequency not valid", "UpdateFrequency not valid", nil)
|
|
614
426
|
}
|
|
615
427
|
|
|
616
|
-
store.enableBackgroundDelivery(for: sampleType, frequency:frequency ) { (success, error) in
|
|
428
|
+
store.enableBackgroundDelivery(for: sampleType, frequency: frequency ) { (success, error) in
|
|
617
429
|
guard let err = error else {
|
|
618
|
-
return resolve(success)
|
|
430
|
+
return resolve(success)
|
|
619
431
|
}
|
|
620
|
-
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
432
|
+
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
621
433
|
}
|
|
622
434
|
}
|
|
623
435
|
|
|
624
436
|
@objc(disableAllBackgroundDelivery:reject:)
|
|
625
|
-
func disableAllBackgroundDelivery(resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock){
|
|
437
|
+
func disableAllBackgroundDelivery(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
626
438
|
guard let store = _store else {
|
|
627
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
439
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
628
440
|
}
|
|
629
441
|
|
|
630
442
|
store.disableAllBackgroundDelivery(completion: { (success, error) in
|
|
631
443
|
guard let err = error else {
|
|
632
|
-
return resolve(success)
|
|
444
|
+
return resolve(success)
|
|
633
445
|
}
|
|
634
|
-
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
446
|
+
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
635
447
|
})
|
|
636
448
|
}
|
|
637
449
|
|
|
638
450
|
@objc(disableBackgroundDelivery:resolve:reject:)
|
|
639
|
-
func disableBackgroundDelivery(typeIdentifier: String, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock){
|
|
451
|
+
func disableBackgroundDelivery(typeIdentifier: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
640
452
|
guard let store = _store else {
|
|
641
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
453
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
642
454
|
}
|
|
643
455
|
|
|
644
456
|
guard let sampleType = objectTypeFromString(typeIdentifier: typeIdentifier) else {
|
|
645
|
-
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
457
|
+
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
646
458
|
}
|
|
647
459
|
|
|
648
|
-
|
|
649
460
|
store.disableBackgroundDelivery(for: sampleType) { (success, error) in
|
|
650
461
|
guard let err = error else {
|
|
651
|
-
return resolve(success)
|
|
462
|
+
return resolve(success)
|
|
652
463
|
}
|
|
653
|
-
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
464
|
+
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
654
465
|
}
|
|
655
466
|
}
|
|
656
467
|
|
|
657
468
|
@objc(subscribeToObserverQuery:resolve:reject:)
|
|
658
|
-
func subscribeToObserverQuery(typeIdentifier: String, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock){
|
|
469
|
+
func subscribeToObserverQuery(typeIdentifier: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
659
470
|
guard let store = _store else {
|
|
660
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
471
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
661
472
|
}
|
|
662
473
|
|
|
663
474
|
guard let sampleType = sampleTypeFromString(typeIdentifier: typeIdentifier) else {
|
|
664
|
-
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
475
|
+
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
665
476
|
}
|
|
666
477
|
|
|
667
478
|
let predicate = HKQuery.predicateForSamples(withStart: Date.init(), end: nil, options: HKQueryOptions.strictStartDate)
|
|
668
479
|
|
|
669
480
|
let queryId = UUID().uuidString
|
|
670
481
|
|
|
671
|
-
func responder(query: HKObserverQuery, handler: @escaping HKObserverQueryCompletionHandler, error: Error?)
|
|
672
|
-
if
|
|
482
|
+
func responder(query: HKObserverQuery, handler: @escaping HKObserverQueryCompletionHandler, error: Error?) {
|
|
483
|
+
if error == nil {
|
|
673
484
|
DispatchQueue.main.async {
|
|
674
|
-
if
|
|
485
|
+
if self.bridge != nil && self.bridge.isValid {
|
|
675
486
|
self.sendEvent(withName: "onChange", body: [
|
|
676
|
-
"typeIdentifier": typeIdentifier
|
|
677
|
-
])
|
|
487
|
+
"typeIdentifier": typeIdentifier
|
|
488
|
+
])
|
|
678
489
|
}
|
|
679
490
|
|
|
680
491
|
}
|
|
681
|
-
handler()
|
|
492
|
+
handler()
|
|
682
493
|
}
|
|
683
494
|
}
|
|
684
495
|
|
|
685
496
|
let query = HKObserverQuery(sampleType: sampleType, predicate: predicate) { (query: HKObserverQuery, handler: @escaping HKObserverQueryCompletionHandler, error: Error?) in
|
|
686
497
|
guard let err = error else {
|
|
687
|
-
return responder(query: query, handler: handler, error: error)
|
|
498
|
+
return responder(query: query, handler: handler, error: error)
|
|
688
499
|
}
|
|
689
|
-
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
500
|
+
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
690
501
|
}
|
|
691
502
|
|
|
692
|
-
store.execute(query)
|
|
503
|
+
store.execute(query)
|
|
693
504
|
|
|
694
|
-
self._runningQueries.updateValue(query, forKey: queryId)
|
|
505
|
+
self._runningQueries.updateValue(query, forKey: queryId)
|
|
695
506
|
}
|
|
696
507
|
|
|
697
508
|
@objc(unsubscribeQuery:resolve:reject:)
|
|
698
|
-
func unsubscribeQuery(queryId: String, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) {
|
|
509
|
+
func unsubscribeQuery(queryId: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
699
510
|
guard let store = _store else {
|
|
700
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
511
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
701
512
|
}
|
|
702
513
|
|
|
703
514
|
guard let query = self._runningQueries[queryId] else {
|
|
704
|
-
reject("Error", "Query with id " + queryId + " not found", nil)
|
|
705
|
-
return
|
|
515
|
+
reject("Error", "Query with id " + queryId + " not found", nil)
|
|
516
|
+
return
|
|
706
517
|
}
|
|
707
518
|
|
|
708
|
-
store.stop(query)
|
|
519
|
+
store.stop(query)
|
|
709
520
|
|
|
710
|
-
self._runningQueries.removeValue(forKey: queryId)
|
|
521
|
+
self._runningQueries.removeValue(forKey: queryId)
|
|
711
522
|
|
|
712
|
-
resolve(true)
|
|
523
|
+
resolve(true)
|
|
713
524
|
}
|
|
714
525
|
|
|
715
|
-
|
|
716
526
|
static override func requiresMainQueueSetup() -> Bool {
|
|
717
527
|
return true
|
|
718
528
|
}
|
|
719
529
|
|
|
720
530
|
@objc(queryStatisticsForQuantity:unitString:from:to:options:resolve:reject:)
|
|
721
|
-
func queryStatisticsForQuantity(typeIdentifier: String, unitString: String, from: Date, to: Date, options: NSArray, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock)
|
|
531
|
+
func queryStatisticsForQuantity(typeIdentifier: String, unitString: String, from: Date, to: Date, options: NSArray, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
722
532
|
guard let store = _store else {
|
|
723
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
533
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
724
534
|
}
|
|
725
535
|
|
|
726
|
-
let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier)
|
|
536
|
+
let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier)
|
|
727
537
|
guard let quantityType = HKObjectType.quantityType(forIdentifier: identifier) else {
|
|
728
|
-
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
538
|
+
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
729
539
|
}
|
|
730
540
|
|
|
731
541
|
let predicate = HKQuery.predicateForSamples(withStart: from, end: to, options: HKQueryOptions.strictEndDate)
|
|
732
542
|
|
|
733
|
-
var opts = HKStatisticsOptions.init()
|
|
543
|
+
var opts = HKStatisticsOptions.init()
|
|
734
544
|
|
|
735
545
|
for o in options {
|
|
736
|
-
let str = o as! String
|
|
737
|
-
if
|
|
546
|
+
let str = o as! String
|
|
547
|
+
if str == "cumulativeSum" {
|
|
738
548
|
opts.insert(HKStatisticsOptions.cumulativeSum)
|
|
739
|
-
}
|
|
740
|
-
else if(str == "discreteAverage"){
|
|
549
|
+
} else if str == "discreteAverage" {
|
|
741
550
|
opts.insert(HKStatisticsOptions.discreteAverage)
|
|
742
|
-
}else if
|
|
551
|
+
} else if str == "discreteMax" {
|
|
743
552
|
opts.insert(HKStatisticsOptions.discreteMax)
|
|
744
|
-
}
|
|
745
|
-
else if(str == "discreteMin"){
|
|
553
|
+
} else if str == "discreteMin" {
|
|
746
554
|
opts.insert(HKStatisticsOptions.discreteMin)
|
|
747
555
|
}
|
|
748
556
|
if #available(iOS 12, *) {
|
|
749
|
-
if
|
|
557
|
+
if str == "discreteMostRecent" {
|
|
750
558
|
opts.insert(HKStatisticsOptions.discreteMostRecent)
|
|
751
559
|
}
|
|
752
560
|
}
|
|
753
561
|
if #available(iOS 13, *) {
|
|
754
|
-
if
|
|
562
|
+
if str == "duration" {
|
|
755
563
|
opts.insert(HKStatisticsOptions.duration)
|
|
756
564
|
}
|
|
757
|
-
if
|
|
565
|
+
if str == "mostRecent" {
|
|
758
566
|
opts.insert(HKStatisticsOptions.mostRecent)
|
|
759
567
|
}
|
|
760
568
|
}
|
|
761
569
|
|
|
762
|
-
if
|
|
570
|
+
if str == "separateBySource" {
|
|
763
571
|
opts.insert(HKStatisticsOptions.separateBySource)
|
|
764
572
|
}
|
|
765
573
|
}
|
|
766
574
|
|
|
767
|
-
let query = HKStatisticsQuery.init(quantityType: quantityType, quantitySamplePredicate: predicate, options: opts) { (
|
|
575
|
+
let query = HKStatisticsQuery.init(quantityType: quantityType, quantitySamplePredicate: predicate, options: opts) { (_, stats: HKStatistics?, _: Error?) in
|
|
768
576
|
if let gottenStats = stats {
|
|
769
|
-
var dic =
|
|
770
|
-
let unit = HKUnit.init(from: unitString)
|
|
577
|
+
var dic = [String: [String: Any]?]()
|
|
578
|
+
let unit = HKUnit.init(from: unitString)
|
|
771
579
|
if let averageQuantity = gottenStats.averageQuantity() {
|
|
772
|
-
dic.updateValue(
|
|
580
|
+
dic.updateValue(serializeQuantity(unit: unit, quantity: averageQuantity), forKey: "averageQuantity")
|
|
773
581
|
}
|
|
774
582
|
if let maximumQuantity = gottenStats.maximumQuantity() {
|
|
775
|
-
dic.updateValue(
|
|
583
|
+
dic.updateValue(serializeQuantity(unit: unit, quantity: maximumQuantity), forKey: "maximumQuantity")
|
|
776
584
|
}
|
|
777
585
|
if let minimumQuantity = gottenStats.minimumQuantity() {
|
|
778
|
-
dic.updateValue(
|
|
586
|
+
dic.updateValue(serializeQuantity(unit: unit, quantity: minimumQuantity), forKey: "minimumQuantity")
|
|
779
587
|
}
|
|
780
588
|
if let sumQuantity = gottenStats.sumQuantity() {
|
|
781
|
-
dic.updateValue(
|
|
589
|
+
dic.updateValue(serializeQuantity(unit: unit, quantity: sumQuantity), forKey: "sumQuantity")
|
|
782
590
|
}
|
|
783
591
|
if #available(iOS 12, *) {
|
|
784
592
|
if let mostRecent = gottenStats.mostRecentQuantity() {
|
|
785
|
-
dic.updateValue(
|
|
593
|
+
dic.updateValue(serializeQuantity(unit: unit, quantity: mostRecent), forKey: "mostRecentQuantity")
|
|
786
594
|
}
|
|
787
595
|
|
|
788
596
|
if let mostRecentDateInterval = gottenStats.mostRecentQuantityDateInterval() {
|
|
789
597
|
dic.updateValue([
|
|
790
598
|
"start": self._dateFormatter.string(from: mostRecentDateInterval.start),
|
|
791
|
-
"end": self._dateFormatter.string(from: mostRecentDateInterval.end)
|
|
599
|
+
"end": self._dateFormatter.string(from: mostRecentDateInterval.end)
|
|
792
600
|
], forKey: "mostRecentQuantityDateInterval")
|
|
793
601
|
}
|
|
794
602
|
}
|
|
795
603
|
if #available(iOS 13, *) {
|
|
796
|
-
let durationUnit = HKUnit.second()
|
|
604
|
+
let durationUnit = HKUnit.second()
|
|
797
605
|
if let duration = gottenStats.duration() {
|
|
798
|
-
dic.updateValue(
|
|
606
|
+
dic.updateValue(serializeQuantity(unit: durationUnit, quantity: duration), forKey: "duration")
|
|
799
607
|
}
|
|
800
608
|
}
|
|
801
609
|
|
|
802
|
-
resolve(dic)
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
store.execute(query);
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
func serializeUnknownQuantity(quantity: HKQuantity) -> Dictionary<String, Any>? {
|
|
810
|
-
if(quantity.is(compatibleWith: HKUnit.percent())){
|
|
811
|
-
return self.serializeQuantity(unit: HKUnit.percent(), quantity: quantity);
|
|
812
|
-
}
|
|
813
|
-
|
|
814
|
-
if(quantity.is(compatibleWith: HKUnit.second())){
|
|
815
|
-
return self.serializeQuantity(unit: HKUnit.second(), quantity: quantity);
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
if(quantity.is(compatibleWith: HKUnit.kilocalorie())){
|
|
819
|
-
return self.serializeQuantity(unit: HKUnit.kilocalorie(), quantity: quantity);
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
if(quantity.is(compatibleWith: HKUnit.count())){
|
|
823
|
-
return self.serializeQuantity(unit: HKUnit.count(), quantity: quantity)
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
if(quantity.is(compatibleWith: HKUnit.meter())){
|
|
827
|
-
return self.serializeQuantity(unit: HKUnit.meter(), quantity: quantity)
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
if #available(iOS 11, *) {
|
|
831
|
-
if(quantity.is(compatibleWith: HKUnit.internationalUnit())){
|
|
832
|
-
return self.serializeQuantity(unit: HKUnit.internationalUnit(), quantity: quantity);
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
if #available(iOS 13, *) {
|
|
837
|
-
if(quantity.is(compatibleWith: HKUnit.hertz())){
|
|
838
|
-
return self.serializeQuantity(unit: HKUnit.hertz(), quantity: quantity);
|
|
839
|
-
}
|
|
840
|
-
if(quantity.is(compatibleWith: HKUnit.decibelHearingLevel())){
|
|
841
|
-
return self.serializeQuantity(unit: HKUnit.decibelHearingLevel(), quantity: quantity);
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
if(quantity.is(compatibleWith: SpeedUnit)){
|
|
846
|
-
return self.serializeQuantity(unit: SpeedUnit, quantity: quantity);
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
if(quantity.is(compatibleWith: METUnit)){
|
|
850
|
-
return self.serializeQuantity(unit: METUnit, quantity: quantity);
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
return nil;
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
func serializeMetadata(metadata: [String: Any]?) -> NSDictionary {
|
|
857
|
-
let serialized: NSMutableDictionary = [:];
|
|
858
|
-
if let m = metadata {
|
|
859
|
-
for item in m {
|
|
860
|
-
if let bool = item.value as? Bool {
|
|
861
|
-
serialized.setValue(bool, forKey: item.key)
|
|
862
|
-
}
|
|
863
|
-
if let str = item.value as? String {
|
|
864
|
-
serialized.setValue(str, forKey: item.key)
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
if let double = item.value as? Double {
|
|
868
|
-
serialized.setValue(double, forKey: item.key)
|
|
869
|
-
}
|
|
870
|
-
if let quantity = item.value as? HKQuantity {
|
|
871
|
-
if let s = serializeUnknownQuantity(quantity: quantity) {
|
|
872
|
-
serialized.setValue(s, forKey: item.key)
|
|
873
|
-
}
|
|
874
|
-
}
|
|
610
|
+
resolve(dic)
|
|
875
611
|
}
|
|
876
612
|
}
|
|
877
|
-
return serialized;
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
func serializeDevice(_device: HKDevice?) -> Dictionary<String, String?>? {
|
|
881
|
-
guard let device = _device else {
|
|
882
|
-
return nil;
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
return [
|
|
886
|
-
"name": device.name,
|
|
887
|
-
"firmwareVersion": device.firmwareVersion,
|
|
888
|
-
"hardwareVersion": device.hardwareVersion,
|
|
889
|
-
"localIdentifier": device.localIdentifier,
|
|
890
|
-
"manufacturer": device.manufacturer,
|
|
891
|
-
"model": device.model,
|
|
892
|
-
"softwareVersion": device.softwareVersion,
|
|
893
|
-
"udiDeviceIdentifier": device.udiDeviceIdentifier
|
|
894
|
-
]
|
|
895
|
-
}
|
|
896
|
-
|
|
897
|
-
func serializeOperatingSystemVersion(_version: OperatingSystemVersion?) -> String? {
|
|
898
|
-
guard let version = _version else {
|
|
899
|
-
return nil;
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
let versionString = "\(version.majorVersion).\(version.minorVersion).\(version.patchVersion)";
|
|
903
|
-
|
|
904
|
-
return versionString;
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
func serializeSourceRevision(_sourceRevision: HKSourceRevision?) -> Dictionary<String, Any?>? {
|
|
908
|
-
guard let sourceRevision = _sourceRevision else {
|
|
909
|
-
return nil;
|
|
910
|
-
}
|
|
911
|
-
|
|
912
|
-
var dict = [
|
|
913
|
-
"source": [
|
|
914
|
-
"name": sourceRevision.source.name,
|
|
915
|
-
"bundleIdentifier": sourceRevision.source.bundleIdentifier
|
|
916
|
-
],
|
|
917
|
-
"version": sourceRevision.version as Any
|
|
918
|
-
] as [String : Any];
|
|
919
613
|
|
|
920
|
-
|
|
921
|
-
dict["operatingSystemVersion"] = self.serializeOperatingSystemVersion(_version: sourceRevision.operatingSystemVersion);
|
|
922
|
-
dict["productType"] = sourceRevision.productType;
|
|
923
|
-
}
|
|
924
|
-
|
|
925
|
-
return dict;
|
|
614
|
+
store.execute(query)
|
|
926
615
|
}
|
|
927
616
|
|
|
928
617
|
@objc(queryWorkoutSamples:distanceUnitString:from:to:limit:ascending:resolve:reject:)
|
|
929
|
-
func queryWorkoutSamples(energyUnitString: String, distanceUnitString: String, from: Date, to: Date, limit: Int, ascending: Bool, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock)
|
|
618
|
+
func queryWorkoutSamples(energyUnitString: String, distanceUnitString: String, from: Date, to: Date, limit: Int, ascending: Bool, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
930
619
|
guard let store = _store else {
|
|
931
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
620
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
932
621
|
}
|
|
933
622
|
|
|
934
|
-
let from =
|
|
935
|
-
let to =
|
|
623
|
+
let from = dateOrNilIfZero(date: from)
|
|
624
|
+
let to = dateOrNilIfZero(date: to)
|
|
936
625
|
|
|
937
|
-
let predicate = from
|
|
626
|
+
let predicate = createPredicate(from: from, to: to)
|
|
938
627
|
|
|
939
|
-
let limit = limit
|
|
628
|
+
let limit = limitOrNilIfZero(limit: limit)
|
|
940
629
|
|
|
941
630
|
let energyUnit = HKUnit.init(from: energyUnitString)
|
|
942
631
|
let distanceUnit = HKUnit.init(from: distanceUnitString)
|
|
943
632
|
|
|
944
|
-
let q = HKSampleQuery(sampleType: .workoutType(), predicate: predicate, limit: limit, sortDescriptors:
|
|
633
|
+
let q = HKSampleQuery(sampleType: .workoutType(), predicate: predicate, limit: limit, sortDescriptors: getSortDescriptors(ascending: ascending)) { (_: HKSampleQuery, sample: [HKSample]?, error: Error?) in
|
|
945
634
|
guard let err = error else {
|
|
946
635
|
guard let samples = sample else {
|
|
947
|
-
return resolve([])
|
|
636
|
+
return resolve([])
|
|
948
637
|
}
|
|
949
|
-
let arr: NSMutableArray = []
|
|
638
|
+
let arr: NSMutableArray = []
|
|
950
639
|
|
|
951
640
|
for s in samples {
|
|
952
641
|
if let workout = s as? HKWorkout {
|
|
953
642
|
let endDate = self._dateFormatter.string(from: workout.endDate)
|
|
954
|
-
let startDate = self._dateFormatter.string(from: workout.startDate)
|
|
643
|
+
let startDate = self._dateFormatter.string(from: workout.startDate)
|
|
955
644
|
|
|
956
645
|
let dict: NSMutableDictionary = [
|
|
957
646
|
"uuid": workout.uuid.uuidString,
|
|
958
|
-
"device":
|
|
647
|
+
"device": serializeDevice(_device: workout.device) as Any,
|
|
959
648
|
"duration": workout.duration,
|
|
960
|
-
"totalDistance":
|
|
961
|
-
"totalEnergyBurned":
|
|
962
|
-
"totalSwimmingStrokeCount":
|
|
649
|
+
"totalDistance": serializeQuantity(unit: distanceUnit, quantity: workout.totalDistance) as Any,
|
|
650
|
+
"totalEnergyBurned": serializeQuantity(unit: energyUnit, quantity: workout.totalEnergyBurned) as Any,
|
|
651
|
+
"totalSwimmingStrokeCount": serializeQuantity(unit: HKUnit.count(), quantity: workout.totalSwimmingStrokeCount) as Any,
|
|
963
652
|
"workoutActivityType": workout.workoutActivityType.rawValue,
|
|
964
653
|
"startDate": startDate,
|
|
965
654
|
"endDate": endDate,
|
|
966
|
-
"metadata":
|
|
967
|
-
"sourceRevision":
|
|
655
|
+
"metadata": serializeMetadata(metadata: workout.metadata),
|
|
656
|
+
"sourceRevision": serializeSourceRevision(_sourceRevision: workout.sourceRevision) as Any
|
|
968
657
|
]
|
|
969
658
|
|
|
970
659
|
if #available(iOS 11, *) {
|
|
971
|
-
dict.setValue(
|
|
660
|
+
dict.setValue(serializeQuantity(unit: HKUnit.count(), quantity: workout.totalFlightsClimbed), forKey: "totalFlightsClimbed")
|
|
972
661
|
}
|
|
973
662
|
|
|
974
663
|
arr.add(dict)
|
|
975
664
|
}
|
|
976
665
|
}
|
|
977
666
|
|
|
978
|
-
return resolve(arr)
|
|
667
|
+
return resolve(arr)
|
|
979
668
|
}
|
|
980
|
-
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
669
|
+
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
981
670
|
}
|
|
982
671
|
|
|
983
|
-
store.execute(q)
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
func serializeAnchor(anchor: HKQueryAnchor?) -> String? {
|
|
987
|
-
guard let anch = anchor else {
|
|
988
|
-
return nil
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
let data = NSKeyedArchiver.archivedData(withRootObject: anch)
|
|
992
|
-
let encoded = data.base64EncodedString();
|
|
993
|
-
|
|
994
|
-
return encoded;
|
|
995
|
-
}
|
|
996
|
-
|
|
997
|
-
func base64StringToHKQueryAnchor(base64String: String) -> HKQueryAnchor? {
|
|
998
|
-
// Step 1: Decode the base64 string to a Data object
|
|
999
|
-
guard let data = Data(base64Encoded: base64String) else {
|
|
1000
|
-
print("Error: Invalid base64 string")
|
|
1001
|
-
return nil
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
// Step 2: Use NSKeyedUnarchiver to unarchive the data and create an HKQueryAnchor object
|
|
1005
|
-
do {
|
|
1006
|
-
let unarchiver = try NSKeyedUnarchiver(forReadingFrom: data)
|
|
1007
|
-
unarchiver.requiresSecureCoding = true
|
|
1008
|
-
let anchor = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data)
|
|
1009
|
-
|
|
1010
|
-
return anchor as? HKQueryAnchor
|
|
1011
|
-
} catch {
|
|
1012
|
-
print("Error: Unable to unarchive HKQueryAnchor object: \(error)")
|
|
1013
|
-
return nil
|
|
672
|
+
store.execute(q)
|
|
1014
673
|
}
|
|
1015
|
-
}
|
|
1016
674
|
|
|
1017
|
-
@objc(queryQuantitySamples:unitString:from:to:limit:ascending:
|
|
675
|
+
@objc(queryQuantitySamples:unitString:from:to:limit:ascending:resolve:reject:)
|
|
1018
676
|
func queryQuantitySamples(
|
|
1019
|
-
typeIdentifier: String,
|
|
1020
|
-
unitString: String,
|
|
1021
|
-
from: Date,
|
|
1022
|
-
to: Date,
|
|
1023
|
-
limit: Int,
|
|
1024
|
-
ascending: Bool,
|
|
1025
|
-
anchor: String,
|
|
677
|
+
typeIdentifier: String,
|
|
678
|
+
unitString: String,
|
|
679
|
+
from: Date,
|
|
680
|
+
to: Date,
|
|
681
|
+
limit: Int,
|
|
682
|
+
ascending: Bool,
|
|
1026
683
|
resolve: @escaping RCTPromiseResolveBlock,
|
|
1027
684
|
reject: @escaping RCTPromiseRejectBlock
|
|
1028
|
-
)
|
|
685
|
+
) {
|
|
1029
686
|
guard let store = _store else {
|
|
1030
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
687
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
1031
688
|
}
|
|
1032
689
|
|
|
1033
|
-
let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier)
|
|
690
|
+
let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier)
|
|
1034
691
|
guard let sampleType = HKSampleType.quantityType(forIdentifier: identifier) else {
|
|
1035
|
-
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
692
|
+
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
1036
693
|
}
|
|
1037
694
|
|
|
1038
|
-
let from =
|
|
1039
|
-
let to =
|
|
695
|
+
let from = dateOrNilIfZero(date: from)
|
|
696
|
+
let to = dateOrNilIfZero(date: to)
|
|
697
|
+
let predicate = createPredicate(from: from, to: to)
|
|
698
|
+
let limit = limitOrNilIfZero(limit: limit)
|
|
1040
699
|
|
|
1041
|
-
let
|
|
700
|
+
let q = HKSampleQuery(sampleType: sampleType, predicate: predicate, limit: limit, sortDescriptors: getSortDescriptors(ascending: ascending)) { (_: HKSampleQuery, sample: [HKSample]?, error: Error?) in
|
|
701
|
+
guard let err = error else {
|
|
702
|
+
guard let samples = sample else {
|
|
703
|
+
return resolve([])
|
|
704
|
+
}
|
|
705
|
+
let arr: NSMutableArray = []
|
|
1042
706
|
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
let q = HKAnchoredObjectQuery(
|
|
1048
|
-
type: sampleType,
|
|
1049
|
-
predicate: predicate,
|
|
1050
|
-
anchor: actualAnchor,
|
|
1051
|
-
limit: limit
|
|
1052
|
-
) { (
|
|
1053
|
-
query: HKAnchoredObjectQuery,
|
|
1054
|
-
s: [HKSample]?,
|
|
1055
|
-
deletedSamples: [HKDeletedObject]?,
|
|
1056
|
-
newAnchor: HKQueryAnchor?,
|
|
1057
|
-
error: Error?
|
|
1058
|
-
) in
|
|
1059
|
-
guard let err = error else {
|
|
1060
|
-
guard let samples = s else {
|
|
1061
|
-
return resolve([]);
|
|
1062
|
-
}
|
|
707
|
+
for s in samples {
|
|
708
|
+
if let sample = s as? HKQuantitySample {
|
|
709
|
+
let serialized = serializeQuantitySample(sample: sample, unit: HKUnit.init(from: unitString))
|
|
1063
710
|
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
711
|
+
arr.add(serialized)
|
|
712
|
+
}
|
|
713
|
+
}
|
|
1067
714
|
|
|
1068
|
-
return
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
return self.serializeDeletedSample(sample: sample)
|
|
1072
|
-
}) as Any,
|
|
1073
|
-
"newAnchor": self.serializeAnchor(anchor: newAnchor) as Any
|
|
1074
|
-
]);
|
|
1075
|
-
}
|
|
1076
|
-
reject(GENERIC_ERROR, err.localizedDescription, err);
|
|
715
|
+
return resolve(arr)
|
|
716
|
+
}
|
|
717
|
+
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
1077
718
|
}
|
|
1078
719
|
|
|
1079
|
-
store.execute(q)
|
|
720
|
+
store.execute(q)
|
|
1080
721
|
}
|
|
1081
722
|
|
|
1082
723
|
@objc(queryCorrelationSamples:from:to:resolve:reject:)
|
|
1083
|
-
func queryCorrelationSamples(typeIdentifier: String, from: Date, to: Date, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock)
|
|
724
|
+
func queryCorrelationSamples(typeIdentifier: String, from: Date, to: Date, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1084
725
|
guard let store = _store else {
|
|
1085
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
726
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
1086
727
|
}
|
|
1087
728
|
|
|
1088
|
-
let identifier = HKCorrelationTypeIdentifier.init(rawValue: typeIdentifier)
|
|
729
|
+
let identifier = HKCorrelationTypeIdentifier.init(rawValue: typeIdentifier)
|
|
1089
730
|
guard let sampleType = HKSampleType.correlationType(forIdentifier: identifier) else {
|
|
1090
|
-
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
731
|
+
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
1091
732
|
}
|
|
1092
733
|
|
|
1093
|
-
let from = from.timeIntervalSince1970 >= 0 ? from : nil
|
|
1094
|
-
let to = to.timeIntervalSince1970 >= 0 ? to : nil
|
|
734
|
+
let from = from.timeIntervalSince1970 >= 0 ? from : nil
|
|
735
|
+
let to = to.timeIntervalSince1970 >= 0 ? to : nil
|
|
1095
736
|
|
|
1096
|
-
let predicate = from
|
|
737
|
+
let predicate = createPredicate(from: from, to: to)
|
|
1097
738
|
|
|
1098
|
-
let q = HKCorrelationQuery(type: sampleType, predicate: predicate, samplePredicates: nil) { (
|
|
739
|
+
let q = HKCorrelationQuery(type: sampleType, predicate: predicate, samplePredicates: nil) { (_: HKCorrelationQuery, _correlations: [HKCorrelation]?, error: Error?) in
|
|
1099
740
|
guard let err = error else {
|
|
1100
741
|
guard let correlations = _correlations else {
|
|
1101
|
-
return resolve([])
|
|
742
|
+
return resolve([])
|
|
1102
743
|
}
|
|
1103
744
|
|
|
1104
|
-
var qts = Set<HKQuantityType>()
|
|
745
|
+
var qts = Set<HKQuantityType>()
|
|
1105
746
|
for c in correlations {
|
|
1106
747
|
for object in c.objects {
|
|
1107
748
|
if let quantitySample = object as? HKQuantitySample {
|
|
@@ -1109,67 +750,166 @@ class ReactNativeHealthkit: RCTEventEmitter {
|
|
|
1109
750
|
}
|
|
1110
751
|
}
|
|
1111
752
|
}
|
|
1112
|
-
return store.preferredUnits(for: qts) { (map: [HKQuantityType
|
|
753
|
+
return store.preferredUnits(for: qts) { (map: [HKQuantityType: HKUnit], error: Error?) in
|
|
1113
754
|
guard let e = error else {
|
|
1114
|
-
let collerationsToReturn: NSMutableArray = []
|
|
755
|
+
let collerationsToReturn: NSMutableArray = []
|
|
1115
756
|
for c in correlations {
|
|
1116
|
-
let objects = NSMutableArray()
|
|
757
|
+
let objects = NSMutableArray()
|
|
1117
758
|
for o in c.objects {
|
|
1118
759
|
if let quantitySample = o as? HKQuantitySample {
|
|
1119
|
-
objects.add(
|
|
760
|
+
objects.add(serializeQuantitySample(sample: quantitySample, unit: map[quantitySample.quantityType]!))
|
|
1120
761
|
}
|
|
1121
762
|
if let categorySample = o as? HKCategorySample {
|
|
1122
|
-
objects.add(
|
|
763
|
+
objects.add(serializeCategorySample(sample: categorySample))
|
|
1123
764
|
}
|
|
1124
765
|
}
|
|
1125
766
|
|
|
1126
767
|
collerationsToReturn.add([
|
|
1127
768
|
"uuid": c.uuid.uuidString,
|
|
1128
|
-
"device":
|
|
769
|
+
"device": serializeDevice(_device: c.device) as Any,
|
|
1129
770
|
"correlationType": c.correlationType.identifier,
|
|
1130
771
|
"objects": objects,
|
|
1131
|
-
"metadata":
|
|
772
|
+
"metadata": serializeMetadata(metadata: c.metadata),
|
|
1132
773
|
"startDate": self._dateFormatter.string(from: c.startDate),
|
|
1133
|
-
"endDate": self._dateFormatter.string(from: c.endDate)
|
|
774
|
+
"endDate": self._dateFormatter.string(from: c.endDate)
|
|
1134
775
|
])
|
|
1135
776
|
}
|
|
1136
777
|
|
|
1137
|
-
return resolve(collerationsToReturn)
|
|
778
|
+
return resolve(collerationsToReturn)
|
|
1138
779
|
}
|
|
1139
|
-
reject(GENERIC_ERROR, e.localizedDescription, e)
|
|
780
|
+
reject(GENERIC_ERROR, e.localizedDescription, e)
|
|
1140
781
|
}
|
|
1141
782
|
}
|
|
1142
|
-
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
783
|
+
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
1143
784
|
}
|
|
1144
785
|
|
|
1145
|
-
store.execute(q)
|
|
786
|
+
store.execute(q)
|
|
1146
787
|
}
|
|
1147
788
|
|
|
1148
|
-
@objc(queryCategorySamples:from:to:limit:ascending:
|
|
1149
|
-
func queryCategorySamples(typeIdentifier: String, from: Date, to: Date, limit: Int, ascending: Bool,
|
|
789
|
+
@objc(queryCategorySamples:from:to:limit:ascending:resolve:reject:)
|
|
790
|
+
func queryCategorySamples(typeIdentifier: String, from: Date, to: Date, limit: Int, ascending: Bool, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1150
791
|
guard let store = _store else {
|
|
1151
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
792
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
1152
793
|
}
|
|
1153
794
|
|
|
1154
|
-
let identifier = HKCategoryTypeIdentifier.init(rawValue: typeIdentifier)
|
|
795
|
+
let identifier = HKCategoryTypeIdentifier.init(rawValue: typeIdentifier)
|
|
1155
796
|
guard let sampleType = HKSampleType.categoryType(forIdentifier: identifier) else {
|
|
1156
|
-
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
797
|
+
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
let from = dateOrNilIfZero(date: from)
|
|
801
|
+
let to = dateOrNilIfZero(date: to)
|
|
802
|
+
let predicate = createPredicate(from: from, to: to)
|
|
803
|
+
let limit = limitOrNilIfZero(limit: limit)
|
|
804
|
+
|
|
805
|
+
let q = HKSampleQuery(sampleType: sampleType, predicate: predicate, limit: limit, sortDescriptors: getSortDescriptors(ascending: ascending)) { (_: HKSampleQuery, sample: [HKSample]?, error: Error?) in
|
|
806
|
+
guard let err = error else {
|
|
807
|
+
guard let samples = sample else {
|
|
808
|
+
return resolve([])
|
|
809
|
+
}
|
|
810
|
+
let arr: NSMutableArray = []
|
|
811
|
+
|
|
812
|
+
for s in samples {
|
|
813
|
+
if let sample = s as? HKCategorySample {
|
|
814
|
+
let serialized = serializeCategorySample(sample: sample)
|
|
815
|
+
|
|
816
|
+
arr.add(serialized)
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
return resolve(arr)
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
store.execute(q)
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
@objc(queryQuantitySamplesWithAnchor:unitString:from:to:limit:anchor:resolve:reject:)
|
|
829
|
+
func queryQuantitySamplesWithAnchor(
|
|
830
|
+
typeIdentifier: String,
|
|
831
|
+
unitString: String,
|
|
832
|
+
from: Date,
|
|
833
|
+
to: Date,
|
|
834
|
+
limit: Int,
|
|
835
|
+
anchor: String,
|
|
836
|
+
resolve: @escaping RCTPromiseResolveBlock,
|
|
837
|
+
reject: @escaping RCTPromiseRejectBlock
|
|
838
|
+
) {
|
|
839
|
+
guard let store = _store else {
|
|
840
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier)
|
|
844
|
+
guard let sampleType = HKSampleType.quantityType(forIdentifier: identifier) else {
|
|
845
|
+
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
let from = dateOrNilIfZero(date: from)
|
|
849
|
+
let to = dateOrNilIfZero(date: to)
|
|
850
|
+
let predicate = createPredicate(from: from, to: to)
|
|
851
|
+
let limit = limitOrNilIfZero(limit: limit)
|
|
852
|
+
|
|
853
|
+
let actualAnchor = deserializeHKQueryAnchor(anchor: anchor)
|
|
854
|
+
|
|
855
|
+
let q = HKAnchoredObjectQuery(
|
|
856
|
+
type: sampleType,
|
|
857
|
+
predicate: predicate,
|
|
858
|
+
anchor: actualAnchor,
|
|
859
|
+
limit: limit
|
|
860
|
+
) { (
|
|
861
|
+
_: HKAnchoredObjectQuery,
|
|
862
|
+
s: [HKSample]?,
|
|
863
|
+
deletedSamples: [HKDeletedObject]?,
|
|
864
|
+
newAnchor: HKQueryAnchor?,
|
|
865
|
+
error: Error?
|
|
866
|
+
) in
|
|
867
|
+
guard let err = error else {
|
|
868
|
+
guard let samples = s else {
|
|
869
|
+
return resolve([])
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
return resolve([
|
|
873
|
+
"samples": samples.map({ sample in
|
|
874
|
+
let serialized = serializeQuantitySample(sample: sample as! HKQuantitySample, unit: HKUnit.init(from: unitString))
|
|
875
|
+
|
|
876
|
+
return serialized
|
|
877
|
+
}) as Any,
|
|
878
|
+
"deletedSamples": deletedSamples?.map({ sample in
|
|
879
|
+
return serializeDeletedSample(sample: sample)
|
|
880
|
+
}) as Any,
|
|
881
|
+
"newAnchor": serializeAnchor(anchor: newAnchor) as Any
|
|
882
|
+
])
|
|
883
|
+
}
|
|
884
|
+
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
store.execute(q)
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
@objc(queryCategorySamplesWithAnchor:from:to:limit:anchor:resolve:reject:)
|
|
891
|
+
func queryCategorySamplesWithAnchor(typeIdentifier: String, from: Date, to: Date, limit: Int, anchor: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
892
|
+
guard let store = _store else {
|
|
893
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
1157
894
|
}
|
|
1158
895
|
|
|
1159
|
-
let
|
|
1160
|
-
let
|
|
896
|
+
let identifier = HKCategoryTypeIdentifier.init(rawValue: typeIdentifier)
|
|
897
|
+
guard let sampleType = HKSampleType.categoryType(forIdentifier: identifier) else {
|
|
898
|
+
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
899
|
+
}
|
|
1161
900
|
|
|
1162
|
-
let
|
|
901
|
+
let from = dateOrNilIfZero(date: from)
|
|
902
|
+
let to = dateOrNilIfZero(date: to)
|
|
903
|
+
let predicate = createPredicate(from: from, to: to)
|
|
904
|
+
let limit = limitOrNilIfZero(limit: limit)
|
|
1163
905
|
|
|
1164
|
-
let limit = limit == 0 ? HKObjectQueryNoLimit : limit;
|
|
1165
|
-
|
|
1166
906
|
let q = HKAnchoredObjectQuery(
|
|
1167
907
|
type: sampleType,
|
|
1168
908
|
predicate: predicate,
|
|
1169
909
|
anchor: anchor != "" ? base64StringToHKQueryAnchor(base64String: anchor) : nil,
|
|
1170
910
|
limit: limit
|
|
1171
911
|
) { (
|
|
1172
|
-
|
|
912
|
+
_: HKAnchoredObjectQuery,
|
|
1173
913
|
s: [HKSample]?,
|
|
1174
914
|
deletedSamples: [HKDeletedObject]?,
|
|
1175
915
|
newAnchor: HKQueryAnchor?,
|
|
@@ -1177,14 +917,14 @@ class ReactNativeHealthkit: RCTEventEmitter {
|
|
|
1177
917
|
) in
|
|
1178
918
|
guard let err = error else {
|
|
1179
919
|
guard let samples = s else {
|
|
1180
|
-
return resolve([])
|
|
920
|
+
return resolve([])
|
|
1181
921
|
}
|
|
1182
|
-
|
|
1183
|
-
let arr: NSMutableArray = []
|
|
922
|
+
|
|
923
|
+
let arr: NSMutableArray = []
|
|
1184
924
|
|
|
1185
925
|
for s in samples {
|
|
1186
926
|
if let sample = s as? HKCategorySample {
|
|
1187
|
-
let serialized =
|
|
927
|
+
let serialized = serializeCategorySample(sample: sample)
|
|
1188
928
|
|
|
1189
929
|
arr.add(serialized)
|
|
1190
930
|
}
|
|
@@ -1193,73 +933,73 @@ class ReactNativeHealthkit: RCTEventEmitter {
|
|
|
1193
933
|
return resolve([
|
|
1194
934
|
"samples": arr,
|
|
1195
935
|
"deletedSamples": deletedSamples?.map({ sample in
|
|
1196
|
-
return
|
|
936
|
+
return serializeDeletedSample(sample: sample)
|
|
1197
937
|
}) as Any,
|
|
1198
|
-
"newAnchor":
|
|
1199
|
-
])
|
|
938
|
+
"newAnchor": serializeAnchor(anchor: newAnchor) as Any
|
|
939
|
+
])
|
|
1200
940
|
}
|
|
1201
|
-
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
941
|
+
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
1202
942
|
}
|
|
1203
943
|
|
|
1204
|
-
store.execute(q)
|
|
944
|
+
store.execute(q)
|
|
1205
945
|
}
|
|
1206
|
-
|
|
946
|
+
|
|
1207
947
|
@objc(querySources:resolve:reject:)
|
|
1208
|
-
func querySources(typeIdentifier: String, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock)
|
|
1209
|
-
|
|
948
|
+
func querySources(typeIdentifier: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
949
|
+
|
|
1210
950
|
guard let store = _store else {
|
|
1211
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
951
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
1212
952
|
}
|
|
1213
953
|
|
|
1214
954
|
guard let type = objectTypeFromString(typeIdentifier: typeIdentifier) else {
|
|
1215
|
-
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
955
|
+
return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
|
|
1216
956
|
}
|
|
1217
|
-
|
|
1218
|
-
let query = HKSourceQuery(sampleType: type as! HKSampleType, samplePredicate: nil) { (
|
|
957
|
+
|
|
958
|
+
let query = HKSourceQuery(sampleType: type as! HKSampleType, samplePredicate: nil) { (_: HKSourceQuery, source: Set<HKSource>?, error: Error?) in
|
|
1219
959
|
guard let err = error else {
|
|
1220
960
|
guard let sources = source else {
|
|
1221
|
-
return resolve([])
|
|
961
|
+
return resolve([])
|
|
1222
962
|
}
|
|
1223
|
-
let arr: NSMutableArray = []
|
|
963
|
+
let arr: NSMutableArray = []
|
|
1224
964
|
|
|
1225
965
|
for s in sources {
|
|
1226
966
|
if let source = s as? HKSource {
|
|
1227
|
-
let serialized =
|
|
967
|
+
let serialized = serializeSource(source: source)
|
|
1228
968
|
|
|
1229
969
|
arr.add(serialized)
|
|
1230
970
|
}
|
|
1231
971
|
}
|
|
1232
972
|
|
|
1233
|
-
return resolve(arr)
|
|
973
|
+
return resolve(arr)
|
|
1234
974
|
}
|
|
1235
|
-
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
1236
|
-
|
|
975
|
+
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
976
|
+
|
|
1237
977
|
}
|
|
1238
978
|
|
|
1239
|
-
store.execute(query)
|
|
979
|
+
store.execute(query)
|
|
1240
980
|
}
|
|
1241
981
|
|
|
1242
982
|
@objc(requestAuthorization:read:resolve:withRejecter:)
|
|
1243
|
-
func requestAuthorization(toShare: NSDictionary, read: NSDictionary, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock)
|
|
983
|
+
func requestAuthorization(toShare: NSDictionary, read: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
1244
984
|
guard let store = _store else {
|
|
1245
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
985
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
1246
986
|
}
|
|
1247
987
|
|
|
1248
|
-
let share = sampleTypesFromDictionary(typeIdentifiers: toShare)
|
|
1249
|
-
let toRead = objectTypesFromDictionary(typeIdentifiers: read)
|
|
988
|
+
let share = sampleTypesFromDictionary(typeIdentifiers: toShare)
|
|
989
|
+
let toRead = objectTypesFromDictionary(typeIdentifiers: read)
|
|
1250
990
|
|
|
1251
991
|
store.requestAuthorization(toShare: share, read: toRead) { (success: Bool, error: Error?) in
|
|
1252
992
|
guard let err = error else {
|
|
1253
|
-
return resolve(success)
|
|
993
|
+
return resolve(success)
|
|
1254
994
|
}
|
|
1255
|
-
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
995
|
+
reject(GENERIC_ERROR, err.localizedDescription, err)
|
|
1256
996
|
}
|
|
1257
997
|
}
|
|
1258
998
|
|
|
1259
999
|
@available(iOS 13.0.0, *)
|
|
1260
1000
|
func getWorkoutByID(store: HKHealthStore,
|
|
1261
1001
|
workoutUUID: UUID) async -> HKWorkout? {
|
|
1262
|
-
let workoutPredicate = HKQuery.predicateForObject(with: workoutUUID)
|
|
1002
|
+
let workoutPredicate = HKQuery.predicateForObject(with: workoutUUID)
|
|
1263
1003
|
|
|
1264
1004
|
let samples = try! await withCheckedThrowingContinuation {
|
|
1265
1005
|
(continuation: CheckedContinuation<[HKSample], Error>) in
|
|
@@ -1267,7 +1007,7 @@ class ReactNativeHealthkit: RCTEventEmitter {
|
|
|
1267
1007
|
predicate: workoutPredicate,
|
|
1268
1008
|
anchor: nil,
|
|
1269
1009
|
limit: 1) {
|
|
1270
|
-
(
|
|
1010
|
+
(_, samples, _, _, error) in
|
|
1271
1011
|
|
|
1272
1012
|
if let hasError = error {
|
|
1273
1013
|
continuation.resume(throwing: hasError)
|
|
@@ -1290,9 +1030,8 @@ class ReactNativeHealthkit: RCTEventEmitter {
|
|
|
1290
1030
|
return workouts.first ?? nil
|
|
1291
1031
|
}
|
|
1292
1032
|
|
|
1293
|
-
|
|
1294
1033
|
@available(iOS 13.0.0, *)
|
|
1295
|
-
func _getWorkoutRoutes(store: HKHealthStore, workoutUUID: UUID) async -> [HKWorkoutRoute]?{
|
|
1034
|
+
func _getWorkoutRoutes(store: HKHealthStore, workoutUUID: UUID) async -> [HKWorkoutRoute]? {
|
|
1296
1035
|
guard let workout = await getWorkoutByID(store: store, workoutUUID: workoutUUID) else {
|
|
1297
1036
|
return nil
|
|
1298
1037
|
}
|
|
@@ -1304,7 +1043,7 @@ class ReactNativeHealthkit: RCTEventEmitter {
|
|
|
1304
1043
|
predicate: workoutPredicate,
|
|
1305
1044
|
anchor: nil,
|
|
1306
1045
|
limit: HKObjectQueryNoLimit) {
|
|
1307
|
-
(
|
|
1046
|
+
(_, samples, _, _, error) in
|
|
1308
1047
|
|
|
1309
1048
|
if let hasError = error {
|
|
1310
1049
|
continuation.resume(throwing: hasError)
|
|
@@ -1334,7 +1073,7 @@ class ReactNativeHealthkit: RCTEventEmitter {
|
|
|
1334
1073
|
var allLocations: [CLLocation] = []
|
|
1335
1074
|
|
|
1336
1075
|
let query = HKWorkoutRouteQuery(route: route) {
|
|
1337
|
-
(
|
|
1076
|
+
(_, locationsOrNil, done, errorOrNil) in
|
|
1338
1077
|
|
|
1339
1078
|
if let error = errorOrNil {
|
|
1340
1079
|
continuation.resume(throwing: error)
|
|
@@ -1367,21 +1106,20 @@ class ReactNativeHealthkit: RCTEventEmitter {
|
|
|
1367
1106
|
return nil
|
|
1368
1107
|
}
|
|
1369
1108
|
for route in _routes {
|
|
1370
|
-
let routeMetadata =
|
|
1109
|
+
let routeMetadata = serializeMetadata(metadata: route.metadata) as! [String: Any]
|
|
1371
1110
|
let routeCLLocations = (await getRouteLocations(store: store, route: route))
|
|
1372
|
-
let routeLocations = routeCLLocations.enumerated().map{(i, loc) in serializeLocation(location: loc, previousLocation: i == 0 ? nil: routeCLLocations[i - 1])}
|
|
1373
|
-
let routeInfos:
|
|
1111
|
+
let routeLocations = routeCLLocations.enumerated().map {(i, loc) in serializeLocation(location: loc, previousLocation: i == 0 ? nil: routeCLLocations[i - 1])}
|
|
1112
|
+
let routeInfos: [String: Any] = ["locations": routeLocations]
|
|
1374
1113
|
allRoutes.append(routeInfos.merging(routeMetadata) { (current, _) in current })
|
|
1375
1114
|
}
|
|
1376
1115
|
return allRoutes
|
|
1377
1116
|
}
|
|
1378
1117
|
|
|
1379
|
-
func serializeLocation(location: CLLocation, previousLocation: CLLocation?) ->
|
|
1118
|
+
func serializeLocation(location: CLLocation, previousLocation: CLLocation?) -> [String: Any] {
|
|
1380
1119
|
var distance: CLLocationDistance?
|
|
1381
1120
|
if let previousLocation = previousLocation {
|
|
1382
1121
|
distance = location.distance(from: previousLocation)
|
|
1383
|
-
}
|
|
1384
|
-
else {
|
|
1122
|
+
} else {
|
|
1385
1123
|
distance = nil
|
|
1386
1124
|
}
|
|
1387
1125
|
return [
|
|
@@ -1402,7 +1140,7 @@ class ReactNativeHealthkit: RCTEventEmitter {
|
|
|
1402
1140
|
func getWorkoutRoutes(
|
|
1403
1141
|
workoutUUID: String,
|
|
1404
1142
|
resolve: @escaping RCTPromiseResolveBlock,
|
|
1405
|
-
reject: @escaping RCTPromiseRejectBlock){
|
|
1143
|
+
reject: @escaping RCTPromiseRejectBlock) {
|
|
1406
1144
|
|
|
1407
1145
|
guard let store = _store else {
|
|
1408
1146
|
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
@@ -1416,17 +1154,16 @@ class ReactNativeHealthkit: RCTEventEmitter {
|
|
|
1416
1154
|
do {
|
|
1417
1155
|
let locations = await getSerializedWorkoutLocations(store: store, workoutUUID: _workoutUUID)
|
|
1418
1156
|
resolve(locations)
|
|
1419
|
-
}
|
|
1420
|
-
catch {
|
|
1157
|
+
} catch {
|
|
1421
1158
|
reject("WORKOUT_LOCATION_ERROR", "Failed to retrieve workout locations", nil)
|
|
1422
1159
|
}
|
|
1423
1160
|
}
|
|
1424
1161
|
}
|
|
1425
1162
|
|
|
1426
|
-
typealias HKAnchoredObjectQueryResult = (samples: [HKSample], deletedSamples: [HKDeletedObject]?, newAnchor: HKQueryAnchor?)
|
|
1163
|
+
typealias HKAnchoredObjectQueryResult = (samples: [HKSample], deletedSamples: [HKDeletedObject]?, newAnchor: HKQueryAnchor?)
|
|
1427
1164
|
|
|
1428
1165
|
@available(iOS 13.0.0, *)
|
|
1429
|
-
func
|
|
1166
|
+
func _queryHeartbeatSeriesSamplesWithAnchor(
|
|
1430
1167
|
store: HKHealthStore,
|
|
1431
1168
|
predicate: NSPredicate?,
|
|
1432
1169
|
limit: Int,
|
|
@@ -1440,123 +1177,192 @@ class ReactNativeHealthkit: RCTEventEmitter {
|
|
|
1440
1177
|
anchor: anchor,
|
|
1441
1178
|
limit: limit
|
|
1442
1179
|
) { (
|
|
1443
|
-
|
|
1180
|
+
_: HKAnchoredObjectQuery,
|
|
1444
1181
|
s: [HKSample]?,
|
|
1445
1182
|
deletedSamples: [HKDeletedObject]?,
|
|
1446
1183
|
newAnchor: HKQueryAnchor?,
|
|
1447
1184
|
error: Error?
|
|
1448
1185
|
) in
|
|
1449
1186
|
if let err = error {
|
|
1450
|
-
continuation.resume(throwing: err)
|
|
1187
|
+
continuation.resume(throwing: err)
|
|
1451
1188
|
}
|
|
1452
1189
|
|
|
1453
1190
|
guard let samples = s else {
|
|
1454
|
-
fatalError("Should not fail")
|
|
1191
|
+
fatalError("Should not fail")
|
|
1455
1192
|
}
|
|
1456
|
-
|
|
1457
|
-
continuation.resume(returning: HKAnchoredObjectQueryResult(samples: samples, deletedSamples: deletedSamples, newAnchor: newAnchor))
|
|
1193
|
+
|
|
1194
|
+
continuation.resume(returning: HKAnchoredObjectQueryResult(samples: samples, deletedSamples: deletedSamples, newAnchor: newAnchor))
|
|
1458
1195
|
}
|
|
1459
|
-
|
|
1460
|
-
store.execute(query)
|
|
1196
|
+
|
|
1197
|
+
store.execute(query)
|
|
1461
1198
|
}
|
|
1462
1199
|
|
|
1463
|
-
return queryResult
|
|
1200
|
+
return queryResult
|
|
1464
1201
|
}
|
|
1465
1202
|
|
|
1466
1203
|
@available(iOS 13.0.0, *)
|
|
1467
1204
|
func getHeartbeatSeriesHeartbeats(store: HKHealthStore, sample: HKHeartbeatSeriesSample) async throws -> [Dictionary<String, Any>] {
|
|
1468
1205
|
let beatTimes = try await withCheckedThrowingContinuation {
|
|
1469
1206
|
(continuation: CheckedContinuation<[Dictionary<String, Any>], Error>) in
|
|
1470
|
-
var allBeats: [Dictionary<String, Any>] = []
|
|
1207
|
+
var allBeats: [Dictionary<String, Any>] = []
|
|
1471
1208
|
|
|
1472
1209
|
let query = HKHeartbeatSeriesQuery(heartbeatSeries: sample) { (
|
|
1473
|
-
|
|
1210
|
+
_: HKHeartbeatSeriesQuery,
|
|
1474
1211
|
timeSinceSeriesStart: TimeInterval,
|
|
1475
1212
|
precededByGap: Bool,
|
|
1476
1213
|
done: Bool,
|
|
1477
1214
|
error: Error?
|
|
1478
1215
|
) in
|
|
1479
1216
|
if let err = error {
|
|
1480
|
-
continuation.resume(throwing: err)
|
|
1217
|
+
continuation.resume(throwing: err)
|
|
1481
1218
|
}
|
|
1482
1219
|
|
|
1483
|
-
let timeDict:
|
|
1220
|
+
let timeDict: [String: Any] = [
|
|
1484
1221
|
"timeSinceSeriesStart": timeSinceSeriesStart,
|
|
1485
1222
|
"precededByGap": precededByGap
|
|
1486
|
-
]
|
|
1487
|
-
|
|
1488
|
-
allBeats.append(timeDict)
|
|
1223
|
+
]
|
|
1224
|
+
|
|
1225
|
+
allBeats.append(timeDict)
|
|
1489
1226
|
|
|
1490
1227
|
if done {
|
|
1491
|
-
continuation.resume(returning: allBeats)
|
|
1228
|
+
continuation.resume(returning: allBeats)
|
|
1492
1229
|
}
|
|
1493
1230
|
}
|
|
1494
|
-
|
|
1495
|
-
store.execute(query)
|
|
1231
|
+
|
|
1232
|
+
store.execute(query)
|
|
1496
1233
|
}
|
|
1497
|
-
|
|
1498
|
-
return beatTimes
|
|
1234
|
+
|
|
1235
|
+
return beatTimes
|
|
1499
1236
|
}
|
|
1500
1237
|
|
|
1501
1238
|
@available(iOS 13.0.0, *)
|
|
1502
|
-
func getSerializedHeartbeatSeriesSample(store: HKHealthStore, sample: HKHeartbeatSeriesSample) async throws ->
|
|
1503
|
-
let sampleMetadata =
|
|
1504
|
-
let sampleHeartbeats = try await getHeartbeatSeriesHeartbeats(store: store, sample: sample)
|
|
1239
|
+
func getSerializedHeartbeatSeriesSample(store: HKHealthStore, sample: HKHeartbeatSeriesSample) async throws -> [String: Any] {
|
|
1240
|
+
let sampleMetadata = serializeMetadata(metadata: sample.metadata) as! [String: Any]
|
|
1241
|
+
let sampleHeartbeats = try await getHeartbeatSeriesHeartbeats(store: store, sample: sample)
|
|
1505
1242
|
|
|
1506
1243
|
return [
|
|
1507
1244
|
"uuid": sample.uuid.uuidString,
|
|
1508
|
-
"device":
|
|
1245
|
+
"device": serializeDevice(_device: sample.device) as Any,
|
|
1509
1246
|
"startDate": self._dateFormatter.string(from: sample.startDate),
|
|
1510
1247
|
"endDate": self._dateFormatter.string(from: sample.endDate),
|
|
1511
1248
|
"heartbeats": sampleHeartbeats as Any,
|
|
1512
|
-
"metadata":
|
|
1513
|
-
"sourceRevision":
|
|
1514
|
-
]
|
|
1249
|
+
"metadata": serializeMetadata(metadata: sample.metadata),
|
|
1250
|
+
"sourceRevision": serializeSourceRevision(_sourceRevision: sample.sourceRevision) as Any
|
|
1251
|
+
]
|
|
1515
1252
|
}
|
|
1516
1253
|
|
|
1517
1254
|
@available(iOS 13.0.0, *)
|
|
1518
|
-
@objc(
|
|
1519
|
-
func
|
|
1255
|
+
@objc(queryHeartbeatSeriesSamplesWithAnchor:to:limit:anchor:resolve:reject:)
|
|
1256
|
+
func queryHeartbeatSeriesSamplesWithAnchor(
|
|
1520
1257
|
from: Date,
|
|
1521
1258
|
to: Date,
|
|
1522
1259
|
limit: Int,
|
|
1523
|
-
ascending: Bool,
|
|
1524
1260
|
anchor: String,
|
|
1525
1261
|
resolve: @escaping RCTPromiseResolveBlock,
|
|
1526
1262
|
reject: @escaping RCTPromiseRejectBlock
|
|
1527
1263
|
) {
|
|
1528
1264
|
guard let store = _store else {
|
|
1529
|
-
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
1265
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
1530
1266
|
}
|
|
1531
1267
|
|
|
1532
1268
|
Task {
|
|
1533
1269
|
do {
|
|
1534
|
-
let from =
|
|
1535
|
-
let to =
|
|
1536
|
-
|
|
1537
|
-
let predicate = from
|
|
1538
|
-
|
|
1539
|
-
let limit = limit
|
|
1540
|
-
|
|
1541
|
-
let actualAnchor = anchor
|
|
1542
|
-
|
|
1543
|
-
let queryResult = try await
|
|
1544
|
-
|
|
1545
|
-
var allHeartbeatSamples: [Dictionary<String, Any>] = []
|
|
1270
|
+
let from = dateOrNilIfZero(date: from)
|
|
1271
|
+
let to = dateOrNilIfZero(date: to)
|
|
1272
|
+
|
|
1273
|
+
let predicate = createPredicate(from: from, to: to)
|
|
1274
|
+
|
|
1275
|
+
let limit = limitOrNilIfZero(limit: limit)
|
|
1276
|
+
|
|
1277
|
+
let actualAnchor = deserializeHKQueryAnchor(anchor: anchor)
|
|
1278
|
+
|
|
1279
|
+
let queryResult = try await _queryHeartbeatSeriesSamplesWithAnchor(store: store, predicate: predicate, limit: limit, anchor: actualAnchor)
|
|
1280
|
+
|
|
1281
|
+
var allHeartbeatSamples: [Dictionary<String, Any>] = []
|
|
1546
1282
|
for sample in queryResult.samples as! [HKHeartbeatSeriesSample] {
|
|
1547
|
-
allHeartbeatSamples.append(try await getSerializedHeartbeatSeriesSample(store: store, sample: sample))
|
|
1283
|
+
allHeartbeatSamples.append(try await getSerializedHeartbeatSeriesSample(store: store, sample: sample))
|
|
1548
1284
|
}
|
|
1549
|
-
|
|
1285
|
+
|
|
1550
1286
|
resolve([
|
|
1551
1287
|
"samples": allHeartbeatSamples as Any,
|
|
1552
1288
|
"deletedSamples": queryResult.deletedSamples?.map({ sample in
|
|
1553
1289
|
return serializeDeletedSample(sample: sample)
|
|
1554
1290
|
}) as Any,
|
|
1555
1291
|
"newAnchor": serializeAnchor(anchor: queryResult.newAnchor) as Any
|
|
1556
|
-
])
|
|
1292
|
+
])
|
|
1557
1293
|
} catch {
|
|
1558
|
-
reject(GENERIC_ERROR, error.localizedDescription, error)
|
|
1294
|
+
reject(GENERIC_ERROR, error.localizedDescription, error)
|
|
1559
1295
|
}
|
|
1560
1296
|
}
|
|
1561
1297
|
}
|
|
1298
|
+
|
|
1299
|
+
@available(iOS 13.0.0, *)
|
|
1300
|
+
func _queryHeartbeatSeriesSamples(
|
|
1301
|
+
store: HKHealthStore,
|
|
1302
|
+
predicate: NSPredicate?,
|
|
1303
|
+
limit: Int,
|
|
1304
|
+
ascending: Bool
|
|
1305
|
+
) async throws -> [HKSample] {
|
|
1306
|
+
let samples = try await withCheckedThrowingContinuation {
|
|
1307
|
+
(continuation: CheckedContinuation<[HKSample], Error>) in
|
|
1308
|
+
|
|
1309
|
+
let query = HKSampleQuery(
|
|
1310
|
+
sampleType: HKSeriesType.heartbeat(),
|
|
1311
|
+
predicate: predicate,
|
|
1312
|
+
limit: limit,
|
|
1313
|
+
sortDescriptors: [NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: ascending)]
|
|
1314
|
+
) { (_: HKSampleQuery, sample: [HKSample]?, error: Error?) in
|
|
1315
|
+
if let err = error {
|
|
1316
|
+
continuation.resume(throwing: err)
|
|
1317
|
+
} else {
|
|
1318
|
+
guard let actualSamples = sample else {
|
|
1319
|
+
fatalError("Should not fail")
|
|
1320
|
+
}
|
|
1321
|
+
continuation.resume(returning: actualSamples)
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
store.execute(query)
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
return samples
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
@available(iOS 13.0.0, *)
|
|
1332
|
+
@objc(queryHeartbeatSeriesSamples:to:limit:ascending:resolve:reject:)
|
|
1333
|
+
func queryHeartbeatSeriesSamples(
|
|
1334
|
+
from: Date,
|
|
1335
|
+
to: Date,
|
|
1336
|
+
limit: Int,
|
|
1337
|
+
ascending: Bool,
|
|
1338
|
+
resolve: @escaping RCTPromiseResolveBlock,
|
|
1339
|
+
reject: @escaping RCTPromiseRejectBlock
|
|
1340
|
+
) {
|
|
1341
|
+
guard let store = _store else {
|
|
1342
|
+
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
Task {
|
|
1346
|
+
do {
|
|
1347
|
+
let from = dateOrNilIfZero(date: from)
|
|
1348
|
+
let to = dateOrNilIfZero(date: to)
|
|
1349
|
+
|
|
1350
|
+
let predicate = createPredicate(from: from, to: to)
|
|
1351
|
+
|
|
1352
|
+
let limit = limitOrNilIfZero(limit: limit)
|
|
1353
|
+
|
|
1354
|
+
let samples = try await _queryHeartbeatSeriesSamples(store: store, predicate: predicate, limit: limit, ascending: ascending)
|
|
1355
|
+
|
|
1356
|
+
var allHeartbeatSamples: [Dictionary<String, Any>] = []
|
|
1357
|
+
for sample in samples as! [HKHeartbeatSeriesSample] {
|
|
1358
|
+
allHeartbeatSamples.append(try await getSerializedHeartbeatSeriesSample(store: store, sample: sample))
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
resolve(allHeartbeatSamples as Any)
|
|
1362
|
+
} catch {
|
|
1363
|
+
reject(GENERIC_ERROR, error.localizedDescription, error)
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1562
1368
|
}
|