diff --git a/packages/health/CHANGELOG.md b/packages/health/CHANGELOG.md index 1917bf296..c07bafbf5 100644 --- a/packages/health/CHANGELOG.md +++ b/packages/health/CHANGELOG.md @@ -6,6 +6,8 @@ * Updated `intl` to ^0.20.1 - Closes [#1092](https://github.com/cph-cachet/flutter-plugins/issues/1092) * Updated `device_info_plus` to ^11.2.0 * Example app: Updated `permission_handler` to ^11.3.1 +* iOS: Add `WATER_TEMPERATURE` and `UNDERWATER_DEPTH` health values - Closes [#1096](https://github.com/cph-cachet/flutter-plugins/issues/1096) +* iOS: Add support for `Underwater Diving` workout - Closes [#1096](https://github.com/cph-cachet/flutter-plugins/issues/1096) ## 11.1.1 diff --git a/packages/health/README.md b/packages/health/README.md index 68ec291bc..e10b90ab5 100644 --- a/packages/health/README.md +++ b/packages/health/README.md @@ -355,6 +355,9 @@ The plugin supports the following [`HealthDataType`](https://pub.dev/documentati | ELECTROCARDIOGRAM | VOLT | yes | | Requires Apple Watch to write the data | | NUTRITION | NO_UNIT | yes | yes | | | INSULIN_DELIVERY | INTERNATIONAL_UNIT | yes | | | +| MENSTRUATION_FLOW | NO_UNIT | yes | yes | | +| WATER_TEMPERATURE | DEGREE_CELSIUS | yes | | Related to/Requires Apple Watch Ultra's Underwater Diving Workout | +| UNDERWATER_DEPTH | METER | yes | | Related to/Requires Apple Watch Ultra's Underwater Diving Workout | ## Workout Types @@ -443,6 +446,7 @@ The plugin supports the following [`HealthWorkoutActivityType`](https://pub.dev/ | TENNIS | yes | yes | | | TRACK_AND_FIELD | yes | | | | TRADITIONAL_STRENGTH_TRAINING | yes | (yes) | on Android this will be stored as STRENGTH_TRAINING | +| UNDERWATER_DIVING | yes | | | | VOLLEYBALL | yes | yes | | | WALKING | yes | yes | | | WATER_FITNESS | yes | | | diff --git a/packages/health/example/ios/Runner.xcodeproj/project.pbxproj b/packages/health/example/ios/Runner.xcodeproj/project.pbxproj index 4ce55d34f..a64ef83b6 100644 --- a/packages/health/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/health/example/ios/Runner.xcodeproj/project.pbxproj @@ -155,6 +155,7 @@ 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 8AB8966E9F27B6C816D51EA9 /* [CP] Embed Pods Frameworks */, + 99FD4B47838A33EC942FDC35 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -271,6 +272,24 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + 99FD4B47838A33EC942FDC35 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/permission_handler_apple/permission_handler_apple_privacy.bundle", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/permission_handler_apple_privacy.bundle", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; AFF7CCF5217A091E1625CD54 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -394,7 +413,10 @@ ); INFOPLIST_FILE = Runner/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", @@ -531,7 +553,10 @@ ); INFOPLIST_FILE = Runner/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", @@ -564,7 +589,10 @@ ); INFOPLIST_FILE = Runner/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", diff --git a/packages/health/example/lib/main.dart b/packages/health/example/lib/main.dart index b77eae30e..e02c1e037 100644 --- a/packages/health/example/lib/main.dart +++ b/packages/health/example/lib/main.dart @@ -376,6 +376,25 @@ class _HealthAppState extends State { endTime: now, ); + // Available on iOS 16.0+ only + if (Platform.isIOS) { + success &= await Health().writeHealthData( + value: 22, + type: HealthDataType.WATER_TEMPERATURE, + startTime: earlier, + endTime: now, + recordingMethod: RecordingMethod.manual + ); + + success &= await Health().writeHealthData( + value: 55, + type: HealthDataType.UNDERWATER_DEPTH, + startTime: earlier, + endTime: now, + recordingMethod: RecordingMethod.manual + ); + } + setState(() { _state = success ? AppState.DATA_ADDED : AppState.DATA_NOT_ADDED; }); diff --git a/packages/health/example/lib/util.dart b/packages/health/example/lib/util.dart index e1c49101d..24168041f 100644 --- a/packages/health/example/lib/util.dart +++ b/packages/health/example/lib/util.dart @@ -59,6 +59,8 @@ const List dataTypesIOS = [ HealthDataType.BLOOD_TYPE, HealthDataType.BIRTH_DATE, HealthDataType.MENSTRUATION_FLOW, + HealthDataType.WATER_TEMPERATURE, + HealthDataType.UNDERWATER_DEPTH, ]; /// List of data types available on Android. diff --git a/packages/health/ios/Classes/SwiftHealthPlugin.swift b/packages/health/ios/Classes/SwiftHealthPlugin.swift index a0bb9d4fd..ebb1f5d40 100644 --- a/packages/health/ios/Classes/SwiftHealthPlugin.swift +++ b/packages/health/ios/Classes/SwiftHealthPlugin.swift @@ -161,6 +161,8 @@ public class SwiftHealthPlugin: NSObject, FlutterPlugin { let GENDER = "GENDER" let BLOOD_TYPE = "BLOOD_TYPE" let MENSTRUATION_FLOW = "MENSTRUATION_FLOW" + let WATER_TEMPERATURE = "WATER_TEMPERATURE" + let UNDERWATER_DEPTH = "UNDERWATER_DEPTH" // Health Unit types @@ -857,7 +859,8 @@ public class SwiftHealthPlugin: NSObject, FlutterPlugin { "recording_method": (sample.metadata?[HKMetadataKeyWasUserEntered] as? Bool == true) ? RecordingMethod.manual.rawValue : RecordingMethod.automatic.rawValue, - "metadata": dataTypeKey == INSULIN_DELIVERY ? sample.metadata : nil + "metadata": dataTypeKey == INSULIN_DELIVERY ? sample.metadata : nil, + "dataUnitKey": unit?.unitString ] } DispatchQueue.main.async { @@ -1384,6 +1387,10 @@ public class SwiftHealthPlugin: NSObject, FlutterPlugin { workoutActivityTypeMap["TAI_CHI"] = .taiChi workoutActivityTypeMap["WRESTLING"] = .wrestling workoutActivityTypeMap["OTHER"] = .other + if #available(iOS 17.0, *) { + workoutActivityTypeMap["UNDERWATER_DIVING"] = .underwaterDiving + } + nutritionList = [ DIETARY_ENERGY_CONSUMED, DIETARY_CARBS_CONSUMED, DIETARY_PROTEIN_CONSUMED, DIETARY_FATS_CONSUMED, DIETARY_CAFFEINE, DIETARY_FIBER, DIETARY_SUGAR, @@ -1617,6 +1624,9 @@ public class SwiftHealthPlugin: NSObject, FlutterPlugin { if #available(iOS 16.0, *) { dataTypesDict[ATRIAL_FIBRILLATION_BURDEN] = HKQuantityType.quantityType(forIdentifier: .atrialFibrillationBurden)! + + dataTypesDict[WATER_TEMPERATURE] = HKQuantityType.quantityType(forIdentifier: .waterTemperature)! + dataTypesDict[UNDERWATER_DEPTH] = HKQuantityType.quantityType(forIdentifier: .underwaterDepth)! } // Concatenate heart events, headache and health data types (both may be empty) @@ -1774,6 +1784,8 @@ public class SwiftHealthPlugin: NSObject, FlutterPlugin { return "mixedCardio" case .handCycling: return "handCycling" + case .underwaterDiving: + return "underwaterDiving" default: return "other" } diff --git a/packages/health/ios/health.podspec b/packages/health/ios/health.podspec index 3a8d89370..96254602b 100644 --- a/packages/health/ios/health.podspec +++ b/packages/health/ios/health.podspec @@ -3,14 +3,14 @@ # Pod::Spec.new do |s| s.name = 'health' - s.version = '1.0.4' + s.version = '12.0.0' s.summary = 'Wrapper for Apple\'s HealthKit on iOS and Google\'s Health Connect on Android.' s.description = <<-DESC Wrapper for Apple's HealthKit on iOS and Google's Health Connect on Android. DESC s.homepage = 'https://pub.dev/packages/health' s.license = { :file => '../LICENSE' } - s.author = { 'Copenhagen Center for Health Technology' => 'cph.cachet@gmail.com' } + s.author = { 'Copenhagen Research Platform at DTU' => 'support@carp.dk' } s.source = { :path => '.' } s.source_files = 'Classes/**/*' s.public_header_files = 'Classes/**/*.h' diff --git a/packages/health/lib/health.g.dart b/packages/health/lib/health.g.dart index fa4423446..c61f0d2e5 100644 --- a/packages/health/lib/health.g.dart +++ b/packages/health/lib/health.g.dart @@ -29,31 +29,23 @@ HealthDataPoint _$HealthDataPointFromJson(Map json) => metadata: json['metadata'] as Map?, ); -Map _$HealthDataPointToJson(HealthDataPoint instance) { - final val = { - 'uuid': instance.uuid, - 'value': instance.value.toJson(), - 'type': _$HealthDataTypeEnumMap[instance.type]!, - 'unit': _$HealthDataUnitEnumMap[instance.unit]!, - 'dateFrom': instance.dateFrom.toIso8601String(), - 'dateTo': instance.dateTo.toIso8601String(), - 'sourcePlatform': _$HealthPlatformTypeEnumMap[instance.sourcePlatform]!, - 'sourceDeviceId': instance.sourceDeviceId, - 'sourceId': instance.sourceId, - 'sourceName': instance.sourceName, - 'recordingMethod': _$RecordingMethodEnumMap[instance.recordingMethod]!, - }; - - void writeNotNull(String key, dynamic value) { - if (value != null) { - val[key] = value; - } - } - - writeNotNull('workoutSummary', instance.workoutSummary?.toJson()); - writeNotNull('metadata', instance.metadata); - return val; -} +Map _$HealthDataPointToJson(HealthDataPoint instance) => + { + 'uuid': instance.uuid, + 'value': instance.value.toJson(), + 'type': _$HealthDataTypeEnumMap[instance.type]!, + 'unit': _$HealthDataUnitEnumMap[instance.unit]!, + 'dateFrom': instance.dateFrom.toIso8601String(), + 'dateTo': instance.dateTo.toIso8601String(), + 'sourcePlatform': _$HealthPlatformTypeEnumMap[instance.sourcePlatform]!, + 'sourceDeviceId': instance.sourceDeviceId, + 'sourceId': instance.sourceId, + 'sourceName': instance.sourceName, + 'recordingMethod': _$RecordingMethodEnumMap[instance.recordingMethod]!, + if (instance.workoutSummary?.toJson() case final value?) + 'workoutSummary': value, + if (instance.metadata case final value?) 'metadata': value, + }; const _$HealthDataTypeEnumMap = { HealthDataType.ACTIVE_ENERGY_BURNED: 'ACTIVE_ENERGY_BURNED', @@ -148,6 +140,8 @@ const _$HealthDataTypeEnumMap = { HealthDataType.BIRTH_DATE: 'BIRTH_DATE', HealthDataType.BLOOD_TYPE: 'BLOOD_TYPE', HealthDataType.MENSTRUATION_FLOW: 'MENSTRUATION_FLOW', + HealthDataType.WATER_TEMPERATURE: 'WATER_TEMPERATURE', + HealthDataType.UNDERWATER_DEPTH: 'UNDERWATER_DEPTH', HealthDataType.HIGH_HEART_RATE_EVENT: 'HIGH_HEART_RATE_EVENT', HealthDataType.LOW_HEART_RATE_EVENT: 'LOW_HEART_RATE_EVENT', HealthDataType.IRREGULAR_HEART_RATE_EVENT: 'IRREGULAR_HEART_RATE_EVENT', @@ -223,37 +217,21 @@ const _$RecordingMethodEnumMap = { HealthValue _$HealthValueFromJson(Map json) => HealthValue()..$type = json['__type'] as String?; -Map _$HealthValueToJson(HealthValue instance) { - final val = {}; - - void writeNotNull(String key, dynamic value) { - if (value != null) { - val[key] = value; - } - } - - writeNotNull('__type', instance.$type); - return val; -} +Map _$HealthValueToJson(HealthValue instance) => + { + if (instance.$type case final value?) '__type': value, + }; NumericHealthValue _$NumericHealthValueFromJson(Map json) => NumericHealthValue( numericValue: json['numericValue'] as num, )..$type = json['__type'] as String?; -Map _$NumericHealthValueToJson(NumericHealthValue instance) { - final val = {}; - - void writeNotNull(String key, dynamic value) { - if (value != null) { - val[key] = value; - } - } - - writeNotNull('__type', instance.$type); - val['numericValue'] = instance.numericValue; - return val; -} +Map _$NumericHealthValueToJson(NumericHealthValue instance) => + { + if (instance.$type case final value?) '__type': value, + 'numericValue': instance.numericValue, + }; AudiogramHealthValue _$AudiogramHealthValueFromJson( Map json) => @@ -269,21 +247,13 @@ AudiogramHealthValue _$AudiogramHealthValueFromJson( )..$type = json['__type'] as String?; Map _$AudiogramHealthValueToJson( - AudiogramHealthValue instance) { - final val = {}; - - void writeNotNull(String key, dynamic value) { - if (value != null) { - val[key] = value; - } - } - - writeNotNull('__type', instance.$type); - val['frequencies'] = instance.frequencies; - val['leftEarSensitivities'] = instance.leftEarSensitivities; - val['rightEarSensitivities'] = instance.rightEarSensitivities; - return val; -} + AudiogramHealthValue instance) => + { + if (instance.$type case final value?) '__type': value, + 'frequencies': instance.frequencies, + 'leftEarSensitivities': instance.leftEarSensitivities, + 'rightEarSensitivities': instance.rightEarSensitivities, + }; WorkoutHealthValue _$WorkoutHealthValueFromJson(Map json) => WorkoutHealthValue( @@ -300,29 +270,23 @@ WorkoutHealthValue _$WorkoutHealthValueFromJson(Map json) => $enumDecodeNullable(_$HealthDataUnitEnumMap, json['totalStepsUnit']), )..$type = json['__type'] as String?; -Map _$WorkoutHealthValueToJson(WorkoutHealthValue instance) { - final val = {}; - - void writeNotNull(String key, dynamic value) { - if (value != null) { - val[key] = value; - } - } - - writeNotNull('__type', instance.$type); - val['workoutActivityType'] = - _$HealthWorkoutActivityTypeEnumMap[instance.workoutActivityType]!; - writeNotNull('totalEnergyBurned', instance.totalEnergyBurned); - writeNotNull('totalEnergyBurnedUnit', - _$HealthDataUnitEnumMap[instance.totalEnergyBurnedUnit]); - writeNotNull('totalDistance', instance.totalDistance); - writeNotNull( - 'totalDistanceUnit', _$HealthDataUnitEnumMap[instance.totalDistanceUnit]); - writeNotNull('totalSteps', instance.totalSteps); - writeNotNull( - 'totalStepsUnit', _$HealthDataUnitEnumMap[instance.totalStepsUnit]); - return val; -} +Map _$WorkoutHealthValueToJson(WorkoutHealthValue instance) => + { + if (instance.$type case final value?) '__type': value, + 'workoutActivityType': + _$HealthWorkoutActivityTypeEnumMap[instance.workoutActivityType]!, + if (instance.totalEnergyBurned case final value?) + 'totalEnergyBurned': value, + if (_$HealthDataUnitEnumMap[instance.totalEnergyBurnedUnit] + case final value?) + 'totalEnergyBurnedUnit': value, + if (instance.totalDistance case final value?) 'totalDistance': value, + if (_$HealthDataUnitEnumMap[instance.totalDistanceUnit] case final value?) + 'totalDistanceUnit': value, + if (instance.totalSteps case final value?) 'totalSteps': value, + if (_$HealthDataUnitEnumMap[instance.totalStepsUnit] case final value?) + 'totalStepsUnit': value, + }; const _$HealthWorkoutActivityTypeEnumMap = { HealthWorkoutActivityType.AMERICAN_FOOTBALL: 'AMERICAN_FOOTBALL', @@ -406,6 +370,7 @@ const _$HealthWorkoutActivityTypeEnumMap = { HealthWorkoutActivityType.WHEELCHAIR_RUN_PACE: 'WHEELCHAIR_RUN_PACE', HealthWorkoutActivityType.WHEELCHAIR_WALK_PACE: 'WHEELCHAIR_WALK_PACE', HealthWorkoutActivityType.WRESTLING: 'WRESTLING', + HealthWorkoutActivityType.UNDERWATER_DIVING: 'UNDERWATER_DIVING', HealthWorkoutActivityType.BIKING_STATIONARY: 'BIKING_STATIONARY', HealthWorkoutActivityType.CALISTHENICS: 'CALISTHENICS', HealthWorkoutActivityType.DANCING: 'DANCING', @@ -443,23 +408,18 @@ ElectrocardiogramHealthValue _$ElectrocardiogramHealthValueFromJson( )..$type = json['__type'] as String?; Map _$ElectrocardiogramHealthValueToJson( - ElectrocardiogramHealthValue instance) { - final val = {}; - - void writeNotNull(String key, dynamic value) { - if (value != null) { - val[key] = value; - } - } - - writeNotNull('__type', instance.$type); - val['voltageValues'] = instance.voltageValues.map((e) => e.toJson()).toList(); - writeNotNull('averageHeartRate', instance.averageHeartRate); - writeNotNull('samplingFrequency', instance.samplingFrequency); - writeNotNull('classification', - _$ElectrocardiogramClassificationEnumMap[instance.classification]); - return val; -} + ElectrocardiogramHealthValue instance) => + { + if (instance.$type case final value?) '__type': value, + 'voltageValues': instance.voltageValues.map((e) => e.toJson()).toList(), + if (instance.averageHeartRate case final value?) + 'averageHeartRate': value, + if (instance.samplingFrequency case final value?) + 'samplingFrequency': value, + if (_$ElectrocardiogramClassificationEnumMap[instance.classification] + case final value?) + 'classification': value, + }; const _$ElectrocardiogramClassificationEnumMap = { ElectrocardiogramClassification.NOT_SET: 'NOT_SET', @@ -483,20 +443,12 @@ ElectrocardiogramVoltageValue _$ElectrocardiogramVoltageValueFromJson( )..$type = json['__type'] as String?; Map _$ElectrocardiogramVoltageValueToJson( - ElectrocardiogramVoltageValue instance) { - final val = {}; - - void writeNotNull(String key, dynamic value) { - if (value != null) { - val[key] = value; - } - } - - writeNotNull('__type', instance.$type); - val['voltage'] = instance.voltage; - val['timeSinceSampleStart'] = instance.timeSinceSampleStart; - return val; -} + ElectrocardiogramVoltageValue instance) => + { + if (instance.$type case final value?) '__type': value, + 'voltage': instance.voltage, + 'timeSinceSampleStart': instance.timeSinceSampleStart, + }; InsulinDeliveryHealthValue _$InsulinDeliveryHealthValueFromJson( Map json) => @@ -506,20 +458,12 @@ InsulinDeliveryHealthValue _$InsulinDeliveryHealthValueFromJson( )..$type = json['__type'] as String?; Map _$InsulinDeliveryHealthValueToJson( - InsulinDeliveryHealthValue instance) { - final val = {}; - - void writeNotNull(String key, dynamic value) { - if (value != null) { - val[key] = value; - } - } - - writeNotNull('__type', instance.$type); - val['units'] = instance.units; - val['reason'] = _$InsulinDeliveryReasonEnumMap[instance.reason]!; - return val; -} + InsulinDeliveryHealthValue instance) => + { + if (instance.$type case final value?) '__type': value, + 'units': instance.units, + 'reason': _$InsulinDeliveryReasonEnumMap[instance.reason]!, + }; const _$InsulinDeliveryReasonEnumMap = { InsulinDeliveryReason.NOT_SET: 'NOT_SET', @@ -577,62 +521,58 @@ NutritionHealthValue _$NutritionHealthValueFromJson( )..$type = json['__type'] as String?; Map _$NutritionHealthValueToJson( - NutritionHealthValue instance) { - final val = {}; - - void writeNotNull(String key, dynamic value) { - if (value != null) { - val[key] = value; - } - } - - writeNotNull('__type', instance.$type); - writeNotNull('name', instance.name); - writeNotNull('mealType', instance.mealType); - writeNotNull('calories', instance.calories); - writeNotNull('protein', instance.protein); - writeNotNull('fat', instance.fat); - writeNotNull('carbs', instance.carbs); - writeNotNull('caffeine', instance.caffeine); - writeNotNull('vitaminA', instance.vitaminA); - writeNotNull('b1Thiamine', instance.b1Thiamine); - writeNotNull('b2Riboflavin', instance.b2Riboflavin); - writeNotNull('b3Niacin', instance.b3Niacin); - writeNotNull('b5PantothenicAcid', instance.b5PantothenicAcid); - writeNotNull('b6Pyridoxine', instance.b6Pyridoxine); - writeNotNull('b7Biotin', instance.b7Biotin); - writeNotNull('b9Folate', instance.b9Folate); - writeNotNull('b12Cobalamin', instance.b12Cobalamin); - writeNotNull('vitaminC', instance.vitaminC); - writeNotNull('vitaminD', instance.vitaminD); - writeNotNull('vitaminE', instance.vitaminE); - writeNotNull('vitaminK', instance.vitaminK); - writeNotNull('calcium', instance.calcium); - writeNotNull('chloride', instance.chloride); - writeNotNull('cholesterol', instance.cholesterol); - writeNotNull('choline', instance.choline); - writeNotNull('chromium', instance.chromium); - writeNotNull('copper', instance.copper); - writeNotNull('fatUnsaturated', instance.fatUnsaturated); - writeNotNull('fatMonounsaturated', instance.fatMonounsaturated); - writeNotNull('fatPolyunsaturated', instance.fatPolyunsaturated); - writeNotNull('fatSaturated', instance.fatSaturated); - writeNotNull('fatTransMonoenoic', instance.fatTransMonoenoic); - writeNotNull('fiber', instance.fiber); - writeNotNull('iodine', instance.iodine); - writeNotNull('iron', instance.iron); - writeNotNull('magnesium', instance.magnesium); - writeNotNull('manganese', instance.manganese); - writeNotNull('molybdenum', instance.molybdenum); - writeNotNull('phosphorus', instance.phosphorus); - writeNotNull('potassium', instance.potassium); - writeNotNull('selenium', instance.selenium); - writeNotNull('sodium', instance.sodium); - writeNotNull('sugar', instance.sugar); - writeNotNull('water', instance.water); - writeNotNull('zinc', instance.zinc); - return val; -} + NutritionHealthValue instance) => + { + if (instance.$type case final value?) '__type': value, + if (instance.name case final value?) 'name': value, + if (instance.mealType case final value?) 'mealType': value, + if (instance.calories case final value?) 'calories': value, + if (instance.protein case final value?) 'protein': value, + if (instance.fat case final value?) 'fat': value, + if (instance.carbs case final value?) 'carbs': value, + if (instance.caffeine case final value?) 'caffeine': value, + if (instance.vitaminA case final value?) 'vitaminA': value, + if (instance.b1Thiamine case final value?) 'b1Thiamine': value, + if (instance.b2Riboflavin case final value?) 'b2Riboflavin': value, + if (instance.b3Niacin case final value?) 'b3Niacin': value, + if (instance.b5PantothenicAcid case final value?) + 'b5PantothenicAcid': value, + if (instance.b6Pyridoxine case final value?) 'b6Pyridoxine': value, + if (instance.b7Biotin case final value?) 'b7Biotin': value, + if (instance.b9Folate case final value?) 'b9Folate': value, + if (instance.b12Cobalamin case final value?) 'b12Cobalamin': value, + if (instance.vitaminC case final value?) 'vitaminC': value, + if (instance.vitaminD case final value?) 'vitaminD': value, + if (instance.vitaminE case final value?) 'vitaminE': value, + if (instance.vitaminK case final value?) 'vitaminK': value, + if (instance.calcium case final value?) 'calcium': value, + if (instance.chloride case final value?) 'chloride': value, + if (instance.cholesterol case final value?) 'cholesterol': value, + if (instance.choline case final value?) 'choline': value, + if (instance.chromium case final value?) 'chromium': value, + if (instance.copper case final value?) 'copper': value, + if (instance.fatUnsaturated case final value?) 'fatUnsaturated': value, + if (instance.fatMonounsaturated case final value?) + 'fatMonounsaturated': value, + if (instance.fatPolyunsaturated case final value?) + 'fatPolyunsaturated': value, + if (instance.fatSaturated case final value?) 'fatSaturated': value, + if (instance.fatTransMonoenoic case final value?) + 'fatTransMonoenoic': value, + if (instance.fiber case final value?) 'fiber': value, + if (instance.iodine case final value?) 'iodine': value, + if (instance.iron case final value?) 'iron': value, + if (instance.magnesium case final value?) 'magnesium': value, + if (instance.manganese case final value?) 'manganese': value, + if (instance.molybdenum case final value?) 'molybdenum': value, + if (instance.phosphorus case final value?) 'phosphorus': value, + if (instance.potassium case final value?) 'potassium': value, + if (instance.selenium case final value?) 'selenium': value, + if (instance.sodium case final value?) 'sodium': value, + if (instance.sugar case final value?) 'sugar': value, + if (instance.water case final value?) 'water': value, + if (instance.zinc case final value?) 'zinc': value, + }; MenstruationFlowHealthValue _$MenstruationFlowHealthValueFromJson( Map json) => @@ -644,22 +584,15 @@ MenstruationFlowHealthValue _$MenstruationFlowHealthValueFromJson( )..$type = json['__type'] as String?; Map _$MenstruationFlowHealthValueToJson( - MenstruationFlowHealthValue instance) { - final val = {}; - - void writeNotNull(String key, dynamic value) { - if (value != null) { - val[key] = value; - } - } - - writeNotNull('__type', instance.$type); - writeNotNull('flow', _$MenstrualFlowEnumMap[instance.flow]); - writeNotNull('isStartOfCycle', instance.isStartOfCycle); - writeNotNull('wasUserEntered', instance.wasUserEntered); - val['dateTime'] = instance.dateTime.toIso8601String(); - return val; -} + MenstruationFlowHealthValue instance) => + { + if (instance.$type case final value?) '__type': value, + if (_$MenstrualFlowEnumMap[instance.flow] case final value?) + 'flow': value, + if (instance.isStartOfCycle case final value?) 'isStartOfCycle': value, + if (instance.wasUserEntered case final value?) 'wasUserEntered': value, + 'dateTime': instance.dateTime.toIso8601String(), + }; const _$MenstrualFlowEnumMap = { MenstrualFlow.unspecified: 'unspecified', diff --git a/packages/health/lib/src/health_plugin.dart b/packages/health/lib/src/health_plugin.dart index 8868a519b..6f513b0ac 100644 --- a/packages/health/lib/src/health_plugin.dart +++ b/packages/health/lib/src/health_plugin.dart @@ -1257,6 +1257,7 @@ class Health { HealthWorkoutActivityType.YOGA, HealthWorkoutActivityType.SWIMMING_OPEN_WATER, HealthWorkoutActivityType.SWIMMING_POOL, + HealthWorkoutActivityType.UNDERWATER_DIVING, }.contains(type); } diff --git a/packages/health/lib/src/heath_data_types.dart b/packages/health/lib/src/heath_data_types.dart index f50762721..878bbc00f 100644 --- a/packages/health/lib/src/heath_data_types.dart +++ b/packages/health/lib/src/heath_data_types.dart @@ -95,6 +95,8 @@ enum HealthDataType { BIRTH_DATE, BLOOD_TYPE, MENSTRUATION_FLOW, + WATER_TEMPERATURE, + UNDERWATER_DEPTH, // Heart Rate events (specific to Apple Watch) HIGH_HEART_RATE_EVENT, @@ -206,6 +208,8 @@ const List dataTypeKeysIOS = [ HealthDataType.BIRTH_DATE, HealthDataType.BLOOD_TYPE, HealthDataType.MENSTRUATION_FLOW, + HealthDataType.WATER_TEMPERATURE, + HealthDataType.UNDERWATER_DEPTH, ]; /// List of data types available on Android @@ -352,6 +356,8 @@ const Map dataTypeToUnit = { HealthDataType.NUTRITION: HealthDataUnit.NO_UNIT, HealthDataType.MENSTRUATION_FLOW: HealthDataUnit.NO_UNIT, + HealthDataType.WATER_TEMPERATURE: HealthDataUnit.DEGREE_CELSIUS, + HealthDataType.UNDERWATER_DEPTH: HealthDataUnit.METER, // Health Connect HealthDataType.TOTAL_CALORIES_BURNED: HealthDataUnit.KILOCALORIE, @@ -527,6 +533,7 @@ enum HealthWorkoutActivityType { WHEELCHAIR_RUN_PACE, WHEELCHAIR_WALK_PACE, WRESTLING, + UNDERWATER_DIVING, // Android only BIKING_STATIONARY,