diff --git a/RNAppleHealthKit.podspec b/RNAppleHealthKit.podspec index 144eeb5c..1f259b80 100644 --- a/RNAppleHealthKit.podspec +++ b/RNAppleHealthKit.podspec @@ -11,25 +11,30 @@ Pod::Spec.new do |s| s.version = '1.7.0' s.summary = 'A React Native package to interact with Apple HealthKit' -# 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? -# * Try to keep it short, snappy and to the point. -# * Write the description between the DESC delimiters below. -# * Finally, don't worry about the indent, CocoaPods strips it! + # 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? + # * Try to keep it short, snappy and to the point. + # * Write the description between the DESC delimiters below. + # * Finally, don't worry about the indent, CocoaPods strips it! - s.description = <<-DESC -A React Native package to interact with Apple HealthKit - DESC + s.description = <<~DESC + A React Native package to interact with Apple HealthKit + DESC s.homepage = 'https://github.com/agencyenterprise/react-native-health' - s.license = { :type => 'MIT', :file => 'LICENSE' } + 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/agencyenterprise/react-native-healthkit.git', + tag: s.version.to_s, + submodules: true + } - s.ios.deployment_target = '9.0' - s.swift_version = '4.2' + s.ios.deployment_target = '14.0' + s.swift_version = '5.5' - s.source_files = 'RCTAppleHealthKit/**/*' + s.source_files = ['v2/RNHealthKitCore/ReactNativeBridge/**/*', 'v2/RNHealthKitCore/HealthKitCore/**/*.swift'] + s.requires_arc = true s.frameworks = ['HealthKit'] s.dependency 'React' diff --git a/example/.buckconfig b/example/.buckconfig deleted file mode 100644 index 934256cb..00000000 --- a/example/.buckconfig +++ /dev/null @@ -1,6 +0,0 @@ - -[android] - target = Google Inc.:Google APIs:23 - -[maven_repositories] - central = https://repo1.maven.org/maven2 diff --git a/example/.eslintrc.js b/example/.eslintrc.js index 40c6dcd0..187894b6 100644 --- a/example/.eslintrc.js +++ b/example/.eslintrc.js @@ -1,4 +1,4 @@ module.exports = { root: true, - extends: '@react-native-community', + extends: '@react-native', }; diff --git a/example/.gitattributes b/example/.gitattributes deleted file mode 100644 index d42ff183..00000000 --- a/example/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*.pbxproj -text diff --git a/example/.gitignore b/example/.gitignore index 6a5e410a..0cab2ac6 100644 --- a/example/.gitignore +++ b/example/.gitignore @@ -20,6 +20,7 @@ DerivedData *.hmap *.ipa *.xcuserstate +ios/.xcode.env.local # Android/IntelliJ # @@ -28,10 +29,10 @@ build/ .gradle local.properties *.iml - -# Visual Studio Code -# -.vscode/ +*.hprof +.cxx/ +*.keystore +!debug.keystore # node.js # @@ -39,12 +40,6 @@ node_modules/ npm-debug.log yarn-error.log -# BUCK -buck-out/ -\.buckd/ -*.keystore -!debug.keystore - # fastlane # # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the @@ -52,12 +47,20 @@ buck-out/ # For more information about the recommended setup visit: # https://docs.fastlane.tools/best-practices/source-control/ -*/fastlane/report.xml -*/fastlane/Preview.html -*/fastlane/screenshots +**/fastlane/report.xml +**/fastlane/Preview.html +**/fastlane/screenshots +**/fastlane/test_output # Bundle artifact *.jsbundle -# CocoaPods +# Ruby / CocoaPods /ios/Pods/ +/vendor/bundle/ + +# Temporary files created by Metro to check the health of the file watcher +.metro-health-check* + +# testing +/coverage diff --git a/example/.prettierrc.js b/example/.prettierrc.js index 5c4de1a4..2b540746 100644 --- a/example/.prettierrc.js +++ b/example/.prettierrc.js @@ -1,6 +1,7 @@ module.exports = { + arrowParens: 'avoid', + bracketSameLine: true, bracketSpacing: false, - jsxBracketSameLine: true, singleQuote: true, trailingComma: 'all', }; diff --git a/example/.watchmanconfig b/example/.watchmanconfig index 9e26dfee..0967ef42 100644 --- a/example/.watchmanconfig +++ b/example/.watchmanconfig @@ -1 +1 @@ -{} \ No newline at end of file +{} diff --git a/example/App.tsx b/example/App.tsx index 7f2a9dad..f66284f4 100644 --- a/example/App.tsx +++ b/example/App.tsx @@ -1,4 +1,4 @@ -import React, {useState, useEffect} from 'react'; +import React, {useEffect} from 'react'; import { SafeAreaView, StyleSheet, @@ -6,66 +6,127 @@ import { View, Text, StatusBar, + Button, } from 'react-native'; -import {Colors} from 'react-native/Libraries/NewAppScreen'; -import AppleHealthKit, { - HealthValue, - HealthKitPermissions, +import RNHealthKit, { + HealthType, + HealthUnit, + StatisticsOption, + Interval, + WorkoutActivityType, + WorkoutMetadataKey, + WorkoutSessionLocationType, + WorkoutSwimmingLocationType, } from 'react-native-health'; -import {NativeEventEmitter, NativeModules} from 'react-native'; +RNHealthKit.initHealthKit( + [HealthType.HeartRate, HealthType.Workout], + [HealthType.HeartRate, HealthType.Workout], +); -/* Permission options */ -const permissions = { - permissions: { - read: [AppleHealthKit.Constants.Permissions.HeartRate], - write: [AppleHealthKit.Constants.Permissions.Steps], - }, -} as HealthKitPermissions; +async function runQuantityQuery() { + const result = await RNHealthKit.getQuantitySamples({ + type: HealthType.HeartRate, + startDate: new Date(2023, 7, 1).toISOString(), + endDate: new Date().toISOString(), + unit: HealthUnit.BeatsPerMinute, + }); + console.log(result); +} + +async function runStatisticsQuery() { + const result = await RNHealthKit.getQuantitySamplesStatistics({ + type: HealthType.ActiveEnergyBurned, + startDate: new Date(2022, 0, 1).toISOString(), + endDate: new Date(2024, 0, 1).toISOString(), + interval: Interval.Year, + anchorDate: new Date(2023, 0, 1).toISOString(), + unit: HealthUnit.Kilocalories, + option: StatisticsOption.CumulativeSum, + }); + console.log(result); +} + +async function saveQuantitySample() { + const result = await RNHealthKit.saveQuantitySample(HealthType.HeartRate, { + startDate: new Date().toISOString(), + endDate: new Date().toISOString(), + value: 82, + unit: HealthUnit.BeatsPerMinute, + metadata: { + TestingMetadata: 'TestingValue', + }, + }); + console.log(result); +} -AppleHealthKit.initHealthKit(permissions, (error: string) => { - /* Called after we receive a response from the system */ +async function runWorkoutQuery() { + const result = await RNHealthKit.getWorkouts({ + startDate: new Date(2023, 7, 1).toISOString(), + endDate: new Date().toISOString(), + activityTypes: [WorkoutActivityType.SwimBikeRun], + }); + console.log(result); +} - if (error) { - console.log('[ERROR] Cannot grant permissions!'); - } +async function saveWorkout() { + const conf1 = { + workoutActivityType: WorkoutActivityType.Swimming, + workoutLocationType: WorkoutSessionLocationType.Outdoor, + workoutSwimmingLocationType: WorkoutSwimmingLocationType.OpenWater, + }; - /* Can now read or write to HealthKit */ + const conf2 = { + workoutActivityType: WorkoutActivityType.Running, + workoutLocationType: WorkoutSessionLocationType.Outdoor, + workoutSwimmingLocationType: WorkoutSwimmingLocationType.Unknown, + }; - const options = { - startDate: new Date(2020, 1, 1).toISOString(), + const activity1 = { + workoutConfiguration: conf1, + startDate: new Date(2023, 8, 8, 4, 0).toISOString(), + endDate: new Date(2023, 8, 8, 4, 6).toISOString(), + metadata: null, }; - AppleHealthKit.getHeartRateSamples( - options, - (callbackError: string, results: HealthValue[]) => { - /* Samples are now collected from HealthKit */ + const activity2 = { + workoutConfiguration: conf2, + startDate: new Date(2023, 8, 8, 4, 10).toISOString(), + endDate: new Date(2023, 8, 8, 4, 15).toISOString(), + metadata: null, + }; + + const activities = [activity1, activity2]; + + const result = await RNHealthKit.saveWorkout({ + activityType: WorkoutActivityType.SwimBikeRun, + startDate: new Date(2023, 8, 8, 4).toISOString(), + endDate: new Date(2023, 8, 8, 5).toISOString(), + activities: activities, + metadata: { + [WorkoutMetadataKey.IndoorWorkout]: false, + [WorkoutMetadataKey.FitnessMachineDuration]: { + unit: HealthUnit.Minutes, + doubleValue: 60, + }, }, - ); -}); + }); + console.log(result); +} export default function App() { - const [authStatus, setAuthStatus] = useState({}); + // const [authStatus, setAuthStatus] = useState({}); useEffect(() => { - new NativeEventEmitter(NativeModules.AppleHealthKit).addListener( - 'healthKit:HeartRate:new', - async () => { - console.log('--> observer triggered'); - }, - ); + // new NativeEventEmitter(NativeModules.AppleHealthKit).addListener( + // 'healthKit:HeartRate:new', + // async () => { + // console.log('--> observer triggered'); + // }, + // ); }); - const handlePressGetAuthStatus = () => { - AppleHealthKit.getAuthStatus(permissions, (err, result) => { - if (err) { - console.error(err); - } - setAuthStatus(result); - }); - }; - return ( <> @@ -78,12 +139,36 @@ export default function App() { React Native Health Example - - Press me to get Auth Status - - - {JSON.stringify(authStatus, null, 2)} - +