diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index f75ed932..66628427 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -3,7 +3,7 @@ name: Bug report about: Create a report to help us improve title: '' labels: bug -assignees: lucaspbordignon +assignees: @ornament-health/mobiledev --- **Describe the bug** diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 3ade1769..1fe49f78 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -3,7 +3,7 @@ name: Feature request about: Suggest an idea for this project title: '' labels: enhancement -assignees: lucaspbordignon +assignees: @ornament-health/mobiledev --- **Is your feature request related to a problem? Please describe.** diff --git a/RCTAppleHealthKit/Types/RCTAggregatorType.h b/RCTAppleHealthKit/RCTAggregatorType.h similarity index 100% rename from RCTAppleHealthKit/Types/RCTAggregatorType.h rename to RCTAppleHealthKit/RCTAggregatorType.h diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m index 4145f141..74d10b25 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m @@ -43,6 +43,8 @@ - (nullable HKObjectType *)getReadPermFromText:(nonnull NSString*)key { return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMassIndex]; } else if ([@"LeanBodyMass" isEqualToString: key]) { return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierLeanBodyMass]; + } else if ([@"AppleSleepingWristTemperature" isEqualToString: key] && systemVersion >= 16.0) { + return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierAppleSleepingWristTemperature]; } // Hearing Identifiers @@ -81,6 +83,8 @@ - (nullable HKObjectType *)getReadPermFromText:(nonnull NSString*)key { return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierNikeFuel]; } else if ([@"AppleExerciseTime" isEqualToString: key] && systemVersion >= 9.3) { return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierAppleExerciseTime]; + } else if ([@"DistanceWheelchair" isEqualToString: key] && systemVersion >= 10.0) { + return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWheelchair]; } else if ([@"AppleStandHour" isEqualToString: key]) { return [HKObjectType quantityTypeForIdentifier:HKCategoryTypeIdentifierAppleStandHour]; } else if ([@"RunningPower" isEqualToString:key]) { @@ -320,6 +324,10 @@ - (nullable HKObjectType *)getReadPermFromText:(nonnull NSString*)key { return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierRespiratoryRate]; } else if ([@"OxygenSaturation" isEqualToString: key]) { return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierOxygenSaturation]; + } else if ([@"heartRateRecoveryOneMinute" isEqualToString: key] && systemVersion >= 16.0) { + return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRateRecoveryOneMinute]; + } else if ([@"AtrialFibrillationBurden" isEqualToString: key] && systemVersion >= 16.0) { + return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierAtrialFibrillationBurden]; } if (@available(iOS 12.2, *)) { if ([@"HighHeartRateEvent" isEqualToString: key]) { @@ -415,13 +423,19 @@ - (nullable HKObjectType *)getReadPermFromText:(nonnull NSString*)key { return [HKObjectType workoutType]; } else if ([@"Workout" isEqualToString: key]) { return [HKObjectType workoutType]; - }else if ([@"WorkoutRoute" isEqualToString:key]){ + } else if ([@"WorkoutRoute" isEqualToString:key]){ return [HKSeriesType workoutRouteType]; } // Lab and tests if ([@"BloodAlcoholContent" isEqualToString: key]) { return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodAlcoholContent]; + } else if ([@"NumberOfTimesFallen" isEqualToString:key]) { + return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierNumberOfTimesFallen]; + } else if ([@"PeakExpiratoryFlowRate" isEqualToString:key]) { + return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierPeakExpiratoryFlowRate]; + } else if ([@"PeripheralPerfusionIndex" isEqualToString:key]) { + return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierPeripheralPerfusionIndex]; } // Activity Summary diff --git a/RCTAppleHealthKit/RCTAppleHealthKit.m b/RCTAppleHealthKit/RCTAppleHealthKit.m index 4486c2b8..9efffdd6 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit.m @@ -707,6 +707,18 @@ + (BOOL)requiresMainQueueSetup [self statistics_getStatisticDietarySugar:input callback:callback]; } +RCT_EXPORT_METHOD(getStatisticDietaryFatMonounsaturated:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryFatMonounsaturated:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticDietaryFatPolyunsaturated:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryFatPolyunsaturated:input callback:callback]; +} + RCT_EXPORT_METHOD(getStatisticDietaryFatSaturated:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) { [self _initializeHealthStore]; @@ -725,18 +737,96 @@ + (BOOL)requiresMainQueueSetup [self statistics_getStatisticDietaryCarbohydrates:input callback:callback]; } +RCT_EXPORT_METHOD(getStatisticDietaryThiamin:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryThiamin:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticDietaryRiboflavin:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryRiboflavin:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticDietaryNiacin:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryNiacin:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticDietaryPantothenicAcid:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryPantothenicAcid:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticDietaryVitaminB6:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryVitaminB6:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticDietaryBiotin:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryBiotin:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticDietaryVitaminB12:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryVitaminB12:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticDietaryVitaminE:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryVitaminE:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticDietaryVitaminK:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryVitaminK:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticDietaryFolate:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryFolate:input callback:callback]; +} + RCT_EXPORT_METHOD(getStatisticDietaryCalcium:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) { [self _initializeHealthStore]; [self statistics_getStatisticDietaryCalcium:input callback:callback]; } +RCT_EXPORT_METHOD(getStatisticDietaryChloride:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryChloride:input callback:callback]; +} + RCT_EXPORT_METHOD(getStatisticDietaryIron:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) { [self _initializeHealthStore]; [self statistics_getStatisticDietaryIron:input callback:callback]; } +RCT_EXPORT_METHOD(getStatisticDietaryMagnesium:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryMagnesium:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticDietaryPhosphorus:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryPhosphorus:input callback:callback]; +} + RCT_EXPORT_METHOD(getStatisticDietaryPotassium:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) { [self _initializeHealthStore]; @@ -767,12 +857,114 @@ + (BOOL)requiresMainQueueSetup [self statistics_getStatisticDietaryVitaminD:input callback:callback]; } +RCT_EXPORT_METHOD(getStatisticDietaryZinc:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryZinc:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticDietaryCaffeine:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryCaffeine:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticDietaryChromium:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryChromium:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticDietaryCopper:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryCopper:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticDietaryIodine:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryIodine:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticDietaryManganese:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryManganese:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticDietaryMolybdenum:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietaryMolybdenum:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticDietarySelenium:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDietarySelenium:input callback:callback]; +} + RCT_EXPORT_METHOD(getStatisticInsulinDelivery:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) { [self _initializeHealthStore]; [self statistics_getStatisticInsulinDelivery:input callback:callback]; } +RCT_EXPORT_METHOD(getStatisticDistanceWheelchair:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticDistanceWheelchair:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticAppleExerciseTime:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticAppleExerciseTime:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticAppleSleepingWristTemperature:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticAppleSleepingWristTemperature:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticHeartRateRecoveryOneMinute:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticHeartRateRecoveryOneMinute:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticAtrialFibrillationBurden:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticAtrialFibrillationBurden:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticNumberOfTimesFallen:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticNumberOfTimesFallen:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticPeakExpiratoryFlowRate:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticPeakExpiratoryFlowRate:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticPeripheralPerfusionIndex:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticPeripheralPerfusionIndex:input callback:callback]; +} + +RCT_EXPORT_METHOD(getStatisticUvExposure:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self _initializeHealthStore]; + [self statistics_getStatisticUvExposure:input callback:callback]; +} + RCT_EXPORT_METHOD(getMedianStatistic:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) { [self _initializeHealthStore]; @@ -876,9 +1068,9 @@ - (void)initializeHealthKit:(NSDictionary *)input callback:(RCTResponseSenderBlo @"SleepAnalysis", @"InsulinDelivery" ]; - + NSArray *templates = @[@"healthKit:%@:new", @"healthKit:%@:failure", @"healthKit:%@:enabled", @"healthKit:%@:sample", @"healthKit:%@:setup:success", @"healthKit:%@:setup:failure"]; - + NSMutableArray *supportedEvents = [[NSMutableArray alloc] init]; for(NSString * type in types) { @@ -904,7 +1096,7 @@ - (void)getModuleInfo:(NSDictionary *)input callback:(RCTResponseSenderBlock)cal - (void)getAuthorizationStatus:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { - + [self _initializeHealthStore]; if ([HKHealthStore isHealthDataAvailable]) { @@ -977,7 +1169,7 @@ - (void)initializeBackgroundObservers:(RCTBridge *)bridge for(NSString * type in fitnessObservers) { [self fitness_registerObserver:type bridge:bridge hasListeners:hasListeners]; } - + NSArray *clinicalObservers = @[ @"AllergyRecord", @"ConditionRecord", @@ -988,11 +1180,11 @@ - (void)initializeBackgroundObservers:(RCTBridge *)bridge @"ProcedureRecord", @"VitalSignRecord" ]; - + for(NSString * type in clinicalObservers) { [self clinical_registerObserver:type bridge:bridge hasListeners:hasListeners]; } - + [self results_registerObservers:bridge hasListeners:hasListeners]; NSLog(@"[HealthKit] Background observers added to the app"); diff --git a/RCTAppleHealthKit/Types/RCTInterval.h b/RCTAppleHealthKit/RCTInterval.h similarity index 100% rename from RCTAppleHealthKit/Types/RCTInterval.h rename to RCTAppleHealthKit/RCTInterval.h diff --git a/RCTAppleHealthKit/Types/RCTStatisticRequest.h b/RCTAppleHealthKit/RCTStatisticRequest.h similarity index 100% rename from RCTAppleHealthKit/Types/RCTStatisticRequest.h rename to RCTAppleHealthKit/RCTStatisticRequest.h diff --git a/RCTAppleHealthKit/Types/RCTStatisticRequest.m b/RCTAppleHealthKit/RCTStatisticRequest.m similarity index 100% rename from RCTAppleHealthKit/Types/RCTStatisticRequest.m rename to RCTAppleHealthKit/RCTStatisticRequest.m diff --git a/RCTAppleHealthKit/RCTTypes.h b/RCTAppleHealthKit/RCTTypes.h index 55ac2b16..09fcdac8 100644 --- a/RCTAppleHealthKit/RCTTypes.h +++ b/RCTAppleHealthKit/RCTTypes.h @@ -3,6 +3,6 @@ // Copyright (c) 2021 Greg Wilson. All rights reserved. // -#import "Types/RCTInterval.h" -#import "Types/RCTAggregatorType.h" -#import "Types/RCTStatisticRequest.h" +#import "RCTInterval.h" +#import "RCTAggregatorType.h" +#import "RCTStatisticRequest.h" diff --git a/RCTAppleHealthKit/RTCAppleHealthKit+Methods_Statistics.h b/RCTAppleHealthKit/RTCAppleHealthKit+Methods_Statistics.h index a3db63ea..641afc0e 100644 --- a/RCTAppleHealthKit/RTCAppleHealthKit+Methods_Statistics.h +++ b/RCTAppleHealthKit/RTCAppleHealthKit+Methods_Statistics.h @@ -22,25 +22,94 @@ - (void)statistics_getStatisticOxygenSaturation:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)statistics_getStatisticRestingHeartRate:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; -// Dietary +// MARK: - Dietary + +// MARK: - Macronutrients - (void)statistics_getStatisticDietaryEnergyConsumed:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)statistics_getStatisticDietaryProtein:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)statistics_getStatisticDietaryFiber:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)statistics_getStatisticDietaryTotalFat:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; -- (void)statistics_getStatisticDietaryWater:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)statistics_getStatisticDietarySugar:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryFatMonounsaturated:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryFatPolyunsaturated:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)statistics_getStatisticDietaryFatSaturated:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)statistics_getStatisticDietaryCholesterol:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)statistics_getStatisticDietaryCarbohydrates:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; + +// MARK: - Vitamins + +- (void)statistics_getStatisticDietaryVitaminA:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryThiamin:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryRiboflavin:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryNiacin:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryPantothenicAcid:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryVitaminB6:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryBiotin:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryVitaminB12:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryVitaminC:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryVitaminD:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryVitaminE:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryVitaminK:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryFolate:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; + +// MARK: - Minerals + - (void)statistics_getStatisticDietaryCalcium:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryChloride:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)statistics_getStatisticDietaryIron:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryMagnesium:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryPhosphorus:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)statistics_getStatisticDietaryPotassium:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)statistics_getStatisticDietarySodium:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; -- (void)statistics_getStatisticDietaryVitaminA:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; -- (void)statistics_getStatisticDietaryVitaminC:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; -- (void)statistics_getStatisticDietaryVitaminD:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryZinc:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; + +// MARK: - Hydration + +- (void)statistics_getStatisticDietaryWater:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; + +// MARK: - Caffeination + +- (void)statistics_getStatisticDietaryCaffeine:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; + +// MARK: - Ultratrace Minerals + +- (void)statistics_getStatisticDietaryChromium:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryCopper:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryIodine:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryManganese:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietaryMolybdenum:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)statistics_getStatisticDietarySelenium:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; + - (void)statistics_getStatisticInsulinDelivery:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +// MARK: - Activity + +- (void)statistics_getStatisticDistanceWheelchair:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; + +- (void)statistics_getStatisticAppleExerciseTime:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; + +// MARK: - Body Measurments + +- (void)statistics_getStatisticAppleSleepingWristTemperature:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; + +// MARK: - Vital Signs + +- (void)statistics_getStatisticHeartRateRecoveryOneMinute:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; + +- (void)statistics_getStatisticAtrialFibrillationBurden:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; + +// MARK: - Lab And Test Results + +- (void)statistics_getStatisticNumberOfTimesFallen:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; + +- (void)statistics_getStatisticPeakExpiratoryFlowRate:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; + +- (void)statistics_getStatisticPeripheralPerfusionIndex:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; + +// MARK: - UV Exposure + +- (void)statistics_getStatisticUvExposure:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; + @end diff --git a/RCTAppleHealthKit/RTCAppleHealthKit+Methods_Statistics.m b/RCTAppleHealthKit/RTCAppleHealthKit+Methods_Statistics.m index 1707eea3..0ff49933 100644 --- a/RCTAppleHealthKit/RTCAppleHealthKit+Methods_Statistics.m +++ b/RCTAppleHealthKit/RTCAppleHealthKit+Methods_Statistics.m @@ -104,226 +104,481 @@ - (void)statistics_getStatisticRestingHeartRate:(NSDictionary *)input callback:( } // MARK: - Dietary +// MARK: - Macronutrients - (void)statistics_getStatisticDietaryEnergyConsumed:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { - NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; - if (aggregatorType != 3) { - callback(@[RCTMakeError(@"aggregator should be CUMULATIVE_SUM = 3", nil, nil)]); - return; - } - HKUnit *unit = HKUnit.kilocalorieUnit; - [self basicStatisticsRequest:input + [self basicDietaryStatisticsRequest:input callback:callback quantity:HKQuantityTypeIdentifierDietaryEnergyConsumed unit:unit]; } - (void)statistics_getStatisticDietaryProtein:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { - NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; - if (aggregatorType != 3) { - callback(@[RCTMakeError(@"aggregator should be CUMULATIVE_SUM = 3", nil, nil)]); - return; - } HKUnit *unit = HKUnit.gramUnit; - [self basicStatisticsRequest:input + [self basicDietaryStatisticsRequest:input callback:callback quantity:HKQuantityTypeIdentifierDietaryProtein unit:unit]; } - (void)statistics_getStatisticDietaryFiber:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { - NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; - if (aggregatorType != 3) { - callback(@[RCTMakeError(@"aggregator should be CUMULATIVE_SUM = 3", nil, nil)]); - return; - } HKUnit *unit = HKUnit.gramUnit; - [self basicStatisticsRequest:input + [self basicDietaryStatisticsRequest:input callback:callback quantity:HKQuantityTypeIdentifierDietaryFiber unit:unit]; } - (void)statistics_getStatisticDietaryTotalFat:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { - NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; - if (aggregatorType != 3) { - callback(@[RCTMakeError(@"aggregator should be CUMULATIVE_SUM = 3", nil, nil)]); - return; - } HKUnit *unit = HKUnit.gramUnit; - [self basicStatisticsRequest:input + [self basicDietaryStatisticsRequest:input callback:callback quantity:HKQuantityTypeIdentifierDietaryFatTotal unit:unit]; } -- (void)statistics_getStatisticDietaryWater:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { - NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; - if (aggregatorType != 3) { - callback(@[RCTMakeError(@"aggregator should be CUMULATIVE_SUM = 3", nil, nil)]); - return; - } - HKUnit *unit = HKUnit.literUnit; - [self basicStatisticsRequest:input +- (void)statistics_getStatisticDietaryFatMonounsaturated:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input callback:callback - quantity:HKQuantityTypeIdentifierDietaryWater + quantity:HKQuantityTypeIdentifierDietaryFatMonounsaturated unit:unit]; } - (void)statistics_getStatisticDietarySugar:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { - NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; - if (aggregatorType != 3) { - callback(@[RCTMakeError(@"aggregator should be CUMULATIVE_SUM = 3", nil, nil)]); - return; - } HKUnit *unit = HKUnit.gramUnit; - [self basicStatisticsRequest:input + [self basicDietaryStatisticsRequest:input callback:callback quantity:HKQuantityTypeIdentifierDietarySugar unit:unit]; } +- (void)statistics_getStatisticDietaryFatPolyunsaturated:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryFatPolyunsaturated + unit:unit]; +} + - (void)statistics_getStatisticDietaryFatSaturated:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { - NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; - if (aggregatorType != 3) { - callback(@[RCTMakeError(@"aggregator should be CUMULATIVE_SUM = 3", nil, nil)]); - return; - } HKUnit *unit = HKUnit.gramUnit; - [self basicStatisticsRequest:input + [self basicDietaryStatisticsRequest:input callback:callback quantity:HKQuantityTypeIdentifierDietaryFatSaturated unit:unit]; } - (void)statistics_getStatisticDietaryCholesterol:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { - NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; - if (aggregatorType != 3) { - callback(@[RCTMakeError(@"aggregator should be CUMULATIVE_SUM = 3", nil, nil)]); - return; - } HKUnit *unit = HKUnit.gramUnit; - [self basicStatisticsRequest:input + [self basicDietaryStatisticsRequest:input callback:callback quantity:HKQuantityTypeIdentifierDietaryCholesterol unit:unit]; } - (void)statistics_getStatisticDietaryCarbohydrates:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { - NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; - if (aggregatorType != 3) { - callback(@[RCTMakeError(@"aggregator should be CUMULATIVE_SUM = 3", nil, nil)]); - return; - } HKUnit *unit = HKUnit.gramUnit; - [self basicStatisticsRequest:input + [self basicDietaryStatisticsRequest:input callback:callback quantity:HKQuantityTypeIdentifierDietaryCarbohydrates unit:unit]; } +// MARK: - Vitamins + +- (void)statistics_getStatisticDietaryVitaminA:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryVitaminA + unit:unit]; +} + +- (void)statistics_getStatisticDietaryThiamin:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryThiamin + unit:unit]; +} + +- (void)statistics_getStatisticDietaryRiboflavin:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryRiboflavin + unit:unit]; +} + +- (void)statistics_getStatisticDietaryNiacin:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryNiacin + unit:unit]; +} + +- (void)statistics_getStatisticDietaryPantothenicAcid:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryPantothenicAcid + unit:unit]; +} + +- (void)statistics_getStatisticDietaryVitaminB6:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryVitaminB6 + unit:unit]; +} + +- (void)statistics_getStatisticDietaryBiotin:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryBiotin + unit:unit]; +} + +- (void)statistics_getStatisticDietaryVitaminB12:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryVitaminB12 + unit:unit]; +} + +- (void)statistics_getStatisticDietaryVitaminC:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryVitaminC + unit:unit]; +} + +- (void)statistics_getStatisticDietaryVitaminD:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryVitaminD + unit:unit]; +} + +- (void)statistics_getStatisticDietaryVitaminE:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryVitaminE + unit:unit]; +} + +- (void)statistics_getStatisticDietaryVitaminK:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryVitaminK + unit:unit]; +} + +- (void)statistics_getStatisticDietaryFolate:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryFolate + unit:unit]; +} + +// MARK: - Minerals + - (void)statistics_getStatisticDietaryCalcium:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { - NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; - if (aggregatorType != 3) { - callback(@[RCTMakeError(@"aggregator should be CUMULATIVE_SUM = 3", nil, nil)]); - return; - } HKUnit *unit = HKUnit.gramUnit; - [self basicStatisticsRequest:input + [self basicDietaryStatisticsRequest:input callback:callback quantity:HKQuantityTypeIdentifierDietaryCalcium unit:unit]; } +- (void)statistics_getStatisticDietaryChloride:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryChloride + unit:unit]; +} + - (void)statistics_getStatisticDietaryIron:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { - NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; - if (aggregatorType != 3) { - callback(@[RCTMakeError(@"aggregator should be CUMULATIVE_SUM = 3", nil, nil)]); - return; - } HKUnit *unit = HKUnit.gramUnit; - [self basicStatisticsRequest:input + [self basicDietaryStatisticsRequest:input callback:callback quantity:HKQuantityTypeIdentifierDietaryIron unit:unit]; } +- (void)statistics_getStatisticDietaryMagnesium:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryMagnesium + unit:unit]; +} + +- (void)statistics_getStatisticDietaryPhosphorus:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryPhosphorus + unit:unit]; +} + - (void)statistics_getStatisticDietaryPotassium:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryPotassium + unit:unit]; +} + +- (void)statistics_getStatisticDietarySodium:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietarySodium + unit:unit]; +} + +- (void)statistics_getStatisticDietaryZinc:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryZinc + unit:unit]; +} + +// MARK: - Hydration + +- (void)statistics_getStatisticDietaryWater:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.literUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryWater + unit:unit]; +} + +// MARK: - Caffeination + +- (void)statistics_getStatisticDietaryCaffeine:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryCaffeine + unit:unit]; +} + +// MARK: - Ultratrace Minerals + +- (void)statistics_getStatisticDietaryChromium:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryChromium + unit:unit]; +} + +- (void)statistics_getStatisticDietaryCopper:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryCopper + unit:unit]; +} + +- (void)statistics_getStatisticDietaryIodine:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryIodine + unit:unit]; +} + +- (void)statistics_getStatisticDietaryManganese:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryManganese + unit:unit]; +} + +- (void)statistics_getStatisticDietaryMolybdenum:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietaryMolybdenum + unit:unit]; +} + +- (void)statistics_getStatisticDietarySelenium:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.gramUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierDietarySelenium + unit:unit]; +} + +- (void)statistics_getStatisticInsulinDelivery:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + HKUnit *unit = HKUnit.internationalUnit; + [self basicDietaryStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierInsulinDelivery + unit:unit]; +} + +// MARK: - Activity + +- (void)statistics_getStatisticDistanceWheelchair:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; if (aggregatorType != 3) { callback(@[RCTMakeError(@"aggregator should be CUMULATIVE_SUM = 3", nil, nil)]); return; } - HKUnit *unit = HKUnit.gramUnit; + HKUnit *unit = HKUnit.meterUnit; [self basicStatisticsRequest:input callback:callback - quantity:HKQuantityTypeIdentifierDietaryPotassium + quantity:HKQuantityTypeIdentifierDistanceWheelchair unit:unit]; } -- (void)statistics_getStatisticDietarySodium:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { +- (void)statistics_getStatisticAppleExerciseTime:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; if (aggregatorType != 3) { callback(@[RCTMakeError(@"aggregator should be CUMULATIVE_SUM = 3", nil, nil)]); return; } - HKUnit *unit = HKUnit.gramUnit; + HKUnit *unit = HKUnit.minuteUnit; [self basicStatisticsRequest:input callback:callback - quantity:HKQuantityTypeIdentifierDietarySodium + quantity:HKQuantityTypeIdentifierAppleExerciseTime unit:unit]; } -- (void)statistics_getStatisticDietaryVitaminA:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { +// MARK: - Body Measurments + +- (void)statistics_getStatisticAppleSleepingWristTemperature:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + if (@available(iOS 16.0, *)) { + NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; + if (aggregatorType == 3) { + callback(@[RCTMakeError(@"aggregator shouldn't be CUMULATIVE_SUM = 3", nil, nil)]); + return; + } + HKUnit *unit = HKUnit.degreeCelsiusUnit; + [self basicStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierAppleSleepingWristTemperature + unit:unit]; + } else { + callback(@[RCTMakeError(@"HKQuantityTypeIdentifierAppleSleepingWristTemperature is only available on iOS 16.0 or newer", nil, nil)]); + return; + } + +} + +// MARK: - Vital Signs + +- (void)statistics_getStatisticHeartRateRecoveryOneMinute:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + if (@available(iOS 16.0, *)) { + NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; + if (aggregatorType == 3) { + callback(@[RCTMakeError(@"aggregator shouldn't be CUMULATIVE_SUM = 3", nil, nil)]); + return; + } + HKUnit *count = [HKUnit countUnit]; + HKUnit *minute = [HKUnit minuteUnit]; + + HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[count unitDividedByUnit:minute]]; + [self basicStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierHeartRateRecoveryOneMinute + unit:unit]; + } else { + callback(@[RCTMakeError(@"HKQuantityTypeIdentifierHeartRateRecoveryOneMinute is only available on iOS 16.0 or newer", nil, nil)]); + return; + } +} + +- (void)statistics_getStatisticAtrialFibrillationBurden:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { + if (@available(iOS 16.0, *)) { + NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; + if (aggregatorType == 3) { + callback(@[RCTMakeError(@"aggregator shouldn't be CUMULATIVE_SUM = 3", nil, nil)]); + return; + } + HKUnit *unit = HKUnit.percentUnit; + [self basicStatisticsRequest:input + callback:callback + quantity:HKQuantityTypeIdentifierAtrialFibrillationBurden + unit:unit]; + } else { + callback(@[RCTMakeError(@"'HKQuantityTypeIdentifierAtrialFibrillationBurden' is only available on iOS 16.0 or newer", nil, nil)]); + return; + } +} + +// MARK: - Lab And Test Results + +- (void)statistics_getStatisticNumberOfTimesFallen:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; if (aggregatorType != 3) { callback(@[RCTMakeError(@"aggregator should be CUMULATIVE_SUM = 3", nil, nil)]); return; } - HKUnit *unit = HKUnit.gramUnit; + HKUnit *unit = HKUnit.countUnit; [self basicStatisticsRequest:input callback:callback - quantity:HKQuantityTypeIdentifierDietaryVitaminA + quantity:HKQuantityTypeIdentifierNumberOfTimesFallen unit:unit]; } -- (void)statistics_getStatisticDietaryVitaminC:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { +- (void)statistics_getStatisticPeakExpiratoryFlowRate:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; - if (aggregatorType != 3) { - callback(@[RCTMakeError(@"aggregator should be CUMULATIVE_SUM = 3", nil, nil)]); + if (aggregatorType == 3) { + callback(@[RCTMakeError(@"aggregator shouldn't be CUMULATIVE_SUM = 3", nil, nil)]); return; } - HKUnit *unit = HKUnit.gramUnit; + HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[[HKUnit literUnit] unitDividedByUnit:[HKUnit minuteUnit]]]; [self basicStatisticsRequest:input callback:callback - quantity:HKQuantityTypeIdentifierDietaryVitaminC + quantity:HKQuantityTypeIdentifierPeakExpiratoryFlowRate unit:unit]; } -- (void)statistics_getStatisticDietaryVitaminD:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { +- (void)statistics_getStatisticPeripheralPerfusionIndex:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; - if (aggregatorType != 3) { - callback(@[RCTMakeError(@"aggregator should be CUMULATIVE_SUM = 3", nil, nil)]); + if (aggregatorType == 3) { + callback(@[RCTMakeError(@"aggregator shouldn't be CUMULATIVE_SUM = 3", nil, nil)]); return; } - HKUnit *unit = HKUnit.gramUnit; + HKUnit *unit = HKUnit.percentUnit; [self basicStatisticsRequest:input callback:callback - quantity:HKQuantityTypeIdentifierDietaryVitaminD + quantity:HKQuantityTypeIdentifierPeripheralPerfusionIndex unit:unit]; } -- (void)statistics_getStatisticInsulinDelivery:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { +// MARK: - UV Exposure + +- (void)statistics_getStatisticUvExposure:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; - if (aggregatorType != 3) { - callback(@[RCTMakeError(@"aggregator should be CUMULATIVE_SUM = 3", nil, nil)]); + if (aggregatorType == 3) { + callback(@[RCTMakeError(@"aggregator shouldn't be CUMULATIVE_SUM = 3", nil, nil)]); return; } - HKUnit *unit = HKUnit.internationalUnit; + HKUnit *unit = HKUnit.countUnit; [self basicStatisticsRequest:input callback:callback - quantity:HKQuantityTypeIdentifierInsulinDelivery + quantity:HKQuantityTypeIdentifierUVExposure unit:unit]; } @@ -439,4 +694,209 @@ - (void)handleStatisticsQuantity:(HKQuantityType *)quantityType }); } +- (void)basicDietaryStatisticsRequest:(NSDictionary *)input + callback:(RCTResponseSenderBlock)callback + quantity:(HKQuantityTypeIdentifier)quantity + unit:(HKUnit *)unit { + + NSUInteger aggregatorType = [RCTAppleHealthKit uintFromOptions:input key:@"aggregator" withDefault:-1]; + + if (aggregatorType == 2) { + [self averageDietaryStatisticsRequest:input + callback:callback + quantity:quantity + unit:unit]; + } else if (aggregatorType == 3) { + [self basicStatisticsRequest:input + callback:callback + quantity:quantity + unit:unit]; + } else { + callback(@[RCTMakeError(@"RNHealth: Aggregator should be CUMULATIVE_SUM = 3 or AVERAGE = 2", nil, nil)]); + return; + } +} + +- (void)averageDietaryStatisticsRequest:(NSDictionary *)input + callback:(RCTResponseSenderBlock)callback + quantity:(HKQuantityTypeIdentifier)quantity + unit:(HKUnit *)unit { + + NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:nil]; + NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]]; + + RCTInterval intervalType = (RCTInterval) [RCTAppleHealthKit uintFromOptions:input key:@"interval" withDefault:RCTIntervalMonth]; + + if (!((intervalType == RCTIntervalDay) || (intervalType == RCTIntervalMonth))) { + callback(@[RCTMakeError(@"RNHealth: interval type isn't valid", nil, nil)]); + return; + } + + NSMutableArray *samplesOutput = [NSMutableArray new]; + HKSampleType *sample =[HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierDietaryFiber]; + + if ([sample isKindOfClass:[HKCharacteristicType class]]) { + callback(@[RCTMakeError(@"RNHealth: Could not load data for HKCharacteristicType", nil, nil)]); + return; + } + + if (sample == nil) { + callback(@[RCTMakeError(@"RNHealth: Could not load data: sample is null", nil, nil)]); + return; + } + + int limit = 5000; + __block HKQueryAnchor *anchor = nil; + __block NSMutableArray<__kindof HKSample *> *samplesResultArray = [NSMutableArray new]; + + __block BOOL hasResults = YES; + __block NSString *anchorString = nil; + + while (hasResults) { + if (anchorString != nil) { + NSData* anchorData = [[NSData alloc] initWithBase64EncodedString:anchorString options:0]; + anchor = [NSKeyedUnarchiver unarchiveObjectWithData:anchorData]; + } + + NSPredicate *anchorPredicate = [RCTAppleHealthKit predicateForAnchoredQueries:anchor startDate:startDate endDate:endDate]; + + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + + [self fetchBatchOfSamples:sample + predicate:anchorPredicate + anchor:anchor + limit:limit + completion:^(NSDictionary *results, NSError *error) { + + if (results) { + @try { + + NSMutableArray<__kindof HKSample *> *data = results[@"data"]; + + if (data == nil) { + hasResults = NO; + NSLog(@"RNHealth averageDietaryStatisticsRequest: An error occured"); + dispatch_semaphore_signal(semaphore); + } + + if (data.count > 0) { + [samplesResultArray addObjectsFromArray:data]; + + anchorString = results[@"anchor"]; + + } else { + hasResults = NO; + } + dispatch_semaphore_signal(semaphore); + } @catch (NSException *exception) { + hasResults = NO; + NSLog(@"RNHealth averageDietaryStatisticsRequest: An error occured"); + dispatch_semaphore_signal(semaphore); + } + } else { + hasResults = NO; + NSLog(@"RNHealth averageDietaryStatisticsRequest: An error occured"); + dispatch_semaphore_signal(semaphore); + } + }]; + + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + }; + + NSDateFormatter *intervalDateFormatter = [[NSDateFormatter alloc] init]; + if (intervalType == RCTIntervalDay) { + [intervalDateFormatter setDateFormat:@"yyyy-MM-dd"]; + } else { + [intervalDateFormatter setDateFormat:@"yyyy-MM"]; + } + + for (HKQuantitySample *sample in samplesResultArray) { + NSString *interval = [intervalDateFormatter stringFromDate:sample.startDate]; + + HKQuantity *quantity = sample.quantity; + double value = [quantity doubleValueForUnit:unit]; + + NSMutableDictionary *response = [NSMutableDictionary dictionary]; + response[@"value"] = value ? @(value) : @"0"; + response[@"interval"] = interval ? interval : @""; + response[@"startDate"] = sample.startDate; + response[@"endDate"] = sample.endDate; + + [samplesOutput addObject:response]; + } + + NSMutableDictionary *groupedByInterval = [NSMutableDictionary new]; + + NSArray *distinctNames; + distinctNames = [samplesOutput valueForKeyPath:@"@distinctUnionOfObjects.interval"]; + for (NSString *name in distinctNames) { + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"interval = %@", name]; + NSArray *intervals = [samplesOutput filteredArrayUsingPredicate:predicate]; + [groupedByInterval setObject:intervals forKey:name]; + } + + NSMutableArray *resultWithSumForInterval = [NSMutableArray new]; + for (NSString* key in groupedByInterval) { + NSArray<__kindof NSDictionary *> *intervalValues = groupedByInterval[key]; + double intervalValue = 0; + double entriesCount = 0; + for (NSDictionary *intervalValueObj in intervalValues) { + intervalValue += [intervalValueObj[@"value"] doubleValue]; + entriesCount += 1; + } + + NSDate *startIntervalDate; + NSDate *endIntervalDate; + NSCalendar* calendar = [NSCalendar currentCalendar]; + if (intervalType == RCTIntervalDay) { + startIntervalDate = [calendar startOfDayForDate:intervalValues.firstObject[@"startDate"]]; + + NSDateComponents *dayComponent = [[NSDateComponents alloc] init]; + dayComponent.day = 1; + endIntervalDate = [calendar dateByAddingComponents:dayComponent toDate:startIntervalDate options:0]; + } else { + NSDateComponents *componentsStartDate = [calendar components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:intervalValues.firstObject[@"startDate"]]; + [componentsStartDate setDay:1]; + startIntervalDate = [calendar dateFromComponents: componentsStartDate]; + + NSDateComponents* componentsEndDate = [calendar components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:intervalValues.lastObject[@"endDate"]]; + [componentsEndDate setMonth:[componentsEndDate month]+1]; + [componentsEndDate setDay:0]; + endIntervalDate = [calendar dateFromComponents:componentsEndDate]; + } + + NSString *startDateString = [RCTAppleHealthKit buildStringFromDateForStatistics:startIntervalDate]; + NSString *endDateString = [RCTAppleHealthKit buildStringFromDateForStatistics:endIntervalDate]; + + NSMutableDictionary *resultForInterval = [NSMutableDictionary new]; + resultForInterval[@"startDate"] = startDateString; + resultForInterval[@"endDate"] = endDateString; + + double averageValue = 0; + if (entriesCount != 0) { + averageValue = intervalValue / entriesCount; + } + resultForInterval[@"value"] = @(averageValue); + + NSString *json = [RCTAppleHealthKit stringFromObject:resultForInterval]; + NSString *hashInput = [[NSString alloc] initWithFormat:@"%@:%@:%@", quantity, @"average", json]; + NSString *hash = [RCTAppleHealthKit md5HashString:hashInput]; + NSString *identifier = [RCTAppleHealthKit formattingStringHash:hash]; + + resultForInterval[@"id"] = identifier; + + resultForInterval[@"interval"] = intervalValues.firstObject[@"interval"]; + [resultWithSumForInterval addObject:resultForInterval]; + } + + NSSortDescriptor *dateDescriptor = [NSSortDescriptor + sortDescriptorWithKey:@"interval" + ascending:YES]; + NSArray *sortDescriptors = [NSArray arrayWithObject:dateDescriptor]; + NSArray *sortedResult = [resultWithSumForInterval + sortedArrayUsingDescriptors:sortDescriptors]; + + callback(@[[NSNull null], sortedResult]); +} + @end diff --git a/RNAppleHealthKit.podspec b/RNAppleHealthKit.podspec index 144eeb5c..d3e11bbc 100644 --- a/RNAppleHealthKit.podspec +++ b/RNAppleHealthKit.podspec @@ -5,11 +5,14 @@ # Any lines starting with a # are optional, but their use is encouraged # To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html # +require 'json' + +package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) Pod::Spec.new do |s| s.name = 'RNAppleHealthKit' - s.version = '1.7.0' - s.summary = 'A React Native package to interact with Apple HealthKit' + s.version = package['version'] + s.summary = package['description'] # This description is used to generate tags and improve search results. # * Think: What does it do? Why did you write it? What is the focus? @@ -21,12 +24,12 @@ Pod::Spec.new do |s| A React Native package to interact with Apple HealthKit DESC - s.homepage = 'https://github.com/agencyenterprise/react-native-health' + s.homepage = 'https://github.com/Ornament-Health/react-native-health' s.license = { :type => 'MIT', :file => 'LICENSE' } s.author = { 'Agency Enterprise' => '' } - s.source = { :git => 'https://github.com/agencyenterprise/react-native-healthkit.git', :tag => s.version.to_s } + s.source = { :git => 'https://github.com/Ornament-Health/react-native-health.git', :tag => s.version.to_s } - s.ios.deployment_target = '9.0' + s.ios.deployment_target = '14.0' s.swift_version = '4.2' s.source_files = 'RCTAppleHealthKit/**/*' diff --git a/app.plugin.js b/app.plugin.js deleted file mode 100644 index 8dbb66a4..00000000 --- a/app.plugin.js +++ /dev/null @@ -1,56 +0,0 @@ -const { withEntitlementsPlist, withInfoPlist } = require('@expo/config-plugins') - -const HEALTH_SHARE = 'Allow $(PRODUCT_NAME) to check health info' -const HEALTH_UPDATE = 'Allow $(PRODUCT_NAME) to update health info' -const HEALTH_CLINIC_SHARE = 'Allow $(PRODUCT_NAME) to check health clinical info' - -const withHealthKit = ( - config, - { healthSharePermission, healthUpdatePermission, isClinicalDataEnabled, healthClinicalDescription } = {}, -) => { - // Add permissions - config = withInfoPlist(config, (config) => { - config.modResults.NSHealthShareUsageDescription = - healthSharePermission || - config.modResults.NSHealthShareUsageDescription || - HEALTH_SHARE - config.modResults.NSHealthUpdateUsageDescription = - healthUpdatePermission || - config.modResults.NSHealthUpdateUsageDescription || - HEALTH_UPDATE - isClinicalDataEnabled ? - config.modResults.NSHealthClinicalHealthRecordsShareUsageDescription = - healthClinicalDescription || - config.modResults.NSHealthClinicalHealthRecordsShareUsageDescription || - HEALTH_CLINIC_SHARE : - null - - return config - }) - - // Add entitlements. These are automatically synced when using EAS build for production apps. - config = withEntitlementsPlist(config, (config) => { - config.modResults['com.apple.developer.healthkit'] = true - if ( - !Array.isArray(config.modResults['com.apple.developer.healthkit.access']) - ) { - config.modResults['com.apple.developer.healthkit.access'] = [] - } - - if (isClinicalDataEnabled) { - config.modResults['com.apple.developer.healthkit.access'].push( - 'health-records', - ) - - // Remove duplicates - config.modResults['com.apple.developer.healthkit.access'] = [ - ...new Set(config.modResults['com.apple.developer.healthkit.access']), - ] - } - - return config - }) - - return config -} -module.exports = withHealthKit diff --git a/docs/Expo.md b/docs/Expo.md deleted file mode 100644 index 8dcf86f1..00000000 --- a/docs/Expo.md +++ /dev/null @@ -1,61 +0,0 @@ -# Expo installation - -> This package cannot be used in the "Expo Go" app because [it requires custom native code](https://docs.expo.dev/workflow/customizing/). - -First install the package with yarn, npm, or [`npx expo install`](https://docs.expo.dev/more/expo-cli/#installation). - -```sh -expo install react-native-health -``` - -After installing this npm package, add the [config plugin](https://docs.expo.io/guides/config-plugins/) to the [`plugins`](https://docs.expo.io/versions/latest/config/app/#plugins) array of your `app.json` or `app.config.js`: - -```json -{ - "expo": { - "plugins": ["react-native-health"] - } -} -``` - -Next, rebuild your app as described in the ["Adding custom native code"](https://docs.expo.dev/workflow/customizing/) guide. - -## API - -The plugin provides props for extra customization. Every time you change the props or plugins, you'll need to rebuild (and `prebuild`) the native app. If no extra properties are added, defaults will be used. - -- `healthSharePermission` (_string_): Sets the iOS `NSHealthShareUsageDescription` permission message to the `Info.plist`. Defaults to `Allow $(PRODUCT_NAME) to check health info`. -- `healthUpdatePermission` (_string_): Sets the iOS `NSHealthUpdateUsageDescription` permission message to the `Info.plist`. Defaults to `Allow $(PRODUCT_NAME) to update health info`. -- `isClinicalDataEnabled` (_boolean_): Adds `health-records` to the `com.apple.developer.healthkit.access` entitlement in the iOS project. Defaults to false. -- `healthClinicalDescription` (_string_): Sets the iOS `NSHealthClinicalHealthRecordsShareUsageDescription` permission message to the `Info.plist`. Defaults to `Allow $(PRODUCT_NAME) to check health info`. - -`app.config.js` - -```json -{ - "expo": { - "plugins": [ - [ - "react-native-health", - { - "isClinicalDataEnabled": true, - "healthSharePermission": "Custom health share permission", - "healthUpdatePermission": "Custom health update permission", - "healthClinicalDescription": "Custom health share permission for clinical data" - } - ] - ] - } -} -``` - -## Background Processing - -Background processing is not currently supported by this plugin. - -## Capabilities - -This plugin will enable the iOS `com.apple.developer.healthkit` entitlement, but in order to sync this with the bundle identifier' production capabilities you'll need to do one of two things: - -- Automatic: Build the app with [EAS build](https://docs.expo.io/build/introduction/) -- Manual: Visit [Apple developer portal](https://developer.apple.com/account/resources/identifiers/list) and enable the HealthKit capability for your bundle identifier before building for production. This can also be done via Xcode. diff --git a/docs/statistics.md b/docs/statistics.md index 7c3ae924..a21dd2c0 100644 --- a/docs/statistics.md +++ b/docs/statistics.md @@ -2,39 +2,84 @@ Query statistic (aggregated) biomarkers. -| Value | Methods | -|---------------------------------------------|------------------------------------| -| bodyMass (body weight) | getStatisticBodyMass | -| bloodPressureSystolic (systolic pressure) | getStatisticBloodPressureSystolic | -| bloodPressureDiastolic (diastolic pressure) | getStatisticBloodPressureDiastolic | -| bloodGlucose (blood glucose) | getStatisticBloodGlucose | -| bodyMassIndex (body mass index) | getStatisticBodyMassIndex | -| height (body height) | getStatisticHeight | -| stepCount (number of steps) | getStatisticStepCount | -| heartRate (pulse) | getStatisticHeartRate | -| bodyTemperature (body temperature) | getStatisticBodyTemperature | -| oxygenSaturation (oxygen saturation) | getStatisticOxygenSaturation | -| restingHeartRate (resting heart rate) | getStatisticRestingHeartRate | -| Dietary | | -| energyConsumed (energy value) | getStatisticDietaryEnergyConsumed | -| protein (protein) | getStatisticDietaryProtein | -| fiber (cellulose) | getStatisticDietaryFiber | -| totalFat (fats) | getStatisticDietaryTotalFat | -| water | getStatisticDietaryWater (water) | -| sugar | getStatisticDietarySugar (sugar) | -| fatSaturated | getStatisticDietaryFatSaturated | -| cholesterol | getStatisticDietaryCholesterol | -| carbohydrates | getStatisticDietaryCarbohydrates | -| calcium | getStatisticDietaryCalcium | -| iron | getStatisticDietaryIron | -| potassium | getStatisticDietaryPotassium | -| sodium | getStatisticDietarySodium | -| vitaminA | getStatisticDietaryVitaminA | -| vitaminC | getStatisticDietaryVitaminC | -| vitaminD | getStatisticDietarySugar | -| Lab and Test Results || -| insulinDelivery (insulin delivery) | getStatisticInsulinDelivery | - +| Value | Methods | +|---------------------------------------------|-------------------------------------------| +| bodyMass (body weight) | getStatisticBodyMass | +| bloodPressureSystolic (systolic pressure) | getStatisticBloodPressureSystolic | +| bloodPressureDiastolic (diastolic pressure) | getStatisticBloodPressureDiastolic | +| bloodGlucose (blood glucose) | getStatisticBloodGlucose | +| bodyMassIndex (body mass index) | getStatisticBodyMassIndex | +| height (body height) | getStatisticHeight | +| stepCount (number of steps) | getStatisticStepCount | +| heartRate (pulse) | getStatisticHeartRate | +| bodyTemperature (body temperature) | getStatisticBodyTemperature | +| oxygenSaturation (oxygen saturation) | getStatisticOxygenSaturation | +| restingHeartRate (resting heart rate) | getStatisticRestingHeartRate | +| Dietary | | +| Macronutrients | | +| energyConsumed (energy value) | getStatisticDietaryEnergyConsumed | +| protein (protein) | getStatisticDietaryProtein | +| fiber (cellulose) | getStatisticDietaryFiber | +| totalFat (fats) | getStatisticDietaryTotalFat | +| sugar | getStatisticDietarySugar (sugar) | +| fatSaturated | getStatisticDietaryFatSaturated | +| fatMonounsaturated | getStatisticDietaryFatMonounsaturated | +| fatPolyunsaturated | getStatisticDietaryFatPolyunsaturated | +| cholesterol | getStatisticDietaryCholesterol | +| carbohydrates | getStatisticDietaryCarbohydrates | +| Vitamins | | +| vitaminA | getStatisticDietaryVitaminA | +| vitaminC | getStatisticDietaryVitaminC | +| vitaminD | getStatisticDietaryVitaminD | +| thiamin | getStatisticDietaryThiamin | +| riboflavin | getStatisticDietaryRiboflavin | +| niacin | getStatisticDietaryNiacin | +| pantothenicAcid | getStatisticDietaryPantothenicAcid | +| vitaminB6 | getStatisticDietaryVitaminB6 | +| biotin | getStatisticDietaryBiotin | +| vitaminB12 | getStatisticDietaryVitaminB12 | +| vitaminE | getStatisticDietaryVitaminE | +| vitaminK | getStatisticDietaryVitaminK | +| folate | getStatisticDietaryFolate | +| calcium | getStatisticDietaryCalcium | +| iron | getStatisticDietaryIron | +| potassium | getStatisticDietaryPotassium | +| sodium | getStatisticDietarySodium | +| Minerals | | +| calcium | getStatisticDietaryCalcium | +| chloride | getStatisticDietaryChloride | +| iron | getStatisticDietaryIron | +| magnesium | getStatisticDietaryMagnesium | +| phosphorus | getStatisticDietaryPhosphorus | +| potassium | getStatisticDietaryPotassium | +| sodium | getStatisticDietarySodium | +| zinc | getStatisticDietaryZinc | +| Hydration | | +| water | getStatisticDietaryWater | +| Caffeination | | +| caffeine | getStatisticDietaryCaffeine | +| Ultratrace Minerals | | +| chromium | getStatisticDietaryChromium | +| copper | getStatisticDietaryCopper | +| iodine | getStatisticDietaryIodine | +| manganese | getStatisticDietaryManganese | +| molybdenum | getStatisticDietaryMolybdenum | +| selenium | getStatisticDietarySelenium | +| Lab and Test Results | | +| insulinDelivery (insulin delivery) | getStatisticInsulinDelivery | +| numberOfTimesFallen | getStatisticNumberOfTimesFallen | +| peakExpiratoryFlowRate | getStatisticPeakExpiratoryFlowRate | +| peripheralPerfusionIndex | getStatisticPeripheralPerfusionIndex | +| Activity | | +| distanceWheelchair | getStatisticDistanceWheelchair | +| appleExerciseTime | getStatisticAppleExerciseTime | +| Body Measurments | | +| appleSleepingWristTemperature | getStatisticAppleSleepingWristTemperature | +| Vital Signs | | +| heartRateRecoveryOneMinute | getStatisticHeartRateRecoveryOneMinute | +| atrialFibrillationBurden | getStatisticAtrialFibrillationBurden | +| UV Exposure | | +| uvExposure | getStatisticUvExposure | ## Example call @@ -43,21 +88,10 @@ Query statistic (aggregated) biomarkers. let options = { aggregator: HealthStatisticsCommonAggregatorType.AVERAGE, interval: HealthStatisticsIntervalType.DAY, // optional; default HealthStatisticsIntervalType.MONTH - unit: 'pound', // optional; startDate: new Date(2021, 0, 0).toISOString(), // optional endDate: new Date().toISOString(), // optional; default now } ``` -For dietary and insulinDelivery: -```typescript -let options: HealthStatisticsDietaryInputOptions = { - aggregator: HealthStatisticsDietaryAggregatorType.CUMULATIVE_SUM, - interval: HealthStatisticsIntervalType.DAY, // optional; default HealthStatisticsIntervalType.MONTH - unit: 'calorie', // optional - startDate: new Date(2021, 0, 0).toISOString(), - endDate: new Date().toISOString(), - } -``` Method call example: @@ -72,13 +106,13 @@ AppleHealthKit.getStatisticBodyMass( }, ) ``` - +For dietary biomarkers (Macronutrients, Vitamins, Minerals, Hydration, Caffeination, Ultratrace Minerals types) could be calculated average or cumulative values. ## Request payload |name|type|required| |---|---|---| -|aggregator|HealthStatisticsCommonAggregatorType or HealthStatisticsStepsAggregatorType or HealthStatisticsDietaryAggregatorType|✓| +|aggregator|HealthStatisticsCommonAggregatorType or HealthStatisticsStepsAggregatorType or CumulativeAggregatorsType|✓| |interval|HealthStatisticsIntervalType|| |unit|string|| |startDate|string|✓| @@ -102,9 +136,8 @@ enum CumulativeAggregatorsType { export type HealthStatisticsCommonAggregatorType = GenericAggregatorsType | AverageAggregatorsType; -export type HealthStatisticsStepsAggregatorType = GenericAggregatorsType | CumulativeAggregatorsType; +export type HealthStatisticsStepsAggregatorType = GenericAggregatorsType | CumulativeAggregatorsType -export type HealthStatisticsDietaryAggregatorType = CumulativeAggregatorsType ``` ## Response diff --git a/index.d.ts b/index.d.ts index dd3d15b1..0b6880f7 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,5 +1,3 @@ -import { HealthInputOptions } from 'react-native-health' - declare module 'react-native-health' { export interface HealthKitPermissions { permissions: { @@ -524,85 +522,271 @@ declare module 'react-native-health' { callback: (err: string, results: Array) => void, ): void + // Dietary + + // Macronutrients getStatisticDietaryEnergyConsumed( - options: HealthStatisticsDietaryInputOptions, + options: HealthStatisticsCommonInputOptions, callback: (err: string, results: Array) => void, ): void - getStatisticDietaryProtein( - options: HealthStatisticsDietaryInputOptions, + getStatisticDietaryCarbohydrates( + options: HealthStatisticsCommonInputOptions, callback: (err: string, results: Array) => void, ): void getStatisticDietaryFiber( - options: HealthStatisticsDietaryInputOptions, + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticDietarySugar( + options: HealthStatisticsCommonInputOptions, callback: (err: string, results: Array) => void, ): void getStatisticDietaryTotalFat( - options: HealthStatisticsDietaryInputOptions, + options: HealthStatisticsCommonInputOptions, callback: (err: string, results: Array) => void, ): void - getStatisticDietaryWater( - options: HealthStatisticsDietaryInputOptions, + getStatisticDietaryFatMonounsaturated( + options: HealthStatisticsCommonInputOptions, callback: (err: string, results: Array) => void, ): void - getStatisticDietarySugar( - options: HealthStatisticsDietaryInputOptions, + getStatisticDietaryFatPolyunsaturated( + options: HealthStatisticsCommonInputOptions, callback: (err: string, results: Array) => void, ): void getStatisticDietaryFatSaturated( - options: HealthStatisticsDietaryInputOptions, + options: HealthStatisticsCommonInputOptions, callback: (err: string, results: Array) => void, ): void getStatisticDietaryCholesterol( - options: HealthStatisticsDietaryInputOptions, + options: HealthStatisticsCommonInputOptions, callback: (err: string, results: Array) => void, ): void - getStatisticDietaryCarbohydrates( - options: HealthStatisticsDietaryInputOptions, + getStatisticDietaryProtein( + options: HealthStatisticsCommonInputOptions, callback: (err: string, results: Array) => void, ): void + // Vitamins + + getStatisticDietaryVitaminA( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticDietaryThiamin( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticDietaryRiboflavin( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticDietaryNiacin( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticDietaryPantothenicAcid( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticDietaryVitaminB6( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticDietaryBiotin( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticDietaryVitaminB12( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticDietaryVitaminC( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticDietaryVitaminD( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticDietaryVitaminE( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticDietaryVitaminK( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticDietaryFolate( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + // Minerals + getStatisticDietaryCalcium( - options: HealthStatisticsDietaryInputOptions, + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticDietaryChloride( + options: HealthStatisticsCommonInputOptions, callback: (err: string, results: Array) => void, ): void getStatisticDietaryIron( - options: HealthStatisticsDietaryInputOptions, + options: HealthStatisticsCommonInputOptions, callback: (err: string, results: Array) => void, ): void + + getStatisticDietaryMagnesium( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticDietaryPhosphorus( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + getStatisticDietaryPotassium( - options: HealthStatisticsDietaryInputOptions, + options: HealthStatisticsCommonInputOptions, callback: (err: string, results: Array) => void, ): void + getStatisticDietarySodium( - options: HealthStatisticsDietaryInputOptions, + options: HealthStatisticsCommonInputOptions, callback: (err: string, results: Array) => void, ): void - getStatisticDietaryVitaminA( - options: HealthStatisticsDietaryInputOptions, + + getStatisticDietaryZinc( + options: HealthStatisticsCommonInputOptions, callback: (err: string, results: Array) => void, ): void - getStatisticDietaryVitaminC( - options: HealthStatisticsDietaryInputOptions, + // Hydration + + getStatisticDietaryWater( + options: HealthStatisticsCommonInputOptions, callback: (err: string, results: Array) => void, ): void - getStatisticDietaryVitaminD( - options: HealthStatisticsDietaryInputOptions, + // Caffeination + + getStatisticDietaryCaffeine( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + // Ultratrace Minerals + + getStatisticDietaryChromium( + options: HealthStatisticsCumulativeInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticDietaryCopper( + options: HealthStatisticsCumulativeInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticDietaryIodine( + options: HealthStatisticsCumulativeInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticDietaryManganese( + options: HealthStatisticsCumulativeInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticDietaryMolybdenum( + options: HealthStatisticsCumulativeInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticDietarySelenium( + options: HealthStatisticsCommonInputOptions, callback: (err: string, results: Array) => void, ): void getStatisticInsulinDelivery( - options: HealthStatisticsDietaryInputOptions, + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + // Activity + + getStatisticDistanceWheelchair( + options: HealthStatisticsCumulativeInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticAppleExerciseTime( + options: HealthStatisticsCumulativeInputOptions, + callback: (err: string, results: Array) => void, + ): void + + // Body Measurments + + getStatisticAppleSleepingWristTemperature( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + // Vital Signs + + getStatisticHeartRateRecoveryOneMinute( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticAtrialFibrillationBurden( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + // Lab And Test Results + + getStatisticNumberOfTimesFallen( + options: HealthStatisticsCumulativeInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticPeakExpiratoryFlowRate( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + getStatisticPeripheralPerfusionIndex( + options: HealthStatisticsCommonInputOptions, + callback: (err: string, results: Array) => void, + ): void + + // UV Exposure + + getStatisticUvExposure( + options: HealthStatisticsCommonInputOptions, callback: (err: string, results: Array) => void, ): void @@ -720,8 +904,8 @@ declare module 'react-native-health' { startDate: string eventTypeInt: number eventType: EventType - } - + } + enum GenericAggregatorsType { MIN = 0, MAX = 1, @@ -750,9 +934,6 @@ declare module 'react-native-health' { DAY = 1, } - export type HealthStatisticsDietaryAggregatorType = - | CumulativeAggregatorsType - export interface HealthStatisticsCommonInputOptions extends HealthUnitOptions { aggregator: HealthStatisticsCommonAggregatorType @@ -768,8 +949,8 @@ declare module 'react-native-health' { endDate?: string } - export interface HealthStatisticsDietaryInputOptions extends HealthUnitOptions { - aggregator: HealthStatisticsDietaryAggregatorType + export interface HealthStatisticsCumulativeInputOptions extends HealthUnitOptions { + aggregator: CumulativeAggregatorsType interval?: HealthStatisticsIntervalType startDate: string endDate: string @@ -1101,10 +1282,12 @@ declare module 'react-native-health' { AllergyRecord = 'AllergyRecord', AppleExerciseTime = 'AppleExerciseTime', AppleMoveTime = 'AppleMoveTime', + AppleSleepingWristTemperature = 'AppleSleepingWristTemperature', AppleStandHour = 'AppleStandHour', AppleStandTime = 'AppleStandTime', AppleWalkingSteadiness = 'AppleWalkingSteadiness', AppleWalkingSteadinessEvent = 'AppleWalkingSteadinessEvent', + AtrialFibrillationBurden = 'AtrialFibrillationBurden', BasalBodyTemperature = 'BasalBodyTemperature', BasalEnergyBurned = 'BasalEnergyBurned', BiologicalSex = 'BiologicalSex', @@ -1130,6 +1313,7 @@ declare module 'react-native-health' { ConditionRecord = 'ConditionRecord', Copper = 'Copper', CoverageRecord = 'CoverageRecord', + DistanceWheelchair = 'DistanceWheelchair', ElectrodermalActivity = 'ElectrodermalActivity', EnergyConsumed = 'EnergyConsumed', EnvironmentalAudioExposure = 'EnvironmentalAudioExposure', @@ -1142,6 +1326,7 @@ declare module 'react-native-health' { ForcedExpiratoryVolume1 = 'ForcedExpiratoryVolume1', ForcedVitalCapacity = 'ForcedVitalCapacity', HeadphoneAudioExposure = 'HeadphoneAudioExposure', + HeartRateRecoveryOneMinute = 'HeartRateRecoveryOneMinute', ImmunizationRecord = 'ImmunizationRecord', InhalerUsage = 'InhalerUsage', InsulinDelivery = 'InsulinDelivery', @@ -1158,9 +1343,12 @@ declare module 'react-native-health' { Molybdenum = 'Molybdenum', Niacin = 'Niacin', NumberOfAlcoholicBeverages = 'NumberOfAlcoholicBeverages', + NumberOfTimesFallen = 'NumberOfTimesFallen', OvulationTestResult = 'OvulationTestResult', OxygenSaturation = 'OxygenSaturation', PantothenicAcid = 'PantothenicAcid', + PeakExpiratoryFlowRate = 'PeakExpiratoryFlowRate', + PeripheralPerfusionIndex = 'PeripheralPerfusionIndex', Phosphorus = 'Phosphorus', Potassium = 'Potassium', Pregnancy = 'Pregnancy', diff --git a/package.json b/package.json index 9f780629..79d8c52a 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "react-native-health", - "version": "1.19.0", + "version": "1.20.0", "description": "A React Native package to interact with Apple HealthKit", "main": "index.js", "repository": { "type": "git", - "url": "git+https://github.com/agencyenterprise/react-native-healthkit.git" + "url": "git+https://github.com/Ornament-Health/react-native-health.git" }, "keywords": [ "Apple", @@ -18,7 +18,7 @@ "ios" ], "bugs": { - "url": "https://github.com/agencyenterprise/react-native-healthkit/issues" + "url": "https://github.com/Ornament-Health/react-native-health/issues" }, "license": "MIT", "devDependencies": { @@ -26,8 +26,5 @@ }, "peerDependencies": { "react-native": ">=0.40.0" - }, - "dependencies": { - "@expo/config-plugins": "^2.0.0" } } diff --git a/src/constants/Permissions.js b/src/constants/Permissions.js index e2c513c2..9d86932c 100644 --- a/src/constants/Permissions.js +++ b/src/constants/Permissions.js @@ -9,10 +9,12 @@ export const Permissions = { AllergyRecord: 'AllergyRecord', AppleExerciseTime: 'AppleExerciseTime', AppleMoveTime: 'AppleMoveTime', + AppleSleepingWristTemperature: 'AppleSleepingWristTemperature', AppleStandHour: 'AppleStandHour', AppleStandTime: 'AppleStandTime', AppleWalkingSteadiness: 'AppleWalkingSteadiness', AppleWalkingSteadinessEvent: 'AppleWalkingSteadinessEvent', + AtrialFibrillationBurden: 'AtrialFibrillationBurden', BasalBodyTemperature: 'BasalBodyTemperature', BasalEnergyBurned: 'BasalEnergyBurned', BiologicalSex: 'BiologicalSex', @@ -38,6 +40,7 @@ export const Permissions = { Contraceptive: 'Contraceptive', Copper: 'Copper', CoverageRecord: 'CoverageRecord', + DistanceWheelchair: 'DistanceWheelchair', EnergyConsumed: 'EnergyConsumed', ElectrodermalActivity: 'ElectrodermalActivity', EnvironmentalAudioExposure: 'EnvironmentalAudioExposure', @@ -50,6 +53,7 @@ export const Permissions = { ForcedExpiratoryVolume1: 'ForcedExpiratoryVolume1', ForcedVitalCapacity: 'ForcedVitalCapacity', HeadphoneAudioExposure: 'HeadphoneAudioExposure', + HeartRateRecoveryOneMinute: 'HeartRateRecoveryOneMinute', ImmunizationRecord: 'ImmunizationRecord', InhalerUsage: 'InhalerUsage', InsulinDelivery: 'InsulinDelivery', @@ -66,9 +70,12 @@ export const Permissions = { Molybdenum: 'Molybdenum', Niacin: 'Niacin', NumberOfAlcoholicBeverages: 'NumberOfAlcoholicBeverages', + NumberOfTimesFallen: 'NumberOfTimesFallen', OvulationTestResult: 'OvulationTestResult', OxygenSaturation: 'OxygenSaturation', PantothenicAcid: 'PantothenicAcid', + PeakExpiratoryFlowRate: 'PeakExpiratoryFlowRate', + PeripheralPerfusionIndex: 'PeripheralPerfusionIndex', Phosphorus: 'Phosphorus', Potassium: 'Potassium', Pregnancy: 'Pregnancy',