@flomentumsolutions/capacitor-health-extended 0.0.7 → 0.0.8
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.
|
@@ -6,6 +6,7 @@ import HealthKit
|
|
|
6
6
|
* Please read the Capacitor iOS Plugin Development Guide
|
|
7
7
|
* here: https://capacitorjs.com/docs/plugins/ios
|
|
8
8
|
*/
|
|
9
|
+
@MainActor
|
|
9
10
|
@objc(HealthPlugin)
|
|
10
11
|
public class HealthPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
11
12
|
public let identifier = "HealthPlugin"
|
|
@@ -22,6 +23,9 @@ public class HealthPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
22
23
|
|
|
23
24
|
let healthStore = HKHealthStore()
|
|
24
25
|
|
|
26
|
+
/// Serial queue to make route‑location mutations thread‑safe without locks
|
|
27
|
+
private let routeSyncQueue = DispatchQueue(label: "com.flomentum.healthplugin.routeSync")
|
|
28
|
+
|
|
25
29
|
@objc func isHealthAvailable(_ call: CAPPluginCall) {
|
|
26
30
|
let isAvailable = HKHealthStore.isHealthDataAvailable()
|
|
27
31
|
call.resolve(["available": isAvailable])
|
|
@@ -325,10 +329,26 @@ public class HealthPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
325
329
|
switch dataType.aggregationStyle {
|
|
326
330
|
case .cumulative:
|
|
327
331
|
return .cumulativeSum
|
|
332
|
+
|
|
333
|
+
// Newer discrete aggregation styles (iOS 15 +)
|
|
334
|
+
case .discreteAverage:
|
|
335
|
+
return .discreteAverage
|
|
336
|
+
@available(iOS 17.0, *)
|
|
337
|
+
case .discreteTemporallyWeighted:
|
|
338
|
+
return .discreteAverage
|
|
339
|
+
@available(iOS 17.0, *)
|
|
340
|
+
case .discreteEquivalentContinuousLevel:
|
|
341
|
+
return .discreteAverage
|
|
342
|
+
@available(iOS 17.0, *)
|
|
343
|
+
case .discreteArithmetic:
|
|
344
|
+
return .discreteAverage
|
|
345
|
+
|
|
346
|
+
// Legacy discrete fallback
|
|
328
347
|
case .discrete:
|
|
329
|
-
return .discreteAverage
|
|
348
|
+
return .discreteAverage
|
|
349
|
+
|
|
330
350
|
@unknown default:
|
|
331
|
-
return .
|
|
351
|
+
return .discreteAverage
|
|
332
352
|
}
|
|
333
353
|
}()
|
|
334
354
|
|
|
@@ -400,7 +420,7 @@ public class HealthPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
400
420
|
}
|
|
401
421
|
}
|
|
402
422
|
|
|
403
|
-
func queryMindfulnessAggregated(startDate: Date, endDate: Date, completion: @escaping ([[String: Any]]?, Error?) -> Void) {
|
|
423
|
+
func queryMindfulnessAggregated(startDate: Date, endDate: Date, completion: @escaping @Sendable ([[String: Any]]?, Error?) -> Void) {
|
|
404
424
|
guard let mindfulType = HKObjectType.categoryType(forIdentifier: .mindfulSession) else {
|
|
405
425
|
completion(nil, NSError(domain: "HealthKit", code: -1, userInfo: [NSLocalizedDescriptionKey: "MindfulSession type unavailable"]))
|
|
406
426
|
return
|
|
@@ -448,7 +468,7 @@ public class HealthPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
448
468
|
|
|
449
469
|
|
|
450
470
|
|
|
451
|
-
private func queryAggregated(for startDate: Date, for endDate: Date, for dataType: HKQuantityType?, completion: @escaping(Double?) -> Void) {
|
|
471
|
+
private func queryAggregated(for startDate: Date, for endDate: Date, for dataType: HKQuantityType?, completion: @escaping @Sendable(Double?) -> Void) {
|
|
452
472
|
|
|
453
473
|
|
|
454
474
|
guard let quantityType = dataType else {
|
|
@@ -602,7 +622,7 @@ public class HealthPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
602
622
|
|
|
603
623
|
|
|
604
624
|
// MARK: - Query Heart Rate Data
|
|
605
|
-
private func queryHeartRate(for workout: HKWorkout, completion: @escaping ([[String: Any]], String?) -> Void) {
|
|
625
|
+
private func queryHeartRate(for workout: HKWorkout, completion: @escaping @Sendable ([[String: Any]], String?) -> Void) {
|
|
606
626
|
let heartRateType = HKObjectType.quantityType(forIdentifier: .heartRate)!
|
|
607
627
|
let predicate = HKQuery.predicateForSamples(withStart: workout.startDate, end: workout.endDate, options: .strictStartDate)
|
|
608
628
|
|
|
@@ -633,7 +653,7 @@ public class HealthPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
633
653
|
}
|
|
634
654
|
|
|
635
655
|
// MARK: - Query Route Data
|
|
636
|
-
private func queryRoute(for workout: HKWorkout, completion: @escaping ([[String: Any]], String?) -> Void) {
|
|
656
|
+
private func queryRoute(for workout: HKWorkout, completion: @escaping @Sendable ([[String: Any]], String?) -> Void) {
|
|
637
657
|
let routeType = HKSeriesType.workoutRoute()
|
|
638
658
|
let predicate = HKQuery.predicateForObjects(from: workout)
|
|
639
659
|
|
|
@@ -664,30 +684,33 @@ public class HealthPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
664
684
|
}
|
|
665
685
|
|
|
666
686
|
// MARK: - Query Route Locations
|
|
667
|
-
private func queryLocations(for route: HKWorkoutRoute, completion: @escaping ([[String: Any]]) -> Void) {
|
|
687
|
+
private func queryLocations(for route: HKWorkoutRoute, completion: @escaping @Sendable ([[String: Any]]) -> Void) {
|
|
668
688
|
var routeLocations: [[String: Any]] = []
|
|
669
|
-
|
|
670
|
-
let locationQuery = HKWorkoutRouteQuery(route: route) {
|
|
689
|
+
|
|
690
|
+
let locationQuery = HKWorkoutRouteQuery(route: route) { _, locations, done, error in
|
|
671
691
|
guard let locations = locations, error == nil else {
|
|
672
692
|
completion([])
|
|
673
693
|
return
|
|
674
694
|
}
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
695
|
+
|
|
696
|
+
// Append on a dedicated serial queue so we’re race‑free without NSLock
|
|
697
|
+
self.routeSyncQueue.async {
|
|
698
|
+
for location in locations {
|
|
699
|
+
let locationDict: [String: Any] = [
|
|
700
|
+
"timestamp": location.timestamp,
|
|
701
|
+
"lat": location.coordinate.latitude,
|
|
702
|
+
"lng": location.coordinate.longitude,
|
|
703
|
+
"alt": location.altitude
|
|
704
|
+
]
|
|
705
|
+
routeLocations.append(locationDict)
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
if done {
|
|
709
|
+
completion(routeLocations)
|
|
710
|
+
}
|
|
688
711
|
}
|
|
689
712
|
}
|
|
690
|
-
|
|
713
|
+
|
|
691
714
|
healthStore.execute(locationQuery)
|
|
692
715
|
}
|
|
693
716
|
|
package/package.json
CHANGED