@kingstinct/react-native-healthkit 8.1.1 → 8.3.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.
Files changed (42) hide show
  1. package/README.md +18 -4
  2. package/ios/Constants.swift +4 -0
  3. package/ios/Helpers.swift +81 -0
  4. package/ios/ReactNativeHealthkit.m +15 -0
  5. package/ios/ReactNativeHealthkit.swift +1680 -1209
  6. package/ios/Serializers.swift +18 -0
  7. package/lib/commonjs/index.ios.js +18 -0
  8. package/lib/commonjs/index.ios.js.map +1 -1
  9. package/lib/commonjs/index.native.js +15 -1
  10. package/lib/commonjs/index.native.js.map +1 -1
  11. package/lib/commonjs/native-types.js +14 -1
  12. package/lib/commonjs/native-types.js.map +1 -1
  13. package/lib/commonjs/test-setup.js +3 -1
  14. package/lib/commonjs/test-setup.js.map +1 -1
  15. package/lib/commonjs/utils/queryStatisticsCollectionForQuantity.js +16 -0
  16. package/lib/commonjs/utils/queryStatisticsCollectionForQuantity.js.map +1 -0
  17. package/lib/commonjs/utils/startWatchApp.js +11 -0
  18. package/lib/commonjs/utils/startWatchApp.js.map +1 -0
  19. package/lib/module/index.ios.js +6 -2
  20. package/lib/module/index.ios.js.map +1 -1
  21. package/lib/module/index.native.js +13 -1
  22. package/lib/module/index.native.js.map +1 -1
  23. package/lib/module/native-types.js +15 -0
  24. package/lib/module/native-types.js.map +1 -1
  25. package/lib/module/test-setup.js +3 -1
  26. package/lib/module/test-setup.js.map +1 -1
  27. package/lib/module/utils/queryStatisticsCollectionForQuantity.js +9 -0
  28. package/lib/module/utils/queryStatisticsCollectionForQuantity.js.map +1 -0
  29. package/lib/module/utils/startWatchApp.js +4 -0
  30. package/lib/module/utils/startWatchApp.js.map +1 -0
  31. package/lib/typescript/src/index.ios.d.ts +6 -2
  32. package/lib/typescript/src/index.native.d.ts +11 -3
  33. package/lib/typescript/src/native-types.d.ts +29 -1
  34. package/lib/typescript/src/utils/queryStatisticsCollectionForQuantity.d.ts +3 -0
  35. package/lib/typescript/src/utils/startWatchApp.d.ts +3 -0
  36. package/package.json +1 -1
  37. package/src/index.ios.tsx +7 -0
  38. package/src/index.native.tsx +16 -0
  39. package/src/native-types.ts +45 -1
  40. package/src/test-setup.ts +2 -0
  41. package/src/utils/queryStatisticsCollectionForQuantity.ts +38 -0
  42. package/src/utils/startWatchApp.ts +7 -0
package/README.md CHANGED
@@ -91,12 +91,26 @@ Some imperative examples:
91
91
  console.log(quantity) // 17.5
92
92
  console.log(unit) // %
93
93
 
94
- /* Listen to data */
95
94
  await HealthKit.requestAuthorization([HKQuantityTypeIdentifier.heartRate]); // request read permission for heart rate
96
95
 
97
- const unsubscribe = HealthKit.subscribeToChanges(HKQuantityTypeIdentifier.heartRate, () => {
98
- // refetch whichever queries you need
99
- });
96
+ /* Subscribe to data (Make sure to request permissions before subscribing to changes) */
97
+ const [hasRequestedAuthorization, setHasRequestedAuthorization] = useState(false);
98
+
99
+ useEffect(() => {
100
+ HealthKit.requestAuthorization([HKQuantityTypeIdentifier.heartRate]).then(() => {
101
+ setHasRequestedAuthorization(true);
102
+ });
103
+ }, []);
104
+
105
+ useEffect(() => {
106
+ if (hasRequestedAuthorization) {
107
+ const unsubscribe = HealthKit.subscribeToChanges(HKQuantityTypeIdentifier.heartRate, () => {
108
+ // refetch data as needed
109
+ });
110
+ }
111
+
112
+ return () => unsubscribe();
113
+ }, [hasRequestedAuthorization]);
100
114
 
101
115
  /* write data */
102
116
  await HealthKit.requestAuthorization([], [HKQuantityTypeIdentifier.insulinDelivery]); // request write permission for insulin delivery
@@ -11,6 +11,7 @@ import HealthKit
11
11
  let INIT_ERROR = "HEALTHKIT_INIT_ERROR"
12
12
  let INIT_ERROR_MESSAGE = "HealthKit not initialized"
13
13
  let TYPE_IDENTIFIER_ERROR = "HEALTHKIT_TYPE_IDENTIFIER_NOT_RECOGNIZED_ERROR"
14
+ let QUERY_ERROR = "HEALTHKIT_QUERY_ERROR"
14
15
  let GENERIC_ERROR = "HEALTHKIT_ERROR"
15
16
 
16
17
  let HKCharacteristicTypeIdentifier_PREFIX = "HKCharacteristicTypeIdentifier"
@@ -23,6 +24,9 @@ let HKWorkoutTypeIdentifier = "HKWorkoutTypeIdentifier"
23
24
  let HKWorkoutRouteTypeIdentifier = "HKWorkoutRouteTypeIdentifier"
24
25
  let HKDataTypeIdentifierHeartbeatSeries = "HKDataTypeIdentifierHeartbeatSeries"
25
26
 
