@kingstinct/react-native-healthkit 11.1.2 → 12.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/ios/CoreModule.swift +6 -6
- package/ios/Helpers.swift +5 -5
- package/ios/QuantityTypeModule.swift +5 -19
- package/ios/WorkoutsModule.swift +14 -14
- package/lib/commonjs/healthkit.ios.js +11 -6
- package/lib/commonjs/healthkit.js +12 -4
- package/lib/commonjs/hooks/useHealthkitAuthorization.js +14 -8
- package/lib/commonjs/hooks/useSubscribeToQuantitySamples.js +20 -0
- package/lib/commonjs/utils/subscribeToQuantitySamples.js +47 -0
- package/lib/module/healthkit.ios.js +6 -4
- package/lib/module/healthkit.js +11 -3
- package/lib/module/hooks/useHealthkitAuthorization.js +14 -8
- package/lib/module/hooks/useSubscribeToQuantitySamples.js +17 -0
- package/lib/module/utils/subscribeToQuantitySamples.js +43 -0
- package/lib/typescript/healthkit.d.ts +19 -9
- package/lib/typescript/healthkit.ios.d.ts +27 -18
- package/lib/typescript/hooks/useHealthkitAuthorization.d.ts +4 -1
- package/lib/typescript/hooks/useSubscribeToQuantitySamples.d.ts +3 -0
- package/lib/typescript/specs/CharacteristicTypeModule.nitro.d.ts +2 -2
- package/lib/typescript/specs/CoreModule.nitro.d.ts +7 -2
- package/lib/typescript/specs/QuantityTypeModule.nitro.d.ts +1 -1
- package/lib/typescript/specs/WorkoutProxy.nitro.d.ts +3 -11
- package/lib/typescript/specs/WorkoutsModule.nitro.d.ts +1 -1
- package/lib/typescript/types/Device.d.ts +8 -8
- package/lib/typescript/types/Source.d.ts +2 -2
- package/lib/typescript/types/Subscriptions.d.ts +14 -1
- package/lib/typescript/types/Workouts.d.ts +1 -1
- package/lib/typescript/utils/subscribeToQuantitySamples.d.ts +5 -0
- package/nitrogen/generated/ios/ReactNativeHealthkit-Swift-Cxx-Bridge.hpp +94 -55
- package/nitrogen/generated/ios/ReactNativeHealthkit-Swift-Cxx-Umbrella.hpp +3 -2
- package/nitrogen/generated/ios/c++/HybridCategoryTypeModuleSpecSwift.hpp +3 -2
- package/nitrogen/generated/ios/c++/HybridCharacteristicTypeModuleSpecSwift.hpp +3 -0
- package/nitrogen/generated/ios/c++/HybridCoreModuleSpecSwift.hpp +10 -4
- package/nitrogen/generated/ios/c++/HybridCorrelationTypeModuleSpecSwift.hpp +3 -2
- package/nitrogen/generated/ios/c++/HybridElectrocardiogramModuleSpecSwift.hpp +3 -2
- package/nitrogen/generated/ios/c++/HybridHeartbeatSeriesModuleSpecSwift.hpp +3 -2
- package/nitrogen/generated/ios/c++/HybridQuantityTypeModuleSpecSwift.hpp +4 -3
- package/nitrogen/generated/ios/c++/HybridSourceProxySpecSwift.hpp +3 -0
- package/nitrogen/generated/ios/c++/HybridStateOfMindModuleSpecSwift.hpp +3 -2
- package/nitrogen/generated/ios/c++/HybridWorkoutProxySpecSwift.hpp +7 -22
- package/nitrogen/generated/ios/c++/HybridWorkoutsModuleSpecSwift.hpp +5 -4
- package/nitrogen/generated/ios/swift/AuthDataTypes.swift +108 -0
- package/nitrogen/generated/ios/swift/ECGQueryOptionsWithSortOrder.swift +16 -2
- package/nitrogen/generated/ios/swift/HybridCategoryTypeModuleSpec.swift +8 -0
- package/nitrogen/generated/ios/swift/HybridCategoryTypeModuleSpec_cxx.swift +10 -1
- package/nitrogen/generated/ios/swift/HybridCharacteristicTypeModuleSpec.swift +8 -0
- package/nitrogen/generated/ios/swift/HybridCharacteristicTypeModuleSpec_cxx.swift +10 -1
- package/nitrogen/generated/ios/swift/HybridCoreModuleSpec.swift +10 -2
- package/nitrogen/generated/ios/swift/HybridCoreModuleSpec_cxx.swift +24 -36
- package/nitrogen/generated/ios/swift/HybridCorrelationTypeModuleSpec.swift +8 -0
- package/nitrogen/generated/ios/swift/HybridCorrelationTypeModuleSpec_cxx.swift +10 -1
- package/nitrogen/generated/ios/swift/HybridElectrocardiogramModuleSpec.swift +8 -0
- package/nitrogen/generated/ios/swift/HybridElectrocardiogramModuleSpec_cxx.swift +10 -1
- package/nitrogen/generated/ios/swift/HybridHeartbeatSeriesModuleSpec.swift +8 -0
- package/nitrogen/generated/ios/swift/HybridHeartbeatSeriesModuleSpec_cxx.swift +10 -1
- package/nitrogen/generated/ios/swift/HybridQuantityTypeModuleSpec.swift +9 -1
- package/nitrogen/generated/ios/swift/HybridQuantityTypeModuleSpec_cxx.swift +13 -12
- package/nitrogen/generated/ios/swift/HybridSourceProxySpec.swift +7 -0
- package/nitrogen/generated/ios/swift/HybridSourceProxySpec_cxx.swift +9 -1
- package/nitrogen/generated/ios/swift/HybridStateOfMindModuleSpec.swift +8 -0
- package/nitrogen/generated/ios/swift/HybridStateOfMindModuleSpec_cxx.swift +11 -10
- package/nitrogen/generated/ios/swift/HybridWorkoutProxySpec.swift +8 -4
- package/nitrogen/generated/ios/swift/HybridWorkoutProxySpec_cxx.swift +10 -53
- package/nitrogen/generated/ios/swift/HybridWorkoutsModuleSpec.swift +9 -1
- package/nitrogen/generated/ios/swift/HybridWorkoutsModuleSpec_cxx.swift +19 -3
- package/nitrogen/generated/ios/swift/PredicateWithMetadataKey.swift +21 -21
- package/nitrogen/generated/ios/swift/PredicateWithStartAndEnd.swift +16 -2
- package/nitrogen/generated/ios/swift/QueryOptionsWithSortOrder.swift +8 -1
- package/nitrogen/generated/ios/swift/QueryOptionsWithSortOrderAndUnit.swift +8 -1
- package/nitrogen/generated/ios/swift/StateOfMindSample.swift +29 -21
- package/nitrogen/generated/ios/swift/{Variant_String_Double_Bool_Date.swift → Variant_Bool_String_Double_Date.swift} +6 -6
- package/nitrogen/generated/ios/swift/WorkoutQueryOptions.swift +8 -1
- package/nitrogen/generated/shared/c++/AuthDataTypes.hpp +85 -0
- package/nitrogen/generated/shared/c++/CategorySample.hpp +0 -2
- package/nitrogen/generated/shared/c++/CategorySampleForSaving.hpp +0 -2
- package/nitrogen/generated/shared/c++/CorrelationSample.hpp +0 -2
- package/nitrogen/generated/shared/c++/DeletedSample.hpp +1 -2
- package/nitrogen/generated/shared/c++/ElectrocardiogramSample.hpp +0 -2
- package/nitrogen/generated/shared/c++/HeartbeatSeriesSample.hpp +0 -2
- package/nitrogen/generated/shared/c++/HybridCategoryTypeModuleSpec.hpp +0 -2
- package/nitrogen/generated/shared/c++/HybridCoreModuleSpec.hpp +5 -5
- package/nitrogen/generated/shared/c++/HybridCorrelationTypeModuleSpec.hpp +0 -2
- package/nitrogen/generated/shared/c++/HybridQuantityTypeModuleSpec.hpp +1 -3
- package/nitrogen/generated/shared/c++/HybridStateOfMindModuleSpec.hpp +0 -2
- package/nitrogen/generated/shared/c++/HybridWorkoutProxySpec.cpp +0 -4
- package/nitrogen/generated/shared/c++/HybridWorkoutProxySpec.hpp +4 -10
- package/nitrogen/generated/shared/c++/HybridWorkoutsModuleSpec.hpp +2 -3
- package/nitrogen/generated/shared/c++/PredicateWithMetadataKey.hpp +5 -5
- package/nitrogen/generated/shared/c++/QuantitySample.hpp +0 -2
- package/nitrogen/generated/shared/c++/QuantitySampleForSaving.hpp +0 -2
- package/nitrogen/generated/shared/c++/StateOfMindSample.hpp +0 -2
- package/nitrogen/generated/shared/c++/WorkoutSample.hpp +0 -2
- package/package.json +7 -7
- package/src/healthkit.ios.ts +11 -6
- package/src/healthkit.ts +19 -6
- package/src/hooks/useHealthkitAuthorization.test.ts +12 -4
- package/src/hooks/useHealthkitAuthorization.ts +20 -14
- package/src/hooks/useSubscribeToQuantitySamples.ts +31 -0
- package/src/specs/CategoryTypeModule.nitro.ts +1 -1
- package/src/specs/CharacteristicTypeModule.nitro.ts +2 -2
- package/src/specs/CoreModule.nitro.ts +8 -6
- package/src/specs/QuantityTypeModule.nitro.ts +1 -1
- package/src/specs/WorkoutProxy.nitro.ts +3 -16
- package/src/specs/WorkoutsModule.nitro.ts +2 -2
- package/src/types/Device.ts +8 -8
- package/src/types/InterfaceVerificationExample.ts +2 -2
- package/src/types/Source.ts +2 -2
- package/src/types/Subscriptions.ts +19 -1
- package/src/types/Workouts.ts +1 -1
- package/src/utils/subscribeToQuantitySamples.ts +63 -0
package/README.md
CHANGED
|
@@ -84,14 +84,16 @@ Some imperative examples:
|
|
|
84
84
|
const isAvailable = await isHealthDataAvailable();
|
|
85
85
|
|
|
86
86
|
/* Read latest sample of any data */
|
|
87
|
-
await requestAuthorization(['HKQuantityTypeIdentifierBodyFatPercentage']); // request read permission for bodyFatPercentage
|
|
87
|
+
await requestAuthorization({ toRead: ['HKQuantityTypeIdentifierBodyFatPercentage'] }); // request read permission for bodyFatPercentage
|
|
88
88
|
|
|
89
89
|
const { quantity, unit, startDate, endDate } = await getMostRecentQuantitySample('HKQuantityTypeIdentifierBodyFatPercentage'); // read latest sample
|
|
90
90
|
|
|
91
91
|
console.log(quantity) // 17.5
|
|
92
92
|
console.log(unit) // %
|
|
93
93
|
|
|
94
|
-
await requestAuthorization(
|
|
94
|
+
await requestAuthorization({
|
|
95
|
+
toRead: ['HKQuantityTypeIdentifierHeartRate']
|
|
96
|
+
}); // request read permission for heart rate
|
|
95
97
|
|
|
96
98
|
/* Subscribe to data (Make sure to request permissions before subscribing to changes) */
|
|
97
99
|
const [hasRequestedAuthorization, setHasRequestedAuthorization] = useState(false);
|
|
@@ -113,7 +115,7 @@ Some imperative examples:
|
|
|
113
115
|
}, [hasRequestedAuthorization]);
|
|
114
116
|
|
|
115
117
|
/* write data */
|
|
116
|
-
await requestAuthorization(
|
|
118
|
+
await requestAuthorization({ toShare: ['HKQuantityTypeIdentifierInsulinDelivery'] }); // request write permission for insulin delivery
|
|
117
119
|
|
|
118
120
|
saveQuantitySample(
|
|
119
121
|
'HKQuantityTypeIdentifierInsulinDelivery',
|
package/ios/CoreModule.swift
CHANGED
|
@@ -109,9 +109,9 @@ class CoreModule: HybridCoreModuleSpec {
|
|
|
109
109
|
throw RuntimeError.error(withMessage: "[react-native-healthkit] got unrecognized AuthorizationStatus with value \(authStatus.rawValue)")
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
func getRequestStatusForAuthorization(
|
|
113
|
-
let toShare = sampleTypesFromArray(typeIdentifiersWriteable: toShare)
|
|
114
|
-
let toRead = objectTypesFromArray(typeIdentifiers: toRead)
|
|
112
|
+
func getRequestStatusForAuthorization(toCheck: AuthDataTypes) throws -> Promise<AuthorizationRequestStatus> {
|
|
113
|
+
let toShare = sampleTypesFromArray(typeIdentifiersWriteable: toCheck.toShare ?? [])
|
|
114
|
+
let toRead = objectTypesFromArray(typeIdentifiers: toCheck.toRead ?? [])
|
|
115
115
|
|
|
116
116
|
return Promise.async {
|
|
117
117
|
try await withCheckedThrowingContinuation { continuation in
|
|
@@ -131,9 +131,9 @@ class CoreModule: HybridCoreModuleSpec {
|
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
func requestAuthorization(
|
|
135
|
-
let share = sampleTypesFromArray(typeIdentifiersWriteable: toShare)
|
|
136
|
-
let toRead = objectTypesFromArray(typeIdentifiers: toRead)
|
|
134
|
+
func requestAuthorization(toRequest: AuthDataTypes) throws -> Promise<Bool> {
|
|
135
|
+
let share = sampleTypesFromArray(typeIdentifiersWriteable: toRequest.toShare ?? [])
|
|
136
|
+
let toRead = objectTypesFromArray(typeIdentifiers: toRequest.toRead ?? [])
|
|
137
137
|
|
|
138
138
|
return Promise.async {
|
|
139
139
|
try await withCheckedThrowingContinuation { continuation in
|
package/ios/Helpers.swift
CHANGED
|
@@ -29,7 +29,7 @@ func getQueryLimit(_ limit: Double?) -> Int {
|
|
|
29
29
|
return Int(limit)
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
return
|
|
32
|
+
return HKObjectQueryNoLimit
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
func createPredicateForWorkout(filter: PredicateForWorkouts) throws -> NSPredicate {
|
|
@@ -144,12 +144,12 @@ func createMetadataPredicate(metadataKey: PredicateWithMetadataKey) throws -> NS
|
|
|
144
144
|
let actualValue: Any
|
|
145
145
|
|
|
146
146
|
switch valueVariant {
|
|
147
|
-
case .first(let
|
|
147
|
+
case .first(let boolValue):
|
|
148
|
+
actualValue = NSNumber(value: boolValue ? 1 : 0)
|
|
149
|
+
case .second(let stringValue):
|
|
148
150
|
actualValue = stringValue
|
|
149
|
-
case .
|
|
151
|
+
case .third(let doubleValue):
|
|
150
152
|
actualValue = NSNumber(value: doubleValue)
|
|
151
|
-
case .third(let boolValue):
|
|
152
|
-
actualValue = NSNumber(value: boolValue ? 1 : 0)
|
|
153
153
|
case .fourth(let dateValue):
|
|
154
154
|
actualValue = dateValue
|
|
155
155
|
}
|
|
@@ -290,17 +290,11 @@ class QuantityTypeModule: HybridQuantityTypeModuleSpec {
|
|
|
290
290
|
}
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
-
func queryStatisticsCollectionForQuantity(identifier: QuantityTypeIdentifier, statistics: [StatisticsOptions], anchorDate:
|
|
293
|
+
func queryStatisticsCollectionForQuantity(identifier: QuantityTypeIdentifier, statistics: [StatisticsOptions], anchorDate: Date, intervalComponents: IntervalComponents, options: StatisticsQueryOptions?) throws -> Promise<[QueryStatisticsResponse]> {
|
|
294
294
|
let quantityType = try initializeQuantityType(identifier.stringValue)
|
|
295
295
|
|
|
296
296
|
let predicate = try createPredicate(filter: options?.filter)
|
|
297
297
|
|
|
298
|
-
// Convert the anchor date string to Date
|
|
299
|
-
let dateFormatter = ISO8601DateFormatter()
|
|
300
|
-
guard let anchor = dateFormatter.date(from: anchorDate) else {
|
|
301
|
-
throw RuntimeError.error(withMessage: "Invalid anchor date format: " + anchorDate)
|
|
302
|
-
}
|
|
303
|
-
|
|
304
298
|
// Create date components from interval
|
|
305
299
|
var dateComponents = DateComponents()
|
|
306
300
|
if let minute = intervalComponents.minute {
|
|
@@ -324,12 +318,13 @@ class QuantityTypeModule: HybridQuantityTypeModuleSpec {
|
|
|
324
318
|
|
|
325
319
|
return Promise.async {
|
|
326
320
|
let unit = try await getUnitToUse(unitOverride: options?.unit, quantityType: quantityType)
|
|
321
|
+
|
|
327
322
|
return try await withCheckedThrowingContinuation { continuation in
|
|
328
323
|
let query = HKStatisticsCollectionQuery.init(
|
|
329
324
|
quantityType: quantityType,
|
|
330
325
|
quantitySamplePredicate: predicate,
|
|
331
326
|
options: opts,
|
|
332
|
-
anchorDate:
|
|
327
|
+
anchorDate: anchorDate,
|
|
333
328
|
intervalComponents: dateComponents
|
|
334
329
|
)
|
|
335
330
|
|
|
@@ -413,16 +408,7 @@ class QuantityTypeModule: HybridQuantityTypeModuleSpec {
|
|
|
413
408
|
let deletedSamples = deletedSamples?.map { serializeDeletedSample(sample: $0) } ?? []
|
|
414
409
|
let newAnchor = serializeAnchor(anchor: newAnchor) ?? ""
|
|
415
410
|
|
|
416
|
-
|
|
417
|
-
let response = QuantitySamplesWithAnchorResponse(
|
|
418
|
-
samples: [],
|
|
419
|
-
deletedSamples: deletedSamples,
|
|
420
|
-
newAnchor: newAnchor
|
|
421
|
-
)
|
|
422
|
-
return continuation.resume(returning: response)
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
let quantitySamples = samples.compactMap { sample in
|
|
411
|
+
let quantitySamples = samples?.compactMap { sample in
|
|
426
412
|
if let quantitySample = sample as? HKQuantitySample {
|
|
427
413
|
do {
|
|
428
414
|
return try serializeQuantitySample(
|
|
@@ -437,7 +423,7 @@ class QuantityTypeModule: HybridQuantityTypeModuleSpec {
|
|
|
437
423
|
}
|
|
438
424
|
|
|
439
425
|
let response = QuantitySamplesWithAnchorResponse(
|
|
440
|
-
samples: quantitySamples,
|
|
426
|
+
samples: quantitySamples ?? [],
|
|
441
427
|
deletedSamples: deletedSamples,
|
|
442
428
|
newAnchor: newAnchor,
|
|
443
429
|
)
|
package/ios/WorkoutsModule.swift
CHANGED
|
@@ -94,20 +94,18 @@ class WorkoutsModule: HybridWorkoutsModuleSpec {
|
|
|
94
94
|
quantities: [QuantitySampleForSaving],
|
|
95
95
|
startDate: Date,
|
|
96
96
|
endDate: Date,
|
|
97
|
-
totals: WorkoutTotals
|
|
98
|
-
metadata: AnyMap
|
|
97
|
+
totals: WorkoutTotals?,
|
|
98
|
+
metadata: AnyMap?
|
|
99
99
|
) throws -> Promise<HybridWorkoutProxySpec> {
|
|
100
100
|
|
|
101
101
|
let type = try initializeWorkoutActivityType(UInt(workoutActivityType.rawValue))
|
|
102
102
|
|
|
103
|
-
//
|
|
104
|
-
if
|
|
105
|
-
|
|
106
|
-
throw RuntimeError.error(withMessage: "endDate must not be less than startDate")
|
|
107
|
-
}
|
|
103
|
+
// ensure that start date is before end date
|
|
104
|
+
if startDate > endDate {
|
|
105
|
+
throw RuntimeError.error(withMessage: "endDate must not be less than startDate")
|
|
108
106
|
}
|
|
109
107
|
|
|
110
|
-
let metadataDeserialized = anyMapToDictionary(metadata)
|
|
108
|
+
let metadataDeserialized = metadata != nil ? anyMapToDictionary(metadata!) : nil
|
|
111
109
|
|
|
112
110
|
var totalEnergyBurned: HKQuantity?
|
|
113
111
|
var totalDistance: HKQuantity?
|
|
@@ -149,8 +147,8 @@ class WorkoutsModule: HybridWorkoutsModuleSpec {
|
|
|
149
147
|
}
|
|
150
148
|
|
|
151
149
|
// if totals are provided override samples
|
|
152
|
-
let rawTotalDistance = totals
|
|
153
|
-
let rawTotalEnergy = totals
|
|
150
|
+
let rawTotalDistance = totals?.distance ?? 0.0
|
|
151
|
+
let rawTotalEnergy = totals?.energyBurned ?? 0.0
|
|
154
152
|
|
|
155
153
|
if rawTotalDistance != 0.0 {
|
|
156
154
|
totalDistance = HKQuantity(unit: .meter(), doubleValue: rawTotalDistance)
|
|
@@ -176,7 +174,7 @@ class WorkoutsModule: HybridWorkoutsModuleSpec {
|
|
|
176
174
|
)
|
|
177
175
|
} else {
|
|
178
176
|
if #available(iOS 11, *) {
|
|
179
|
-
if totalFlightsClimbed
|
|
177
|
+
if let totalFlightsClimbed = totalFlightsClimbed {
|
|
180
178
|
workout = HKWorkout.init(
|
|
181
179
|
activityType: type,
|
|
182
180
|
start: startDate,
|
|
@@ -214,15 +212,17 @@ class WorkoutsModule: HybridWorkoutsModuleSpec {
|
|
|
214
212
|
store.save(workout) { (_: Bool, error: Error?) in
|
|
215
213
|
if let error = error {
|
|
216
214
|
return continuation.resume(throwing: error)
|
|
217
|
-
}
|
|
218
|
-
if !initializedSamples.isEmpty {
|
|
215
|
+
} else if !initializedSamples.isEmpty {
|
|
219
216
|
store.add(initializedSamples, to: workout) { (_, error: Error?) in
|
|
220
217
|
if let error = error {
|
|
221
218
|
return continuation.resume(throwing: error)
|
|
222
219
|
}
|
|
220
|
+
return continuation.resume()
|
|
223
221
|
}
|
|
222
|
+
} else {
|
|
223
|
+
return continuation.resume()
|
|
224
224
|
}
|
|
225
|
-
|
|
225
|
+
|
|
226
226
|
}
|
|
227
227
|
}) as Void
|
|
228
228
|
|
|
@@ -17,8 +17,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
17
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.
|
|
21
|
-
exports.getWheelchairUseAsync = exports.getFitzpatrickSkinTypeAsync = exports.getDateOfBirthAsync = exports.getBloodTypeAsync = exports.getBiologicalSexAsync = exports.areObjectTypesAvailableAsync = exports.areObjectTypesAvailable = exports.isObjectTypeAvailableAsync = exports.isObjectTypeAvailable = exports.
|
|
20
|
+
exports.isProtectedDataAvailable = exports.startWatchApp = exports.saveWorkoutSample = exports.saveQuantitySample = exports.saveCorrelationSample = exports.saveCategorySample = exports.deleteObjects = exports.requestAuthorization = exports.querySources = exports.queryWorkoutSamplesWithAnchor = exports.queryWorkoutSamples = exports.queryStatisticsCollectionForQuantity = exports.queryStatisticsForQuantity = exports.queryQuantitySamplesWithAnchor = exports.queryQuantitySamples = exports.queryElectrocardiogramSamplesWithAnchor = exports.queryElectrocardiogramSamples = exports.queryHeartbeatSeriesSamplesWithAnchor = exports.queryHeartbeatSeriesSamples = exports.queryCorrelationSamples = exports.queryCategorySamplesWithAnchor = exports.queryCategorySamples = exports.isHealthDataAvailableAsync = exports.isHealthDataAvailable = exports.getWheelchairUse = exports.getRequestStatusForAuthorization = exports.getPreferredUnits = exports.getFitzpatrickSkinType = exports.getDateOfBirth = exports.getBloodType = exports.getBiologicalSex = exports.enableBackgroundDelivery = exports.disableBackgroundDelivery = exports.disableAllBackgroundDelivery = exports.authorizationStatusFor = exports.useSubscribeToQuantitySamples = exports.useSubscribeToChanges = exports.useStatisticsForQuantity = exports.useSources = exports.useMostRecentWorkout = exports.useMostRecentQuantitySample = exports.useMostRecentCategorySample = exports.useIsHealthDataAvailable = exports.useHealthkitAuthorization = exports.subscribeToQuantitySamples = exports.subscribeToChanges = exports.getPreferredUnit = exports.getMostRecentWorkout = exports.getMostRecentQuantitySample = exports.getMostRecentCategorySample = void 0;
|
|
21
|
+
exports.getWheelchairUseAsync = exports.getFitzpatrickSkinTypeAsync = exports.getDateOfBirthAsync = exports.getBloodTypeAsync = exports.getBiologicalSexAsync = exports.areObjectTypesAvailableAsync = exports.areObjectTypesAvailable = exports.isObjectTypeAvailableAsync = exports.isObjectTypeAvailable = exports.isQuantityCompatibleWithUnit = exports.saveStateOfMindSample = exports.queryStateOfMindSamples = void 0;
|
|
22
22
|
const react_native_1 = require("react-native");
|
|
23
23
|
const useHealthkitAuthorization_1 = __importDefault(require("./hooks/useHealthkitAuthorization"));
|
|
24
24
|
exports.useHealthkitAuthorization = useHealthkitAuthorization_1.default;
|
|
@@ -36,6 +36,8 @@ const useStatisticsForQuantity_1 = __importDefault(require("./hooks/useStatistic
|
|
|
36
36
|
exports.useStatisticsForQuantity = useStatisticsForQuantity_1.default;
|
|
37
37
|
const useSubscribeToChanges_1 = __importDefault(require("./hooks/useSubscribeToChanges"));
|
|
38
38
|
exports.useSubscribeToChanges = useSubscribeToChanges_1.default;
|
|
39
|
+
const useSubscribeToQuantitySamples_1 = __importDefault(require("./hooks/useSubscribeToQuantitySamples"));
|
|
40
|
+
exports.useSubscribeToQuantitySamples = useSubscribeToQuantitySamples_1.default;
|
|
39
41
|
const modules_1 = require("./modules");
|
|
40
42
|
const getMostRecentCategorySample_1 = __importDefault(require("./utils/getMostRecentCategorySample"));
|
|
41
43
|
exports.getMostRecentCategorySample = getMostRecentCategorySample_1.default;
|
|
@@ -45,6 +47,10 @@ const getMostRecentWorkout_1 = __importDefault(require("./utils/getMostRecentWor
|
|
|
45
47
|
exports.getMostRecentWorkout = getMostRecentWorkout_1.default;
|
|
46
48
|
const getPreferredUnit_1 = __importDefault(require("./utils/getPreferredUnit"));
|
|
47
49
|
exports.getPreferredUnit = getPreferredUnit_1.default;
|
|
50
|
+
const subscribeToChanges_1 = require("./utils/subscribeToChanges");
|
|
51
|
+
Object.defineProperty(exports, "subscribeToChanges", { enumerable: true, get: function () { return subscribeToChanges_1.subscribeToChanges; } });
|
|
52
|
+
const subscribeToQuantitySamples_1 = require("./utils/subscribeToQuantitySamples");
|
|
53
|
+
Object.defineProperty(exports, "subscribeToQuantitySamples", { enumerable: true, get: function () { return subscribeToQuantitySamples_1.subscribeToQuantitySamples; } });
|
|
48
54
|
__exportStar(require("./types"), exports);
|
|
49
55
|
const currentMajorVersionIOS = react_native_1.Platform.OS === 'ios' ? Number.parseInt(react_native_1.Platform.Version, 10) : 0;
|
|
50
56
|
// Named exports - all functions bound to their respective modules
|
|
@@ -81,13 +87,11 @@ exports.saveCategorySample = modules_1.CategoryTypes.saveCategorySample.bind(mod
|
|
|
81
87
|
exports.saveCorrelationSample = modules_1.CorrelationTypes.saveCorrelationSample.bind(modules_1.CorrelationTypes);
|
|
82
88
|
exports.saveQuantitySample = modules_1.QuantityTypes.saveQuantitySample.bind(modules_1.QuantityTypes);
|
|
83
89
|
exports.saveWorkoutSample = modules_1.Workouts.saveWorkoutSample.bind(modules_1.Workouts);
|
|
84
|
-
exports.subscribeToChanges = modules_1.Core.subscribeToObserverQuery.bind(modules_1.Core);
|
|
85
90
|
exports.startWatchApp = modules_1.Workouts.startWatchAppWithWorkoutConfiguration.bind(modules_1.Workouts);
|
|
86
91
|
exports.isProtectedDataAvailable = modules_1.Core.isProtectedDataAvailable.bind(modules_1.Core);
|
|
87
92
|
exports.queryStateOfMindSamples = modules_1.StateOfMind.queryStateOfMindSamples.bind(modules_1.StateOfMind);
|
|
88
93
|
exports.saveStateOfMindSample = modules_1.StateOfMind.saveStateOfMindSample.bind(modules_1.StateOfMind);
|
|
89
94
|
exports.isQuantityCompatibleWithUnit = modules_1.QuantityTypes.isQuantityCompatibleWithUnit.bind(modules_1.QuantityTypes);
|
|
90
|
-
exports.unsubscribeQueries = modules_1.Core.unsubscribeQueries.bind(modules_1.Core);
|
|
91
95
|
exports.isObjectTypeAvailable = modules_1.Core.isObjectTypeAvailable.bind(modules_1.Core);
|
|
92
96
|
exports.isObjectTypeAvailableAsync = modules_1.Core.isObjectTypeAvailableAsync.bind(modules_1.Core);
|
|
93
97
|
exports.areObjectTypesAvailable = modules_1.Core.areObjectTypesAvailable.bind(modules_1.Core);
|
|
@@ -145,8 +149,8 @@ exports.default = {
|
|
|
145
149
|
saveCorrelationSample: exports.saveCorrelationSample,
|
|
146
150
|
saveQuantitySample: exports.saveQuantitySample,
|
|
147
151
|
saveWorkoutSample: exports.saveWorkoutSample,
|
|
148
|
-
subscribeToChanges:
|
|
149
|
-
|
|
152
|
+
subscribeToChanges: subscribeToChanges_1.subscribeToChanges,
|
|
153
|
+
subscribeToQuantitySamples: subscribeToQuantitySamples_1.subscribeToQuantitySamples,
|
|
150
154
|
startWatchApp: exports.startWatchApp,
|
|
151
155
|
isProtectedDataAvailable: exports.isProtectedDataAvailable,
|
|
152
156
|
queryStateOfMindSamples: exports.queryStateOfMindSamples,
|
|
@@ -156,6 +160,7 @@ exports.default = {
|
|
|
156
160
|
useMostRecentQuantitySample: useMostRecentQuantitySample_1.default,
|
|
157
161
|
useMostRecentWorkout: useMostRecentWorkout_1.default,
|
|
158
162
|
useSubscribeToChanges: useSubscribeToChanges_1.default,
|
|
163
|
+
useSubscribeToQuantitySamples: useSubscribeToQuantitySamples_1.default,
|
|
159
164
|
useHealthkitAuthorization: useHealthkitAuthorization_1.default,
|
|
160
165
|
useIsHealthDataAvailable: useIsHealthDataAvailable_1.useIsHealthDataAvailable,
|
|
161
166
|
useSources: useSources_1.default,
|
|
@@ -15,7 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
exports.useSources = exports.useIsHealthDataAvailable = exports.useHealthkitAuthorization = exports.useSubscribeToChanges = exports.useMostRecentWorkout = exports.useMostRecentQuantitySample = exports.getPreferredUnit = exports.getMostRecentWorkout = exports.getMostRecentQuantitySample = exports.saveStateOfMindSample = exports.queryStateOfMindSamples = exports.startWatchApp = exports.saveWorkoutSample = exports.queryWorkoutSamplesWithAnchor = exports.queryWorkoutSamples = exports.queryElectrocardiogramSamplesWithAnchor = exports.queryElectrocardiogramSamples = exports.queryHeartbeatSeriesSamplesWithAnchor = exports.queryHeartbeatSeriesSamples = exports.saveCorrelationSample = exports.queryCorrelationSamples = exports.saveCategorySample = exports.isQuantityCompatibleWithUnit = exports.saveQuantitySample = exports.queryStatisticsCollectionForQuantity = exports.queryStatisticsForQuantity = exports.queryQuantitySamplesWithAnchor = exports.queryQuantitySamples = exports.getWheelchairUse = exports.getFitzpatrickSkinType = exports.getDateOfBirth = exports.getBloodType = exports.getBiologicalSex = exports.areObjectTypesAvailableAsync = exports.areObjectTypesAvailable = exports.isObjectTypeAvailableAsync = exports.isObjectTypeAvailable = exports.isProtectedDataAvailable = exports.subscribeToChanges = exports.deleteObjects = exports.requestAuthorization = exports.querySources = exports.isHealthDataAvailableAsync = exports.isHealthDataAvailable = exports.getRequestStatusForAuthorization = exports.getPreferredUnits = exports.enableBackgroundDelivery = exports.disableBackgroundDelivery = exports.disableAllBackgroundDelivery = exports.authorizationStatusFor = void 0;
|
|
18
|
-
exports.
|
|
18
|
+
exports.useSubscribeToQuantitySamples = exports.subscribeToQuantitySamples = exports.getWheelchairUseAsync = exports.getFitzpatrickSkinTypeAsync = exports.getDateOfBirthAsync = exports.getBloodTypeAsync = exports.getBiologicalSexAsync = exports.useStatisticsForQuantity = void 0;
|
|
19
19
|
exports.queryCategorySamples = queryCategorySamples;
|
|
20
20
|
exports.queryCategorySamplesWithAnchor = queryCategorySamplesWithAnchor;
|
|
21
21
|
exports.getMostRecentCategorySample = getMostRecentCategorySample;
|
|
@@ -49,7 +49,9 @@ exports.isHealthDataAvailableAsync = UnavailableFnFromModule('isHealthDataAvaila
|
|
|
49
49
|
exports.querySources = UnavailableFnFromModule('querySources', Promise.resolve([]));
|
|
50
50
|
exports.requestAuthorization = UnavailableFnFromModule('requestAuthorization', Promise.resolve(false));
|
|
51
51
|
exports.deleteObjects = UnavailableFnFromModule('deleteObjects', Promise.resolve(0));
|
|
52
|
-
exports.subscribeToChanges = UnavailableFnFromModule('subscribeToChanges',
|
|
52
|
+
exports.subscribeToChanges = UnavailableFnFromModule('subscribeToChanges', {
|
|
53
|
+
remove: () => false,
|
|
54
|
+
}); // Mocking the observer query UUID
|
|
53
55
|
exports.isProtectedDataAvailable = UnavailableFnFromModule('isProtectedDataAvailable', false);
|
|
54
56
|
exports.isObjectTypeAvailable = UnavailableFnFromModule('isObjectTypeAvailable', false);
|
|
55
57
|
exports.isObjectTypeAvailableAsync = UnavailableFnFromModule('isObjectTypeAvailableAsync', Promise.resolve(false));
|
|
@@ -160,14 +162,18 @@ exports.getBloodTypeAsync = UnavailableFnFromModule('getBloodTypeAsync', Promise
|
|
|
160
162
|
exports.getDateOfBirthAsync = UnavailableFnFromModule('getDateOfBirthAsync', Promise.resolve(new Date(0))); // Assuming string for date
|
|
161
163
|
exports.getFitzpatrickSkinTypeAsync = UnavailableFnFromModule('getFitzpatrickSkinTypeAsync', Promise.resolve(Characteristics_1.FitzpatrickSkinType.notSet));
|
|
162
164
|
exports.getWheelchairUseAsync = UnavailableFnFromModule('getWheelchairUseAsync', Promise.resolve(Characteristics_1.WheelchairUse.notSet));
|
|
163
|
-
|
|
165
|
+
const subscribeToQuantitySamples = UnavailableFnFromModule('subscribeToQuantitySamples', {
|
|
166
|
+
remove: () => false,
|
|
167
|
+
}); // Mocking the observer query UUID
|
|
168
|
+
exports.subscribeToQuantitySamples = subscribeToQuantitySamples;
|
|
169
|
+
const useSubscribeToQuantitySamples = UnavailableFnFromModule('useSubscribeToQuantitySamples', undefined); // Mocking callback structure
|
|
170
|
+
exports.useSubscribeToQuantitySamples = useSubscribeToQuantitySamples;
|
|
164
171
|
// --- Default Export ---
|
|
165
172
|
// This attempts to match the structure of the default export from index.ios.ts
|
|
166
173
|
const HealthkitModule = {
|
|
167
174
|
// All named exports are also part of the default export object
|
|
168
175
|
authorizationStatusFor: exports.authorizationStatusFor,
|
|
169
176
|
isObjectTypeAvailable: exports.isObjectTypeAvailable,
|
|
170
|
-
unsubscribeQueries: exports.unsubscribeQueries,
|
|
171
177
|
isObjectTypeAvailableAsync: exports.isObjectTypeAvailableAsync,
|
|
172
178
|
areObjectTypesAvailable: exports.areObjectTypesAvailable,
|
|
173
179
|
areObjectTypesAvailableAsync: exports.areObjectTypesAvailableAsync,
|
|
@@ -213,6 +219,8 @@ const HealthkitModule = {
|
|
|
213
219
|
isProtectedDataAvailable: exports.isProtectedDataAvailable,
|
|
214
220
|
queryStateOfMindSamples: exports.queryStateOfMindSamples,
|
|
215
221
|
saveStateOfMindSample: exports.saveStateOfMindSample,
|
|
222
|
+
subscribeToQuantitySamples,
|
|
223
|
+
useSubscribeToQuantitySamples,
|
|
216
224
|
// Hooks
|
|
217
225
|
useMostRecentCategorySample,
|
|
218
226
|
useMostRecentQuantitySample: exports.useMostRecentQuantitySample,
|
|
@@ -8,21 +8,27 @@ const modules_1 = require("../modules");
|
|
|
8
8
|
* @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614152-requestauthorization Apple Docs - requestAuthorization}
|
|
9
9
|
* @see {@link https://developer.apple.com/documentation/healthkit/authorizing_access_to_health_data Apple Docs - Authorizing access to health data}
|
|
10
10
|
*/
|
|
11
|
-
const useHealthkitAuthorization = (
|
|
11
|
+
const useHealthkitAuthorization = ({ toWrite, toRead, }) => {
|
|
12
12
|
const [status, setStatus] = (0, react_1.useState)(null);
|
|
13
|
-
const readMemo = (0, react_1.useRef)(
|
|
14
|
-
const writeMemo = (0, react_1.useRef)(
|
|
13
|
+
const readMemo = (0, react_1.useRef)(toRead);
|
|
14
|
+
const writeMemo = (0, react_1.useRef)(toWrite);
|
|
15
15
|
(0, react_1.useEffect)(() => {
|
|
16
|
-
readMemo.current =
|
|
17
|
-
writeMemo.current =
|
|
18
|
-
}, [
|
|
16
|
+
readMemo.current = toRead;
|
|
17
|
+
writeMemo.current = toWrite;
|
|
18
|
+
}, [toRead, toWrite]);
|
|
19
19
|
const refreshAuthStatus = (0, react_1.useCallback)(async () => {
|
|
20
|
-
const auth = await modules_1.Core.getRequestStatusForAuthorization(
|
|
20
|
+
const auth = await modules_1.Core.getRequestStatusForAuthorization({
|
|
21
|
+
toShare: writeMemo.current,
|
|
22
|
+
toRead: readMemo.current,
|
|
23
|
+
});
|
|
21
24
|
setStatus(auth);
|
|
22
25
|
return auth;
|
|
23
26
|
}, []);
|
|
24
27
|
const request = (0, react_1.useCallback)(async () => {
|
|
25
|
-
await modules_1.Core.requestAuthorization(
|
|
28
|
+
await modules_1.Core.requestAuthorization({
|
|
29
|
+
toShare: writeMemo.current,
|
|
30
|
+
toRead: readMemo.current,
|
|
31
|
+
});
|
|
26
32
|
return refreshAuthStatus();
|
|
27
33
|
}, [refreshAuthStatus]);
|
|
28
34
|
(0, react_1.useEffect)(() => {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useSubscribeToQuantitySamples = useSubscribeToQuantitySamples;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const subscribeToQuantitySamples_1 = require("../utils/subscribeToQuantitySamples");
|
|
6
|
+
function useSubscribeToQuantitySamples(identifier, onChange) {
|
|
7
|
+
const onChangeRef = (0, react_1.useRef)(onChange);
|
|
8
|
+
(0, react_1.useEffect)(() => {
|
|
9
|
+
onChangeRef.current = onChange;
|
|
10
|
+
}, [onChange]);
|
|
11
|
+
(0, react_1.useEffect)(() => {
|
|
12
|
+
const subscription = (0, subscribeToQuantitySamples_1.subscribeToQuantitySamples)(identifier, (args) => {
|
|
13
|
+
onChangeRef.current(args);
|
|
14
|
+
});
|
|
15
|
+
return () => {
|
|
16
|
+
subscription.remove();
|
|
17
|
+
};
|
|
18
|
+
}, [identifier]);
|
|
19
|
+
}
|
|
20
|
+
exports.default = useSubscribeToQuantitySamples;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.subscribeToQuantitySamples = void 0;
|
|
4
|
+
const modules_1 = require("../modules");
|
|
5
|
+
const subscribeToChanges_1 = require("./subscribeToChanges");
|
|
6
|
+
const subscribeToQuantitySamples = (identifier, callback, after) => {
|
|
7
|
+
let anchor;
|
|
8
|
+
const afterDate = after ?? new Date();
|
|
9
|
+
const init = async () => {
|
|
10
|
+
// we need to do an initial query to get a handle for the deletedSamples
|
|
11
|
+
const { newAnchor } = await modules_1.QuantityTypes.queryQuantitySamplesWithAnchor(identifier, {
|
|
12
|
+
filter: {
|
|
13
|
+
startDate: afterDate,
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
anchor = newAnchor;
|
|
17
|
+
};
|
|
18
|
+
init();
|
|
19
|
+
return (0, subscribeToChanges_1.subscribeToChanges)(identifier, async ({ errorMessage }) => {
|
|
20
|
+
if (errorMessage) {
|
|
21
|
+
return callback({
|
|
22
|
+
typeIdentifier: identifier,
|
|
23
|
+
errorMessage,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
// seems like all deletedSamples are included when no anchor is provided, so we don't want to return those for the first query
|
|
27
|
+
const hadAnchorWhenDoingQuery = !!anchor;
|
|
28
|
+
const { samples, newAnchor, deletedSamples } = await modules_1.QuantityTypes.queryQuantitySamplesWithAnchor(identifier, {
|
|
29
|
+
anchor,
|
|
30
|
+
filter: {
|
|
31
|
+
startDate: afterDate,
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
anchor = newAnchor;
|
|
35
|
+
const hasNewSamples = samples.length > 0 ||
|
|
36
|
+
(deletedSamples.length > 0 && hadAnchorWhenDoingQuery);
|
|
37
|
+
if (hasNewSamples) {
|
|
38
|
+
callback({
|
|
39
|
+
typeIdentifier: identifier,
|
|
40
|
+
samples,
|
|
41
|
+
anchor: newAnchor,
|
|
42
|
+
deletedSamples: hadAnchorWhenDoingQuery ? deletedSamples : [],
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
exports.subscribeToQuantitySamples = subscribeToQuantitySamples;
|
|
@@ -7,14 +7,17 @@ import useMostRecentWorkout from './hooks/useMostRecentWorkout';
|
|
|
7
7
|
import useSources from './hooks/useSources';
|
|
8
8
|
import useStatisticsForQuantity from './hooks/useStatisticsForQuantity';
|
|
9
9
|
import useSubscribeToChanges from './hooks/useSubscribeToChanges';
|
|
10
|
+
import useSubscribeToQuantitySamples from './hooks/useSubscribeToQuantitySamples';
|
|
10
11
|
import { CategoryTypes, Characteristics, Core, CorrelationTypes, Electrocardiograms, HeartbeatSeries, QuantityTypes, StateOfMind, Workouts, } from './modules';
|
|
11
12
|
import getMostRecentCategorySample from './utils/getMostRecentCategorySample';
|
|
12
13
|
import getMostRecentQuantitySample from './utils/getMostRecentQuantitySample';
|
|
13
14
|
import getMostRecentWorkout from './utils/getMostRecentWorkout';
|
|
14
15
|
import getPreferredUnit from './utils/getPreferredUnit';
|
|
16
|
+
import { subscribeToChanges } from './utils/subscribeToChanges';
|
|
17
|
+
import { subscribeToQuantitySamples } from './utils/subscribeToQuantitySamples';
|
|
15
18
|
export * from './types';
|
|
16
19
|
const currentMajorVersionIOS = Platform.OS === 'ios' ? Number.parseInt(Platform.Version, 10) : 0;
|
|
17
|
-
export { getMostRecentCategorySample, getMostRecentQuantitySample, getMostRecentWorkout, getPreferredUnit,
|
|
20
|
+
export { getMostRecentCategorySample, getMostRecentQuantitySample, getMostRecentWorkout, getPreferredUnit, subscribeToChanges, subscribeToQuantitySamples, useHealthkitAuthorization, useIsHealthDataAvailable, useMostRecentCategorySample, useMostRecentQuantitySample, useMostRecentWorkout, useSources, useStatisticsForQuantity, useSubscribeToChanges, useSubscribeToQuantitySamples, };
|
|
18
21
|
// Named exports - all functions bound to their respective modules
|
|
19
22
|
export const authorizationStatusFor = Core.authorizationStatusFor.bind(Core);
|
|
20
23
|
export const disableAllBackgroundDelivery = Core.disableAllBackgroundDelivery.bind(Core);
|
|
@@ -49,13 +52,11 @@ export const saveCategorySample = CategoryTypes.saveCategorySample.bind(Category
|
|
|
49
52
|
export const saveCorrelationSample = CorrelationTypes.saveCorrelationSample.bind(CorrelationTypes);
|
|
50
53
|
export const saveQuantitySample = QuantityTypes.saveQuantitySample.bind(QuantityTypes);
|
|
51
54
|
export const saveWorkoutSample = Workouts.saveWorkoutSample.bind(Workouts);
|
|
52
|
-
export const subscribeToChanges = Core.subscribeToObserverQuery.bind(Core);
|
|
53
55
|
export const startWatchApp = Workouts.startWatchAppWithWorkoutConfiguration.bind(Workouts);
|
|
54
56
|
export const isProtectedDataAvailable = Core.isProtectedDataAvailable.bind(Core);
|
|
55
57
|
export const queryStateOfMindSamples = StateOfMind.queryStateOfMindSamples.bind(StateOfMind);
|
|
56
58
|
export const saveStateOfMindSample = StateOfMind.saveStateOfMindSample.bind(StateOfMind);
|
|
57
59
|
export const isQuantityCompatibleWithUnit = QuantityTypes.isQuantityCompatibleWithUnit.bind(QuantityTypes);
|
|
58
|
-
export const unsubscribeQueries = Core.unsubscribeQueries.bind(Core);
|
|
59
60
|
export const isObjectTypeAvailable = Core.isObjectTypeAvailable.bind(Core);
|
|
60
61
|
export const isObjectTypeAvailableAsync = Core.isObjectTypeAvailableAsync.bind(Core);
|
|
61
62
|
export const areObjectTypesAvailable = Core.areObjectTypesAvailable.bind(Core);
|
|
@@ -114,7 +115,7 @@ export default {
|
|
|
114
115
|
saveQuantitySample,
|
|
115
116
|
saveWorkoutSample,
|
|
116
117
|
subscribeToChanges,
|
|
117
|
-
|
|
118
|
+
subscribeToQuantitySamples,
|
|
118
119
|
startWatchApp,
|
|
119
120
|
isProtectedDataAvailable,
|
|
120
121
|
queryStateOfMindSamples,
|
|
@@ -124,6 +125,7 @@ export default {
|
|
|
124
125
|
useMostRecentQuantitySample,
|
|
125
126
|
useMostRecentWorkout,
|
|
126
127
|
useSubscribeToChanges,
|
|
128
|
+
useSubscribeToQuantitySamples,
|
|
127
129
|
useHealthkitAuthorization,
|
|
128
130
|
useIsHealthDataAvailable,
|
|
129
131
|
useSources,
|
package/lib/module/healthkit.js
CHANGED
|
@@ -27,7 +27,9 @@ export const isHealthDataAvailableAsync = UnavailableFnFromModule('isHealthDataA
|
|
|
27
27
|
export const querySources = UnavailableFnFromModule('querySources', Promise.resolve([]));
|
|
28
28
|
export const requestAuthorization = UnavailableFnFromModule('requestAuthorization', Promise.resolve(false));
|
|
29
29
|
export const deleteObjects = UnavailableFnFromModule('deleteObjects', Promise.resolve(0));
|
|
30
|
-
export const subscribeToChanges = UnavailableFnFromModule('subscribeToChanges',
|
|
30
|
+
export const subscribeToChanges = UnavailableFnFromModule('subscribeToChanges', {
|
|
31
|
+
remove: () => false,
|
|
32
|
+
}); // Mocking the observer query UUID
|
|
31
33
|
export const isProtectedDataAvailable = UnavailableFnFromModule('isProtectedDataAvailable', false);
|
|
32
34
|
export const isObjectTypeAvailable = UnavailableFnFromModule('isObjectTypeAvailable', false);
|
|
33
35
|
export const isObjectTypeAvailableAsync = UnavailableFnFromModule('isObjectTypeAvailableAsync', Promise.resolve(false));
|
|
@@ -138,14 +140,18 @@ export const getBloodTypeAsync = UnavailableFnFromModule('getBloodTypeAsync', Pr
|
|
|
138
140
|
export const getDateOfBirthAsync = UnavailableFnFromModule('getDateOfBirthAsync', Promise.resolve(new Date(0))); // Assuming string for date
|
|
139
141
|
export const getFitzpatrickSkinTypeAsync = UnavailableFnFromModule('getFitzpatrickSkinTypeAsync', Promise.resolve(FitzpatrickSkinType.notSet));
|
|
140
142
|
export const getWheelchairUseAsync = UnavailableFnFromModule('getWheelchairUseAsync', Promise.resolve(WheelchairUse.notSet));
|
|
141
|
-
|
|
143
|
+
const subscribeToQuantitySamples = UnavailableFnFromModule('subscribeToQuantitySamples', {
|
|
144
|
+
remove: () => false,
|
|
145
|
+
}); // Mocking the observer query UUID
|
|
146
|
+
export { subscribeToQuantitySamples };
|
|
147
|
+
const useSubscribeToQuantitySamples = UnavailableFnFromModule('useSubscribeToQuantitySamples', undefined); // Mocking callback structure
|
|
148
|
+
export { useSubscribeToQuantitySamples };
|
|
142
149
|
// --- Default Export ---
|
|
143
150
|
// This attempts to match the structure of the default export from index.ios.ts
|
|
144
151
|
const HealthkitModule = {
|
|
145
152
|
// All named exports are also part of the default export object
|
|
146
153
|
authorizationStatusFor,
|
|
147
154
|
isObjectTypeAvailable,
|
|
148
|
-
unsubscribeQueries,
|
|
149
155
|
isObjectTypeAvailableAsync,
|
|
150
156
|
areObjectTypesAvailable,
|
|
151
157
|
areObjectTypesAvailableAsync,
|
|
@@ -191,6 +197,8 @@ const HealthkitModule = {
|
|
|
191
197
|
isProtectedDataAvailable,
|
|
192
198
|
queryStateOfMindSamples,
|
|
193
199
|
saveStateOfMindSample,
|
|
200
|
+
subscribeToQuantitySamples,
|
|
201
|
+
useSubscribeToQuantitySamples,
|
|
194
202
|
// Hooks
|
|
195
203
|
useMostRecentCategorySample,
|
|
196
204
|
useMostRecentQuantitySample,
|
|
@@ -5,21 +5,27 @@ import { Core } from '../modules';
|
|
|
5
5
|
* @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614152-requestauthorization Apple Docs - requestAuthorization}
|
|
6
6
|
* @see {@link https://developer.apple.com/documentation/healthkit/authorizing_access_to_health_data Apple Docs - Authorizing access to health data}
|
|
7
7
|
*/
|
|
8
|
-
export const useHealthkitAuthorization = (
|
|
8
|
+
export const useHealthkitAuthorization = ({ toWrite, toRead, }) => {
|
|
9
9
|
const [status, setStatus] = useState(null);
|
|
10
|
-
const readMemo = useRef(
|
|
11
|
-
const writeMemo = useRef(
|
|
10
|
+
const readMemo = useRef(toRead);
|
|
11
|
+
const writeMemo = useRef(toWrite);
|
|
12
12
|
useEffect(() => {
|
|
13
|
-
readMemo.current =
|
|
14
|
-
writeMemo.current =
|
|
15
|
-
}, [
|
|
13
|
+
readMemo.current = toRead;
|
|
14
|
+
writeMemo.current = toWrite;
|
|
15
|
+
}, [toRead, toWrite]);
|
|
16
16
|
const refreshAuthStatus = useCallback(async () => {
|
|
17
|
-
const auth = await Core.getRequestStatusForAuthorization(
|
|
17
|
+
const auth = await Core.getRequestStatusForAuthorization({
|
|
18
|
+
toShare: writeMemo.current,
|
|
19
|
+
toRead: readMemo.current,
|
|
20
|
+
});
|
|
18
21
|
setStatus(auth);
|
|
19
22
|
return auth;
|
|
20
23
|
}, []);
|
|
21
24
|
const request = useCallback(async () => {
|
|
22
|
-
await Core.requestAuthorization(
|
|
25
|
+
await Core.requestAuthorization({
|
|
26
|
+
toShare: writeMemo.current,
|
|
27
|
+
toRead: readMemo.current,
|
|
28
|
+
});
|
|
23
29
|
return refreshAuthStatus();
|
|
24
30
|
}, [refreshAuthStatus]);
|
|
25
31
|
useEffect(() => {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
import { subscribeToQuantitySamples } from '../utils/subscribeToQuantitySamples';
|
|
3
|
+
export function useSubscribeToQuantitySamples(identifier, onChange) {
|
|
4
|
+
const onChangeRef = useRef(onChange);
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
onChangeRef.current = onChange;
|
|
7
|
+
}, [onChange]);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
const subscription = subscribeToQuantitySamples(identifier, (args) => {
|
|
10
|
+
onChangeRef.current(args);
|
|
11
|
+
});
|
|
12
|
+
return () => {
|
|
13
|
+
subscription.remove();
|
|
14
|
+
};
|
|
15
|
+
}, [identifier]);
|
|
16
|
+
}
|
|
17
|
+
export default useSubscribeToQuantitySamples;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { QuantityTypes } from '../modules';
|
|
2
|
+
import { subscribeToChanges } from './subscribeToChanges';
|
|
3
|
+
export const subscribeToQuantitySamples = (identifier, callback, after) => {
|
|
4
|
+
let anchor;
|
|
5
|
+
const afterDate = after ?? new Date();
|
|
6
|
+
const init = async () => {
|
|
7
|
+
// we need to do an initial query to get a handle for the deletedSamples
|
|
8
|
+
const { newAnchor } = await QuantityTypes.queryQuantitySamplesWithAnchor(identifier, {
|
|
9
|
+
filter: {
|
|
10
|
+
startDate: afterDate,
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
anchor = newAnchor;
|
|
14
|
+
};
|
|
15
|
+
init();
|
|
16
|
+
return subscribeToChanges(identifier, async ({ errorMessage }) => {
|
|
17
|
+
if (errorMessage) {
|
|
18
|
+
return callback({
|
|
19
|
+
typeIdentifier: identifier,
|
|
20
|
+
errorMessage,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
// seems like all deletedSamples are included when no anchor is provided, so we don't want to return those for the first query
|
|
24
|
+
const hadAnchorWhenDoingQuery = !!anchor;
|
|
25
|
+
const { samples, newAnchor, deletedSamples } = await QuantityTypes.queryQuantitySamplesWithAnchor(identifier, {
|
|
26
|
+
anchor,
|
|
27
|
+
filter: {
|
|
28
|
+
startDate: afterDate,
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
anchor = newAnchor;
|
|
32
|
+
const hasNewSamples = samples.length > 0 ||
|
|
33
|
+
(deletedSamples.length > 0 && hadAnchorWhenDoingQuery);
|
|
34
|
+
if (hasNewSamples) {
|
|
35
|
+
callback({
|
|
36
|
+
typeIdentifier: identifier,
|
|
37
|
+
samples,
|
|
38
|
+
anchor: newAnchor,
|
|
39
|
+
deletedSamples: hadAnchorWhenDoingQuery ? deletedSamples : [],
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
};
|