27
+ let HKWorkoutActivityTypePropertyName = "activityType"
28
+ let HKWorkoutSessionLocationTypePropertyName = "locationType"
29
+
26
30
  let SpeedUnit = HKUnit(from: "m/s") // HKUnit.meter().unitDivided(by: HKUnit.second())
27
31
  // Support for MET data: HKAverageMETs 8.24046 kcal/hr·kg
28
32
  let METUnit = HKUnit(from: "kcal/hr·kg")
package/ios/Helpers.swift CHANGED
@@ -156,3 +156,84 @@ func objectTypeFromString(typeIdentifier: String) -> HKObjectType? {
156
156
 
157
157
  return nil
158
158
  }
159
+
160
+ func hkStatisticsOptionsFromOptions(_ options: NSArray) -> HKStatisticsOptions {
161
+ var opts = HKStatisticsOptions()
162
+
163
+ for o in options {
164
+ guard let str = o as? String else { continue }
165
+
166
+ switch str {
167
+ case "cumulativeSum":
168
+ opts.insert(.cumulativeSum)
169
+ case "discreteAverage":
170
+ opts.insert(.discreteAverage)
171
+ case "discreteMax":
172
+ opts.insert(.discreteMax)
173
+ case "discreteMin":
174
+ opts.insert(.discreteMin)
175
+ case "discreteMostRecent":
176
+ if #available(iOS 12, *) {
177
+ opts.insert(.discreteMostRecent)
178
+ }
179
+ case "duration":
180
+ if #available(iOS 13, *) {
181
+ opts.insert(.duration)
182
+ }
183
+ case "mostRecent":
184
+ if #available(iOS 13, *) {
185
+ opts.insert(.mostRecent)
186
+ }
187
+ case "separateBySource":
188
+ opts.insert(.separateBySource)
189
+ default:
190
+ continue
191
+ }
192
+ }
193
+
194
+ return opts
195
+ }
196
+
197
+ func componentsFromInterval(_ interval: NSDictionary) -> DateComponents {
198
+ let componentKeys: [String: WritableKeyPath<DateComponents, Int?>] = [
199
+ "minute": \.minute,
200
+ "hour": \.hour,
201
+ "day": \.day,
202
+ "month": \.month,
203
+ "year": \.year
204
+ ]
205
+
206
+ var intervalComponents = DateComponents()
207
+ for (key, keyPath) in componentKeys {
208
+ if let value = interval[key] as? Int {
209
+ intervalComponents[keyPath: keyPath] = value
210
+ }
211
+ }
212
+ return intervalComponents
213
+ }
214
+
215
+ func serializeQuantityIfExists(unit: HKUnit, quantity: HKQuantity?) -> [String: Any]? {
216
+ guard let quantity = quantity else { return nil }
217
+ return serializeQuantity(unit: unit, quantity: quantity)
218
+ }
219
+
220
+ func serializeStatisticIfExists(unit: HKUnit, quantity: HKQuantity?, stats: HKStatistics) -> [String: Any]? {
221
+ guard let quantity = quantity else { return nil }
222
+ return serializeStatistic(unit: unit, quantity: quantity, stats: stats)
223
+ }
224
+
225
+ func parseWorkoutConfiguration(_ dict: NSDictionary) -> HKWorkoutConfiguration {
226
+ let configuration = HKWorkoutConfiguration()
227
+
228
+ if let activityTypeRaw = dict[HKWorkoutActivityTypePropertyName] as? UInt,
229
+ let activityType = HKWorkoutActivityType(rawValue: activityTypeRaw) {
230
+ configuration.activityType = activityType
231
+ }
232
+
233
+ if let locationTypeRaw = dict[HKWorkoutSessionLocationTypePropertyName] as? Int,
234
+ let locationType = HKWorkoutSessionLocationType(rawValue: locationTypeRaw) {
235
+ configuration.locationType = locationType
236
+ }
237
+
238
+ return configuration
239
+ }
@@ -214,6 +214,17 @@ RCT_EXTERN_METHOD(queryStatisticsForQuantity:(NSString)typeIdentifier
214
214
  reject:(RCTPromiseRejectBlock)reject
215
215
  )
216
216
 
217
+ RCT_EXTERN_METHOD(queryStatisticsCollectionForQuantity:(NSString)typeIdentifier
218
+ unitString:(NSString)unitString
219
+ options:(NSArray)options
220
+ anchorDate:(NSDate)anchorDate
221
+ interval:(NSDictionary)interval
222
+ startDate:(NSDate)startDate
223
+ endDate:(NSDate)endDate
224
+ resolve:(RCTPromiseResolveBlock)resolve
225
+ reject:(RCTPromiseRejectBlock)reject
226
+ )
227
+
217
228
  RCT_EXTERN_METHOD(getWheelchairUse:(RCTPromiseResolveBlock)resolve
218
229
  withRejecter:(RCTPromiseRejectBlock)reject)
219
230
 
@@ -230,5 +241,9 @@ RCT_EXTERN_METHOD(getWorkoutPlanById:(NSString)workoutUUID
230
241
  RCT_EXTERN_METHOD(isProtectedDataAvailable:(RCTPromiseResolveBlock)resolve
231
242
  withRejecter:(RCTPromiseRejectBlock)reject)
232
243
 
244
+ RCT_EXTERN_METHOD(startWatchAppWithWorkoutConfiguration:(NSDictionary)workoutConfiguration
245
+ resolve:(RCTPromiseResolveBlock)resolve
246
+ reject:(RCTPromiseRejectBlock)reject
247
+ )
233
248
 
234
249
  @end