From 3086d95ec7fa6573767e34162f32fd3542fcf5c9 Mon Sep 17 00:00:00 2001 From: Robert Herber Date: Wed, 13 Sep 2023 14:59:57 +0200 Subject: [PATCH 1/9] chore: release 7.3.0 --- CHANGELOG.md | 21 +++++++++++++++++++++ package.json | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18006be..9bd88ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,24 @@ +# [7.3.0](https://github.com/kingstinct/react-native-healthkit/compare/v7.2.0...v7.3.0) (2023-09-13) + + +### Bug Fixes + +* handle when enddate is nil ([1146385](https://github.com/kingstinct/react-native-healthkit/commit/11463857c493091ac0b916d1ee7694f77c7dfe9a)) +* return uuid string ([9679e8a](https://github.com/kingstinct/react-native-healthkit/commit/9679e8a12507ba51a6ea4088d421ec9c4e56dfe8)) +* swift placeholder for workoutPlanId ([3389e17](https://github.com/kingstinct/react-native-healthkit/commit/3389e17d423926ea6b9b8513822a5510cf1370a8)) + + +### Features + +* add more types ([c100a64](https://github.com/kingstinct/react-native-healthkit/commit/c100a6419a766a1aa8126202acd7ad2b98576bb5)) +* allow totals in saveWorkoutSamples ([89c57db](https://github.com/kingstinct/react-native-healthkit/commit/89c57dbd5c8d312345f2fbf9c9e28db2d676a733)) +* create getWorkoutPlanId function ([ec3d7ef](https://github.com/kingstinct/react-native-healthkit/commit/ec3d7ef62aa6ab1a2fff2a8e34ffd13be5976a71)) +* handle when function is called by OS less than 17 ([81a5e01](https://github.com/kingstinct/react-native-healthkit/commit/81a5e01a5f8bbb55e9188c027e9330ad59b0b199)) +* move getWorkoutPlan into its own async function ([d72d3e5](https://github.com/kingstinct/react-native-healthkit/commit/d72d3e59f982d0cde5602488fb926e2a7109abcb)) +* rename function to getWorkoutPlanById and return id and activity type ([edfecf2](https://github.com/kingstinct/react-native-healthkit/commit/edfecf2b40f6b9f94e8d5fd2995b8ee0ea1b8d7b)) +* rename function to getWorkoutPlanById and return id and activity type ([ff252ac](https://github.com/kingstinct/react-native-healthkit/commit/ff252acbf85967952c40780298bdbbe352774b7b)) +* saveWorkoutRoute function ([e9eaee8](https://github.com/kingstinct/react-native-healthkit/commit/e9eaee83a556ff0112b19384bc945b4e9ccddade)) + # [7.2.0](https://github.com/kingstinct/react-native-healthkit/compare/v7.1.1...v7.2.0) (2023-09-04) diff --git a/package.json b/package.json index 5a0d789..c8ba2a0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kingstinct/react-native-healthkit", - "version": "7.2.0", + "version": "7.3.0", "description": "React Native bindings for HealthKit", "main": "lib/commonjs/index", "module": "lib/module/index", From 3ffe295e6bd271b0a31026e59fc82ccaebbbba83 Mon Sep 17 00:00:00 2001 From: Josh Parnham Date: Mon, 25 Sep 2023 15:49:46 -0700 Subject: [PATCH 2/9] Update queryStatisticsForQuantity to resolve when statistics in callback is nil --- ios/ReactNativeHealthkit.swift | 65 ++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/ios/ReactNativeHealthkit.swift b/ios/ReactNativeHealthkit.swift index 06f436a..eba7026 100644 --- a/ios/ReactNativeHealthkit.swift +++ b/ios/ReactNativeHealthkit.swift @@ -673,42 +673,45 @@ class ReactNativeHealthkit: RCTEventEmitter { } let query = HKStatisticsQuery.init(quantityType: quantityType, quantitySamplePredicate: predicate, options: opts) { (_, stats: HKStatistics?, _: Error?) in - if let gottenStats = stats { - var dic = [String: [String: Any]?]() - let unit = HKUnit.init(from: unitString) - if let averageQuantity = gottenStats.averageQuantity() { - dic.updateValue(serializeQuantity(unit: unit, quantity: averageQuantity), forKey: "averageQuantity") - } - if let maximumQuantity = gottenStats.maximumQuantity() { - dic.updateValue(serializeQuantity(unit: unit, quantity: maximumQuantity), forKey: "maximumQuantity") - } - if let minimumQuantity = gottenStats.minimumQuantity() { - dic.updateValue(serializeQuantity(unit: unit, quantity: minimumQuantity), forKey: "minimumQuantity") - } - if let sumQuantity = gottenStats.sumQuantity() { - dic.updateValue(serializeQuantity(unit: unit, quantity: sumQuantity), forKey: "sumQuantity") + var dic = [String: [String: Any]?]() + + guard let gottenStats = stats else { + return resolve(dic) + } + + let unit = HKUnit.init(from: unitString) + if let averageQuantity = gottenStats.averageQuantity() { + dic.updateValue(serializeQuantity(unit: unit, quantity: averageQuantity), forKey: "averageQuantity") + } + if let maximumQuantity = gottenStats.maximumQuantity() { + dic.updateValue(serializeQuantity(unit: unit, quantity: maximumQuantity), forKey: "maximumQuantity") + } + if let minimumQuantity = gottenStats.minimumQuantity() { + dic.updateValue(serializeQuantity(unit: unit, quantity: minimumQuantity), forKey: "minimumQuantity") + } + if let sumQuantity = gottenStats.sumQuantity() { + dic.updateValue(serializeQuantity(unit: unit, quantity: sumQuantity), forKey: "sumQuantity") + } + if #available(iOS 12, *) { + if let mostRecent = gottenStats.mostRecentQuantity() { + dic.updateValue(serializeQuantity(unit: unit, quantity: mostRecent), forKey: "mostRecentQuantity") } - if #available(iOS 12, *) { - if let mostRecent = gottenStats.mostRecentQuantity() { - dic.updateValue(serializeQuantity(unit: unit, quantity: mostRecent), forKey: "mostRecentQuantity") - } - if let mostRecentDateInterval = gottenStats.mostRecentQuantityDateInterval() { - dic.updateValue([ - "start": self._dateFormatter.string(from: mostRecentDateInterval.start), - "end": self._dateFormatter.string(from: mostRecentDateInterval.end) - ], forKey: "mostRecentQuantityDateInterval") - } + if let mostRecentDateInterval = gottenStats.mostRecentQuantityDateInterval() { + dic.updateValue([ + "start": self._dateFormatter.string(from: mostRecentDateInterval.start), + "end": self._dateFormatter.string(from: mostRecentDateInterval.end) + ], forKey: "mostRecentQuantityDateInterval") } - if #available(iOS 13, *) { - let durationUnit = HKUnit.second() - if let duration = gottenStats.duration() { - dic.updateValue(serializeQuantity(unit: durationUnit, quantity: duration), forKey: "duration") - } + } + if #available(iOS 13, *) { + let durationUnit = HKUnit.second() + if let duration = gottenStats.duration() { + dic.updateValue(serializeQuantity(unit: durationUnit, quantity: duration), forKey: "duration") } - - resolve(dic) } + + resolve(dic) } store.execute(query) From 928cd3b73723686a57905204a26162ed7535454d Mon Sep 17 00:00:00 2001 From: Robert Herber Date: Thu, 19 Oct 2023 14:45:31 +0200 Subject: [PATCH 3/9] style: add named exports --- example/src/App.tsx | 26 +- src/hooks/useHealthkitAuthorization.ts | 5 + src/hooks/useMostRecentCategorySample.ts | 3 + src/hooks/useMostRecentQuantitySample.ts | 3 + src/hooks/useMostRecentWorkout.ts | 3 + src/index.ios.tsx | 219 -------------- src/index.native.tsx | 201 +++++++++++++ src/index.tsx | 361 +++++++++++++++++------ src/index.web.tsx | 1 + src/utils/saveCategorySample.ts | 4 + 10 files changed, 502 insertions(+), 324 deletions(-) delete mode 100644 src/index.ios.tsx create mode 100644 src/index.native.tsx create mode 100644 src/index.web.tsx diff --git a/example/src/App.tsx b/example/src/App.tsx index 894d8ce..e37d530 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -5,19 +5,19 @@ import Healthkit, { HKStatisticsOptions, HKWorkoutActivityType, HKCategoryTypeIdentifier, + useMostRecentQuantitySample, + useStatisticsForQuantity, + useSources, + useMostRecentWorkout, + useHealthkitAuthorization, + deleteQuantitySample, + deleteSamples, + queryHeartbeatSeriesSamplesWithAnchor, + queryQuantitySamplesWithAnchor, + saveQuantitySample, + saveWorkoutRoute, + saveWorkoutSample, } from '@kingstinct/react-native-healthkit' -import useHealthkitAuthorization from '@kingstinct/react-native-healthkit/hooks/useHealthkitAuthorization' -import useMostRecentQuantitySample from '@kingstinct/react-native-healthkit/hooks/useMostRecentQuantitySample' -import useMostRecentWorkout from '@kingstinct/react-native-healthkit/hooks/useMostRecentWorkout' -import useSources from '@kingstinct/react-native-healthkit/hooks/useSources' -import useStatisticsForQuantity from '@kingstinct/react-native-healthkit/hooks/useStatisticsForQuantity' -import deleteQuantitySample from '@kingstinct/react-native-healthkit/utils/deleteQuantitySample' -import deleteSamples from '@kingstinct/react-native-healthkit/utils/deleteSamples' -import queryHeartbeatSeriesSamplesWithAnchor from '@kingstinct/react-native-healthkit/utils/queryHeartbeatSeriesSamplesWithAnchor' -import queryQuantitySamplesWithAnchor from '@kingstinct/react-native-healthkit/utils/queryQuantitySamplesWithAnchor' -import saveQuantitySample from '@kingstinct/react-native-healthkit/utils/saveQuantitySample' -import saveWorkoutRoute from '@kingstinct/react-native-healthkit/utils/saveWorkoutRoute' -import saveWorkoutSample from '@kingstinct/react-native-healthkit/utils/saveWorkoutSample' import dayjs from 'dayjs' import relativeTime from 'dayjs/plugin/relativeTime' import React, { @@ -629,7 +629,7 @@ const App = () => { const [canAccessProtectedData, setAccessProtectedData] = useState(false) useEffect(() => { - Healthkit.canAccessProtectedData() + Healthkit.isProtectedDataAvailable() .then(setAccessProtectedData) .catch(() => setAccessProtectedData(false)) }, []) diff --git a/src/hooks/useHealthkitAuthorization.ts b/src/hooks/useHealthkitAuthorization.ts index cd54e34..f3f60fa 100644 --- a/src/hooks/useHealthkitAuthorization.ts +++ b/src/hooks/useHealthkitAuthorization.ts @@ -7,6 +7,11 @@ import requestAuthorization from '../utils/requestAuthorization' import type { HealthkitReadAuthorization, HealthkitWriteAuthorization, HKAuthorizationRequestStatus } from '../native-types' +/** + * @description Hook to retrieve the current authorization status for the given types, and request authorization if needed. + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614152-requestauthorization Apple Docs - requestAuthorization} + * @see {@link https://developer.apple.com/documentation/healthkit/authorizing_access_to_health_data Apple Docs - Authorizing access to health data} + */ const useHealthkitAuthorization = (read: readonly HealthkitReadAuthorization[], write?: readonly HealthkitWriteAuthorization[]) => { const [status, setStatus] = useState(null) diff --git a/src/hooks/useMostRecentCategorySample.ts b/src/hooks/useMostRecentCategorySample.ts index 069f071..dbb2653 100644 --- a/src/hooks/useMostRecentCategorySample.ts +++ b/src/hooks/useMostRecentCategorySample.ts @@ -6,6 +6,9 @@ import getMostRecentCategorySample from '../utils/getMostRecentCategorySample' import type { HKCategoryTypeIdentifier } from '../native-types' import type { HKCategorySample } from '../types' +/** + * @returns the most recent sample for the given category type. + */ function useMostRecentCategorySample< TCategory extends HKCategoryTypeIdentifier >(identifier: TCategory) { diff --git a/src/hooks/useMostRecentQuantitySample.ts b/src/hooks/useMostRecentQuantitySample.ts index c33adc2..f3a9ef1 100644 --- a/src/hooks/useMostRecentQuantitySample.ts +++ b/src/hooks/useMostRecentQuantitySample.ts @@ -7,6 +7,9 @@ import subscribeToChanges from '../utils/subscribeToChanges' import type { HKQuantityTypeIdentifier, UnitForIdentifier } from '../native-types' import type { HKQuantitySample } from '../types' +/** + * @returns the most recent sample for the given quantity type. + */ function useMostRecentQuantitySample< TIdentifier extends HKQuantityTypeIdentifier, TUnit extends UnitForIdentifier diff --git a/src/hooks/useMostRecentWorkout.ts b/src/hooks/useMostRecentWorkout.ts index ec20ee3..14bbcd5 100644 --- a/src/hooks/useMostRecentWorkout.ts +++ b/src/hooks/useMostRecentWorkout.ts @@ -9,6 +9,9 @@ import subscribeToChanges from '../utils/subscribeToChanges' import type { EnergyUnit, LengthUnit } from '../native-types' import type { HKWorkout } from '../types' +/** + * @returns the most recent workout sample. + */ function useMostRecentWorkout< TEnergy extends EnergyUnit, TDistance extends LengthUnit diff --git a/src/index.ios.tsx b/src/index.ios.tsx deleted file mode 100644 index 094ab45..0000000 --- a/src/index.ios.tsx +++ /dev/null @@ -1,219 +0,0 @@ -import { Platform } from 'react-native' - -import useHealthkitAuthorization from './hooks/useHealthkitAuthorization' -import useIsHealthDataAvailable from './hooks/useIsHealthDataAvailable' -import useMostRecentCategorySample from './hooks/useMostRecentCategorySample' -import useMostRecentQuantitySample from './hooks/useMostRecentQuantitySample' -import useMostRecentWorkout from './hooks/useMostRecentWorkout' -import useSubscribeToChanges from './hooks/useSubscribeToChanges' -import Native, { HKQuantityTypeIdentifier } from './native-types' -import deleteQuantitySample from './utils/deleteQuantitySample' -import deleteSamples from './utils/deleteSamples' -import getDateOfBirth from './utils/getDateOfBirth' -import getMostRecentCategorySample from './utils/getMostRecentCategorySample' -import getMostRecentQuantitySample from './utils/getMostRecentQuantitySample' -import getMostRecentWorkout from './utils/getMostRecentWorkout' -import getPreferredUnit from './utils/getPreferredUnit' -import getPreferredUnits from './utils/getPreferredUnits' -import getRequestStatusForAuthorization from './utils/getRequestStatusForAuthorization' -import getWorkoutPlanById from './utils/getWorkoutPlanById' -import queryCategorySamples from './utils/queryCategorySamples' -import queryCategorySamplesWithAnchor from './utils/queryCategorySamplesWithAnchor' -import queryCorrelationSamples from './utils/queryCorrelationSamples' -import queryHeartbeatSeriesSamples from './utils/queryHeartbeatSeriesSamples' -import queryHeartbeatSeriesSamplesWithAnchor from './utils/queryHeartbeatSeriesSamplesWithAnchor' -import queryQuantitySamples from './utils/queryQuantitySamples' -import queryQuantitySamplesWithAnchor from './utils/queryQuantitySamplesWithAnchor' -import querySources from './utils/querySources' -import queryStatisticsForQuantity from './utils/queryStatisticsForQuantity' -import queryWorkouts from './utils/queryWorkouts' -import requestAuthorization from './utils/requestAuthorization' -import saveCategorySample from './utils/saveCategorySample' -import saveCorrelationSample from './utils/saveCorrelationSample' -import saveQuantitySample from './utils/saveQuantitySample' -import saveWorkoutRoute from './utils/saveWorkoutRoute' -import saveWorkoutSample from './utils/saveWorkoutSample' -import subscribeToChanges from './utils/subscribeToChanges' - -const currentMajorVersionIOS = Platform.OS === 'ios' ? parseInt(Platform.Version, 10) : 0 - -const allQuantityTypesList = [...Object.values(HKQuantityTypeIdentifier)] - -const availableQuantityTypes = (majorVersionIOS = currentMajorVersionIOS) => { - if (majorVersionIOS >= 17) { - return allQuantityTypesList - } - - // remove types that are not available before iOS 17 - return allQuantityTypesList.filter((type) => ![ - HKQuantityTypeIdentifier.cyclingCadence, - HKQuantityTypeIdentifier.cyclingFunctionalThresholdPower, - HKQuantityTypeIdentifier.cyclingPower, - HKQuantityTypeIdentifier.cyclingSpeed, - HKQuantityTypeIdentifier.physicalEffort, - HKQuantityTypeIdentifier.timeInDaylight, - ].includes(type)) -} - -const authorizationStatusFor = Native.authorizationStatusFor.bind(Native) -const isHealthDataAvailable = Native.isHealthDataAvailable.bind(Native) -// Todo [>8]: Rename to align with Apple function name (isProtectedDataAvailable) -const canAccessProtectedData = Native.canAccessProtectedData.bind(Native) -const disableBackgroundDelivery = Native.disableBackgroundDelivery.bind(Native) -const disableAllBackgroundDelivery = Native.disableAllBackgroundDelivery.bind(Native) -const enableBackgroundDelivery = Native.enableBackgroundDelivery.bind(Native) -const getBiologicalSex = Native.getBiologicalSex.bind(Native) -const getFitzpatrickSkinType = Native.getFitzpatrickSkinType.bind(Native) -const getWheelchairUse = Native.getWheelchairUse.bind(Native) -const getBloodType = Native.getBloodType.bind(Native) -const getWorkoutRoutes = Native.getWorkoutRoutes.bind(Native) - -/** - * @see {@link https://developer.apple.com/documentation/healthkit/about_the_healthkit_framework About the HealthKit Framework (Apple Docs)} - */ -export default { - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614154-authorizationstatus authorizationStatus(for:) (Apple Docs) } - * @see {@link https://developer.apple.com/documentation/healthkit/authorizing_access_to_health_data Authorizing access to health data (Apple Docs) } - */ - authorizationStatusFor, - - /** - * - * @returns All available quantity types for the current iOS version (currently excluding types that are not available before iOS 17) - */ - availableQuantityTypes, - - /** - * @description By default, HealthKit data is available on iOS and watchOS. HealthKit data is also available on iPadOS 17 or later. However, devices running in an enterprise environment may restrict access to HealthKit data. - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614180-ishealthdataavailable isHealthDataAvailable() (Apple Docs)} - * @returns {boolean} true if HealthKit is available; otherwise, false. - */ - isHealthDataAvailable, - - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614181-isprotecteddataavailable isProtectedDataAvailable() (Apple Docs)} - * @see {@link https://developer.apple.com/documentation/healthkit/protecting_user_privacy#3705074 Protecting User Privacy - Access encrypted data (Apple Docs)} - * @returns {boolean} A Boolean value that indicates whether content protection is active. - */ - isProtectedDataAvailable: canAccessProtectedData, - - // Todo [>8]: Remove to align with Apple function name (isProtectedDataAvailable) - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614181-isprotecteddataavailable isProtectedDataAvailable() (Apple Docs)} - * @see {@link https://developer.apple.com/documentation/healthkit/protecting_user_privacy#3705074 Protecting User Privacy - Access encrypted data (Apple Docs)} - * @deprecated Use {@link isProtectedDataAvailable} instead. Will be removed in next major version. - * @returns {boolean} A Boolean value that indicates whether content protection is active. - */ - canAccessProtectedData, - - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614158-disableallbackgrounddelivery disableAllBackgroundDelivery(completion:) (Apple Docs)} - */ - disableAllBackgroundDelivery, - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614177-disablebackgrounddelivery disableBackgroundDelivery(for:withCompletion:) (Apple Docs)} - */ - disableBackgroundDelivery, - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614175-enablebackgrounddelivery enableBackgroundDelivery(for:frequency:withCompletion:) (Apple Docs)} - */ - enableBackgroundDelivery, - - // simple convenience getters - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614171-biologicalsex biologicalSex() (Apple Docs)} - */ - getBiologicalSex, - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614161-fitzpatrickskintype fitzpatrickSkinType() (Apple Docs)} - */ - getFitzpatrickSkinType, - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1648356-wheelchairuse wheelchairUse() (Apple Docs)} - */ - getWheelchairUse, - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614164-bloodtype bloodType() (Apple Docs)} - */ - getBloodType, - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1648357-dateofbirthcomponents dateOfBirthComponents() (Apple Docs)} - */ - getDateOfBirth, - - getMostRecentQuantitySample, - getMostRecentCategorySample, - getMostRecentWorkout, - - /** - * @see {@link https://developer.apple.com/documentation/healthkit/workouts_and_activity_rings/reading_route_data Reading route data (Apple Docs)} - * @see {@link https://developer.apple.com/documentation/healthkit/hkworkoutroutequery HKWorkoutRouteQuery (Apple Docs)} - */ - getWorkoutRoutes, - getWorkoutPlanById, - - getPreferredUnit, - getPreferredUnits, - getRequestStatusForAuthorization, - - // query methods - queryCategorySamples, - queryCategorySamplesWithAnchor, - queryCorrelationSamples, - queryHeartbeatSeriesSamples, - queryHeartbeatSeriesSamplesWithAnchor, - queryQuantitySamples, - queryQuantitySamplesWithAnchor, - queryStatisticsForQuantity, - queryWorkouts, - querySources, - - requestAuthorization, - - // delete methods - deleteQuantitySample, - deleteSamples, - - // save methods - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614168-savecategorysample save(_:withCompletion:) (Apple Docs)} - * @see {@link https://developer.apple.com/documentation/healthkit/saving_data_to_healthkit Saving data to HealthKit (Apple Docs)} - */ - saveCategorySample, - saveCorrelationSample, - saveQuantitySample, - saveWorkoutSample, - saveWorkoutRoute, - - // subscriptions - subscribeToChanges, - - /** - * @returns the most recent sample for the given category type. - */ - useMostRecentCategorySample, - /** - * @returns the most recent sample for the given quantity type. - */ - useMostRecentQuantitySample, - /** - * @returns the most recent workout sample. - */ - useMostRecentWorkout, - useSubscribeToChanges, - /** - * @description By default, HealthKit data is available on iOS and watchOS. HealthKit data is also available on iPadOS 17 or later. However, devices running in an enterprise environment may restrict access to HealthKit data. - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614180-ishealthdataavailable Apple Docs} - * @returns {boolean | null} true if HealthKit is available; otherwise, false. null while initializing. - */ - useIsHealthDataAvailable, - /** - * @description Hook to retrieve the current authorization status for the given types, and request authorization if needed. - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614152-requestauthorization Apple Docs - requestAuthorization} - * @see {@link https://developer.apple.com/documentation/healthkit/authorizing_access_to_health_data Apple Docs - Authorizing access to health data} - */ - useHealthkitAuthorization, -} - -export * from './types' diff --git a/src/index.native.tsx b/src/index.native.tsx new file mode 100644 index 0000000..7557520 --- /dev/null +++ b/src/index.native.tsx @@ -0,0 +1,201 @@ +import { Platform } from 'react-native' + +import { + HKAuthorizationRequestStatus, HKAuthorizationStatus, HKBiologicalSex, HKBloodType, HKFitzpatrickSkinType, HKUnits, HKWheelchairUse, +} from './native-types' + +import type ReactNativeHealthkit from '.' +import type { QueryCategorySamplesFn } from './utils/queryCategorySamples' +import type { QueryQuantitySamplesFn } from './utils/queryQuantitySamples' + +const notAvailableError = `[@kingstinct/react-native-healthkit] Platform "${ + Platform.OS +}" not supported` + +let hasWarned = false + +function UnavailableFn(retVal: T) { + return () => { + if (!hasWarned) { + // eslint-disable-next-line no-console + console.warn(notAvailableError) + hasWarned = true + } + return retVal + } +} + +const authorizationStatusFor = UnavailableFn(Promise.resolve(HKAuthorizationStatus.notDetermined)), + availableQuantityTypes = UnavailableFn([]), + disableAllBackgroundDelivery = UnavailableFn(Promise.resolve(false)), + disableBackgroundDelivery = UnavailableFn(Promise.resolve(false)), + enableBackgroundDelivery = UnavailableFn(Promise.resolve(false)), + getBiologicalSex = UnavailableFn(Promise.resolve(HKBiologicalSex.notSet)), + getBloodType = UnavailableFn(Promise.resolve(HKBloodType.notSet)), + getDateOfBirth = UnavailableFn(Promise.resolve(new Date(0))), + getFitzpatrickSkinType = UnavailableFn(Promise.resolve(HKFitzpatrickSkinType.notSet)), + getMostRecentCategorySample = UnavailableFn(Promise.resolve(null)), + getMostRecentQuantitySample = UnavailableFn(Promise.resolve(null)), + getMostRecentWorkout = UnavailableFn(Promise.resolve(null)), + getPreferredUnit = UnavailableFn(Promise.resolve(HKUnits.Count)), + getPreferredUnits = UnavailableFn(Promise.resolve([])), + getRequestStatusForAuthorization = UnavailableFn(Promise.resolve(HKAuthorizationRequestStatus.unknown)), + getWheelchairUse = UnavailableFn(Promise.resolve(HKWheelchairUse.notSet)), + getWorkoutRoutes = UnavailableFn(Promise.resolve([])), + isHealthDataAvailable = async () => Promise.resolve(false), + useSources = UnavailableFn(null), + useStatisticsForQuantity = UnavailableFn(null), + queryCategorySamples = UnavailableFn(Promise.resolve([])) as unknown as QueryCategorySamplesFn, + queryCategorySamplesWithAnchor = UnavailableFn(Promise.resolve({ + samples: [], + deletedSamples: [], + newAnchor: '', + })), + queryCorrelationSamples = UnavailableFn(Promise.resolve([])), + queryHeartbeatSeriesSamples = UnavailableFn(Promise.resolve([])), + queryHeartbeatSeriesSamplesWithAnchor = UnavailableFn(Promise.resolve({ + samples: [], + deletedSamples: [], + newAnchor: '', + })), + queryQuantitySamples = UnavailableFn(Promise.resolve([])) as unknown as QueryQuantitySamplesFn, + queryQuantitySamplesWithAnchor = UnavailableFn(Promise.resolve({ + samples: [], + deletedSamples: [], + newAnchor: '', + })), + queryStatisticsForQuantity = UnavailableFn(Promise.resolve({ + averageQuantity: undefined, + maximumQuantity: undefined, + minimumQuantity: undefined, + sumQuantity: undefined, + mostRecentQuantity: undefined, + mostRecentQuantityDateInterval: undefined, + duration: undefined, + })), + queryWorkouts = UnavailableFn(Promise.resolve([])), + querySources = UnavailableFn(Promise.resolve([])), + requestAuthorization = UnavailableFn(Promise.resolve(false)), + deleteQuantitySample = UnavailableFn(Promise.resolve(false)), + deleteSamples = UnavailableFn(Promise.resolve(false)), + getWorkoutPlanById = UnavailableFn(Promise.resolve(null)), + saveCategorySample = UnavailableFn(Promise.resolve(false)), + saveCorrelationSample = UnavailableFn(Promise.resolve(false)), + saveQuantitySample = UnavailableFn(Promise.resolve(false)), + saveWorkoutSample = UnavailableFn(Promise.resolve(null)), + saveWorkoutRoute = UnavailableFn(Promise.resolve(false)), + subscribeToChanges = UnavailableFn(Promise.resolve(async () => Promise.resolve(false))), + useMostRecentCategorySample = UnavailableFn(null), + useMostRecentQuantitySample = UnavailableFn(null), + useMostRecentWorkout = UnavailableFn(null), + useSubscribeToChanges = UnavailableFn([null, () => null]), + useHealthkitAuthorization = UnavailableFn([null, async () => Promise.resolve(HKAuthorizationRequestStatus.unknown)] as const), + useIsHealthDataAvailable = () => false, + canAccessProtectedData = async () => Promise.resolve(false), + isProtectedDataAvailable = async () => Promise.resolve(false) + +const Healthkit: typeof ReactNativeHealthkit = { + authorizationStatusFor, + availableQuantityTypes, + useSources, + useStatisticsForQuantity, + disableAllBackgroundDelivery, + disableBackgroundDelivery, + enableBackgroundDelivery, + getBiologicalSex, + getBloodType, + getDateOfBirth, + getFitzpatrickSkinType, + getMostRecentCategorySample, + getMostRecentQuantitySample, + getMostRecentWorkout, + getPreferredUnit, + getPreferredUnits, + getRequestStatusForAuthorization, + getWheelchairUse, + getWorkoutRoutes, + isHealthDataAvailable, + queryCategorySamples, + queryCategorySamplesWithAnchor, + queryCorrelationSamples, + queryHeartbeatSeriesSamples, + queryHeartbeatSeriesSamplesWithAnchor, + queryQuantitySamples, + queryQuantitySamplesWithAnchor, + queryStatisticsForQuantity, + queryWorkouts, + querySources, + requestAuthorization, + deleteQuantitySample, + deleteSamples, + getWorkoutPlanById, + saveCategorySample, + saveCorrelationSample, + saveQuantitySample, + saveWorkoutSample, + saveWorkoutRoute, + subscribeToChanges, + useMostRecentCategorySample, + useMostRecentQuantitySample, + useMostRecentWorkout, + useSubscribeToChanges, + useHealthkitAuthorization, + useIsHealthDataAvailable, + canAccessProtectedData, + isProtectedDataAvailable, +} + +export { + authorizationStatusFor, + availableQuantityTypes, + disableAllBackgroundDelivery, + disableBackgroundDelivery, + enableBackgroundDelivery, + useSources, + useStatisticsForQuantity, + getBiologicalSex, + getBloodType, + getDateOfBirth, + getFitzpatrickSkinType, + getMostRecentCategorySample, + getMostRecentQuantitySample, + getMostRecentWorkout, + getPreferredUnit, + getPreferredUnits, + getRequestStatusForAuthorization, + getWheelchairUse, + getWorkoutRoutes, + isHealthDataAvailable, + queryCategorySamples, + queryCategorySamplesWithAnchor, + queryCorrelationSamples, + queryHeartbeatSeriesSamples, + queryHeartbeatSeriesSamplesWithAnchor, + queryQuantitySamples, + queryQuantitySamplesWithAnchor, + queryStatisticsForQuantity, + queryWorkouts, + querySources, + requestAuthorization, + deleteQuantitySample, + deleteSamples, + getWorkoutPlanById, + saveCategorySample, + saveCorrelationSample, + saveQuantitySample, + saveWorkoutSample, + saveWorkoutRoute, + subscribeToChanges, + useMostRecentCategorySample, + useMostRecentQuantitySample, + useMostRecentWorkout, + useSubscribeToChanges, + useHealthkitAuthorization, + useIsHealthDataAvailable, + canAccessProtectedData, + isProtectedDataAvailable, +} + +export * from './types' + +export default Healthkit diff --git a/src/index.tsx b/src/index.tsx index c7d0747..7f60ef5 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,99 +1,276 @@ import { Platform } from 'react-native' -import { - HKAuthorizationRequestStatus, HKAuthorizationStatus, HKBiologicalSex, HKBloodType, HKFitzpatrickSkinType, HKUnits, HKWheelchairUse, -} from './native-types' - -import type ReactNativeHealthkit from './index.ios' -import type { QueryCategorySamplesFn } from './utils/queryCategorySamples' -import type { QueryQuantitySamplesFn } from './utils/queryQuantitySamples' - -const notAvailableError = `[@kingstinct/react-native-healthkit] Platform "${ - Platform.OS -}" not supported` - -let hasWarned = false - -function UnavailableFn(retVal: T) { - return () => { - if (!hasWarned) { - // eslint-disable-next-line no-console - console.warn(notAvailableError) - hasWarned = true - } - return retVal +import useHealthkitAuthorization from './hooks/useHealthkitAuthorization' +import useIsHealthDataAvailable from './hooks/useIsHealthDataAvailable' +import useMostRecentCategorySample from './hooks/useMostRecentCategorySample' +import useMostRecentQuantitySample from './hooks/useMostRecentQuantitySample' +import useMostRecentWorkout from './hooks/useMostRecentWorkout' +import useSources from './hooks/useSources' +import useStatisticsForQuantity from './hooks/useStatisticsForQuantity' +import useSubscribeToChanges from './hooks/useSubscribeToChanges' +import Native, { HKQuantityTypeIdentifier } from './native-types' +import deleteQuantitySample from './utils/deleteQuantitySample' +import deleteSamples from './utils/deleteSamples' +import getDateOfBirth from './utils/getDateOfBirth' +import getMostRecentCategorySample from './utils/getMostRecentCategorySample' +import getMostRecentQuantitySample from './utils/getMostRecentQuantitySample' +import getMostRecentWorkout from './utils/getMostRecentWorkout' +import getPreferredUnit from './utils/getPreferredUnit' +import getPreferredUnits from './utils/getPreferredUnits' +import getRequestStatusForAuthorization from './utils/getRequestStatusForAuthorization' +import getWorkoutPlanById from './utils/getWorkoutPlanById' +import queryCategorySamples from './utils/queryCategorySamples' +import queryCategorySamplesWithAnchor from './utils/queryCategorySamplesWithAnchor' +import queryCorrelationSamples from './utils/queryCorrelationSamples' +import queryHeartbeatSeriesSamples from './utils/queryHeartbeatSeriesSamples' +import queryHeartbeatSeriesSamplesWithAnchor from './utils/queryHeartbeatSeriesSamplesWithAnchor' +import queryQuantitySamples from './utils/queryQuantitySamples' +import queryQuantitySamplesWithAnchor from './utils/queryQuantitySamplesWithAnchor' +import querySources from './utils/querySources' +import queryStatisticsForQuantity from './utils/queryStatisticsForQuantity' +import queryWorkouts from './utils/queryWorkouts' +import requestAuthorization from './utils/requestAuthorization' +import saveCategorySample from './utils/saveCategorySample' +import saveCorrelationSample from './utils/saveCorrelationSample' +import saveQuantitySample from './utils/saveQuantitySample' +import saveWorkoutRoute from './utils/saveWorkoutRoute' +import saveWorkoutSample from './utils/saveWorkoutSample' +import subscribeToChanges from './utils/subscribeToChanges' + +const currentMajorVersionIOS = Platform.OS === 'ios' ? parseInt(Platform.Version, 10) : 0 + +const allQuantityTypesList = [...Object.values(HKQuantityTypeIdentifier)] + +const availableQuantityTypes = (majorVersionIOS = currentMajorVersionIOS) => { + if (majorVersionIOS >= 17) { + return allQuantityTypesList } + + // remove types that are not available before iOS 17 + return allQuantityTypesList.filter((type) => ![ + HKQuantityTypeIdentifier.cyclingCadence, + HKQuantityTypeIdentifier.cyclingFunctionalThresholdPower, + HKQuantityTypeIdentifier.cyclingPower, + HKQuantityTypeIdentifier.cyclingSpeed, + HKQuantityTypeIdentifier.physicalEffort, + HKQuantityTypeIdentifier.timeInDaylight, + ].includes(type)) } -const Healthkit = { - authorizationStatusFor: UnavailableFn(Promise.resolve(HKAuthorizationStatus.notDetermined)), - availableQuantityTypes: UnavailableFn([]), - disableAllBackgroundDelivery: UnavailableFn(Promise.resolve(false)), - disableBackgroundDelivery: UnavailableFn(Promise.resolve(false)), - enableBackgroundDelivery: UnavailableFn(Promise.resolve(false)), - getBiologicalSex: UnavailableFn(Promise.resolve(HKBiologicalSex.notSet)), - getBloodType: UnavailableFn(Promise.resolve(HKBloodType.notSet)), - getDateOfBirth: UnavailableFn(Promise.resolve(new Date(0))), - getFitzpatrickSkinType: UnavailableFn(Promise.resolve(HKFitzpatrickSkinType.notSet)), - getMostRecentCategorySample: UnavailableFn(Promise.resolve(null)), - getMostRecentQuantitySample: UnavailableFn(Promise.resolve(null)), - getMostRecentWorkout: UnavailableFn(Promise.resolve(null)), - getPreferredUnit: UnavailableFn(Promise.resolve(HKUnits.Count)), - getPreferredUnits: UnavailableFn(Promise.resolve([])), - getRequestStatusForAuthorization: UnavailableFn(Promise.resolve(HKAuthorizationRequestStatus.unknown)), - getWheelchairUse: UnavailableFn(Promise.resolve(HKWheelchairUse.notSet)), - getWorkoutRoutes: UnavailableFn(Promise.resolve([])), - isHealthDataAvailable: async () => Promise.resolve(false), - queryCategorySamples: UnavailableFn(Promise.resolve([])) as unknown as QueryCategorySamplesFn, - queryCategorySamplesWithAnchor: UnavailableFn(Promise.resolve({ - samples: [], - deletedSamples: [], - newAnchor: '', - })), - queryCorrelationSamples: UnavailableFn(Promise.resolve([])), - queryHeartbeatSeriesSamples: UnavailableFn(Promise.resolve([])), - queryHeartbeatSeriesSamplesWithAnchor: UnavailableFn(Promise.resolve({ - samples: [], - deletedSamples: [], - newAnchor: '', - })), - queryQuantitySamples: UnavailableFn(Promise.resolve([])) as unknown as QueryQuantitySamplesFn, - queryQuantitySamplesWithAnchor: UnavailableFn(Promise.resolve({ - samples: [], - deletedSamples: [], - newAnchor: '', - })), - queryStatisticsForQuantity: UnavailableFn(Promise.resolve({ - averageQuantity: undefined, - maximumQuantity: undefined, - minimumQuantity: undefined, - sumQuantity: undefined, - mostRecentQuantity: undefined, - mostRecentQuantityDateInterval: undefined, - duration: undefined, - })), - queryWorkouts: UnavailableFn(Promise.resolve([])), - querySources: UnavailableFn(Promise.resolve([])), - requestAuthorization: UnavailableFn(Promise.resolve(false)), - deleteQuantitySample: UnavailableFn(Promise.resolve(false)), - deleteSamples: UnavailableFn(Promise.resolve(false)), - getWorkoutPlanById: UnavailableFn(Promise.resolve(null)), - saveCategorySample: UnavailableFn(Promise.resolve(false)), - saveCorrelationSample: UnavailableFn(Promise.resolve(false)), - saveQuantitySample: UnavailableFn(Promise.resolve(false)), - saveWorkoutSample: UnavailableFn(Promise.resolve(null)), - saveWorkoutRoute: UnavailableFn(Promise.resolve(false)), - subscribeToChanges: UnavailableFn(Promise.resolve(async () => Promise.resolve(false))), - useMostRecentCategorySample: UnavailableFn(null), - useMostRecentQuantitySample: UnavailableFn(null), - useMostRecentWorkout: UnavailableFn(null), - useSubscribeToChanges: UnavailableFn([null, () => null]), - useHealthkitAuthorization: UnavailableFn([null, async () => Promise.resolve(HKAuthorizationRequestStatus.unknown)] as const), - useIsHealthDataAvailable: () => false, - canAccessProtectedData: async () => Promise.resolve(false), - isProtectedDataAvailable: async () => Promise.resolve(false), -} as typeof ReactNativeHealthkit +const authorizationStatusFor = Native.authorizationStatusFor.bind(Native) +const isHealthDataAvailable = Native.isHealthDataAvailable.bind(Native) +// Todo [>8]: Rename to align with Apple function name (isProtectedDataAvailable) +const canAccessProtectedData = Native.canAccessProtectedData.bind(Native) +const disableBackgroundDelivery = Native.disableBackgroundDelivery.bind(Native) +const disableAllBackgroundDelivery = Native.disableAllBackgroundDelivery.bind(Native) +const enableBackgroundDelivery = Native.enableBackgroundDelivery.bind(Native) +const getBiologicalSex = Native.getBiologicalSex.bind(Native) +const getFitzpatrickSkinType = Native.getFitzpatrickSkinType.bind(Native) +const getWheelchairUse = Native.getWheelchairUse.bind(Native) +const getBloodType = Native.getBloodType.bind(Native) +const getWorkoutRoutes = Native.getWorkoutRoutes.bind(Native) -export * from './types' +/** + * @see {@link https://developer.apple.com/documentation/healthkit/about_the_healthkit_framework About the HealthKit Framework (Apple Docs)} + */ +export default { + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614154-authorizationstatus authorizationStatus(for:) (Apple Docs) } + * @see {@link https://developer.apple.com/documentation/healthkit/authorizing_access_to_health_data Authorizing access to health data (Apple Docs) } + */ + authorizationStatusFor, + + /** + * + * @returns All available quantity types for the current iOS version (currently excluding types that are not available before iOS 17) + */ + availableQuantityTypes, + + /** + * @description By default, HealthKit data is available on iOS and watchOS. HealthKit data is also available on iPadOS 17 or later. However, devices running in an enterprise environment may restrict access to HealthKit data. + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614180-ishealthdataavailable isHealthDataAvailable() (Apple Docs)} + * @returns {boolean} true if HealthKit is available; otherwise, false. + */ + isHealthDataAvailable, + + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614181-isprotecteddataavailable isProtectedDataAvailable() (Apple Docs)} + * @see {@link https://developer.apple.com/documentation/healthkit/protecting_user_privacy#3705074 Protecting User Privacy - Access encrypted data (Apple Docs)} + * @returns {boolean} A Boolean value that indicates whether content protection is active. + */ + isProtectedDataAvailable: canAccessProtectedData, + + // Todo [>8]: Remove to align with Apple function name (isProtectedDataAvailable) + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614181-isprotecteddataavailable isProtectedDataAvailable() (Apple Docs)} + * @see {@link https://developer.apple.com/documentation/healthkit/protecting_user_privacy#3705074 Protecting User Privacy - Access encrypted data (Apple Docs)} + * @deprecated Use {@link isProtectedDataAvailable} instead. Will be removed in next major version. + * @returns {boolean} A Boolean value that indicates whether content protection is active. + */ + canAccessProtectedData, + + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614158-disableallbackgrounddelivery disableAllBackgroundDelivery(completion:) (Apple Docs)} + */ + disableAllBackgroundDelivery, + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614177-disablebackgrounddelivery disableBackgroundDelivery(for:withCompletion:) (Apple Docs)} + */ + disableBackgroundDelivery, + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614175-enablebackgrounddelivery enableBackgroundDelivery(for:frequency:withCompletion:) (Apple Docs)} + */ + enableBackgroundDelivery, + + // simple convenience getters + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614171-biologicalsex biologicalSex() (Apple Docs)} + */ + getBiologicalSex, + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614161-fitzpatrickskintype fitzpatrickSkinType() (Apple Docs)} + */ + getFitzpatrickSkinType, + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1648356-wheelchairuse wheelchairUse() (Apple Docs)} + */ + getWheelchairUse, + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614164-bloodtype bloodType() (Apple Docs)} + */ + getBloodType, + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1648357-dateofbirthcomponents dateOfBirthComponents() (Apple Docs)} + */ + getDateOfBirth, + + getMostRecentQuantitySample, + getMostRecentCategorySample, + getMostRecentWorkout, + + /** + * @see {@link https://developer.apple.com/documentation/healthkit/workouts_and_activity_rings/reading_route_data Reading route data (Apple Docs)} + * @see {@link https://developer.apple.com/documentation/healthkit/hkworkoutroutequery HKWorkoutRouteQuery (Apple Docs)} + */ + getWorkoutRoutes, + getWorkoutPlanById, -export default Healthkit as typeof ReactNativeHealthkit + getPreferredUnit, + getPreferredUnits, + getRequestStatusForAuthorization, + + // query methods + queryCategorySamples, + queryCategorySamplesWithAnchor, + queryCorrelationSamples, + queryHeartbeatSeriesSamples, + queryHeartbeatSeriesSamplesWithAnchor, + queryQuantitySamples, + queryQuantitySamplesWithAnchor, + queryStatisticsForQuantity, + queryWorkouts, + querySources, + + requestAuthorization, + + // delete methods + deleteQuantitySample, + deleteSamples, + + // save methods + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614168-savecategorysample save(_:withCompletion:) (Apple Docs)} + * @see {@link https://developer.apple.com/documentation/healthkit/saving_data_to_healthkit Saving data to HealthKit (Apple Docs)} + */ + saveCategorySample, + saveCorrelationSample, + saveQuantitySample, + saveWorkoutSample, + saveWorkoutRoute, + + // subscriptions + subscribeToChanges, + + /** + * @returns the most recent sample for the given category type. + */ + useMostRecentCategorySample, + /** + * @returns the most recent sample for the given quantity type. + */ + useMostRecentQuantitySample, + /** + * @returns the most recent workout sample. + */ + useMostRecentWorkout, + useSubscribeToChanges, + /** + * @description By default, HealthKit data is available on iOS and watchOS. HealthKit data is also available on iPadOS 17 or later. However, devices running in an enterprise environment may restrict access to HealthKit data. + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614180-ishealthdataavailable Apple Docs} + * @returns {boolean | null} true if HealthKit is available; otherwise, false. null while initializing. + */ + useIsHealthDataAvailable, + /** + * @description Hook to retrieve the current authorization status for the given types, and request authorization if needed. + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614152-requestauthorization Apple Docs - requestAuthorization} + * @see {@link https://developer.apple.com/documentation/healthkit/authorizing_access_to_health_data Apple Docs - Authorizing access to health data} + */ + useHealthkitAuthorization, + useSources, + useStatisticsForQuantity, +} + +const isProtectedDataAvailable = canAccessProtectedData + +export { + authorizationStatusFor, + availableQuantityTypes, + disableAllBackgroundDelivery, + disableBackgroundDelivery, + enableBackgroundDelivery, + getBiologicalSex, + getBloodType, + getDateOfBirth, + getFitzpatrickSkinType, + getMostRecentCategorySample, + getMostRecentQuantitySample, + getMostRecentWorkout, + getPreferredUnit, + getPreferredUnits, + getRequestStatusForAuthorization, + getWheelchairUse, + getWorkoutRoutes, + isHealthDataAvailable, + queryCategorySamples, + queryCategorySamplesWithAnchor, + queryCorrelationSamples, + queryHeartbeatSeriesSamples, + queryHeartbeatSeriesSamplesWithAnchor, + queryQuantitySamples, + queryQuantitySamplesWithAnchor, + queryStatisticsForQuantity, + queryWorkouts, + querySources, + requestAuthorization, + deleteQuantitySample, + deleteSamples, + getWorkoutPlanById, + saveCategorySample, + saveCorrelationSample, + saveQuantitySample, + saveWorkoutSample, + saveWorkoutRoute, + subscribeToChanges, + useMostRecentCategorySample, + useMostRecentQuantitySample, + useMostRecentWorkout, + useSubscribeToChanges, + useHealthkitAuthorization, + useIsHealthDataAvailable, + useSources, + useStatisticsForQuantity, + canAccessProtectedData, + isProtectedDataAvailable, +} + +export * from './types' diff --git a/src/index.web.tsx b/src/index.web.tsx new file mode 100644 index 0000000..41b84ba --- /dev/null +++ b/src/index.web.tsx @@ -0,0 +1 @@ +export * from './index.native' diff --git a/src/utils/saveCategorySample.ts b/src/utils/saveCategorySample.ts index 0d0ae76..0a5b126 100644 --- a/src/utils/saveCategorySample.ts +++ b/src/utils/saveCategorySample.ts @@ -2,6 +2,10 @@ import Native from '../native-types' import type { HKCategoryTypeIdentifier, HKCategoryValueForIdentifier, MetadataMapperForCategoryIdentifier } from '../native-types' +/** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614168-savecategorysample save(_:withCompletion:) (Apple Docs)} + * @see {@link https://developer.apple.com/documentation/healthkit/saving_data_to_healthkit Saving data to HealthKit (Apple Docs)} + */ async function saveCategorySample( identifier: T, value: HKCategoryValueForIdentifier, From 3ec0a2d82b6d7e76d3c5dffb9188b487a4d6a4dc Mon Sep 17 00:00:00 2001 From: Robert Herber Date: Thu, 19 Oct 2023 14:48:15 +0200 Subject: [PATCH 4/9] chore: release 7.3.1 --- CHANGELOG.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bd88ef..afbe8a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## [7.3.1](https://github.com/kingstinct/react-native-healthkit/compare/v7.3.0...v7.3.1) (2023-10-19) + # [7.3.0](https://github.com/kingstinct/react-native-healthkit/compare/v7.2.0...v7.3.0) (2023-09-13) diff --git a/package.json b/package.json index c8ba2a0..958c6dc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kingstinct/react-native-healthkit", - "version": "7.3.0", + "version": "7.3.1", "description": "React Native bindings for HealthKit", "main": "lib/commonjs/index", "module": "lib/module/index", From 95e9a84014e261cc21e62d8f9826ead656d48737 Mon Sep 17 00:00:00 2001 From: Robert Herber Date: Mon, 23 Oct 2023 17:59:39 +0200 Subject: [PATCH 5/9] fix: platform exports gone wrong --- src/index.ios.tsx | 276 ++++++++++++++++++++++++++++++++++++++++++ src/index.native.tsx | 2 +- src/index.tsx | 277 +------------------------------------------ src/index.web.tsx | 4 + 4 files changed, 284 insertions(+), 275 deletions(-) create mode 100644 src/index.ios.tsx diff --git a/src/index.ios.tsx b/src/index.ios.tsx new file mode 100644 index 0000000..7f60ef5 --- /dev/null +++ b/src/index.ios.tsx @@ -0,0 +1,276 @@ +import { Platform } from 'react-native' + +import useHealthkitAuthorization from './hooks/useHealthkitAuthorization' +import useIsHealthDataAvailable from './hooks/useIsHealthDataAvailable' +import useMostRecentCategorySample from './hooks/useMostRecentCategorySample' +import useMostRecentQuantitySample from './hooks/useMostRecentQuantitySample' +import useMostRecentWorkout from './hooks/useMostRecentWorkout' +import useSources from './hooks/useSources' +import useStatisticsForQuantity from './hooks/useStatisticsForQuantity' +import useSubscribeToChanges from './hooks/useSubscribeToChanges' +import Native, { HKQuantityTypeIdentifier } from './native-types' +import deleteQuantitySample from './utils/deleteQuantitySample' +import deleteSamples from './utils/deleteSamples' +import getDateOfBirth from './utils/getDateOfBirth' +import getMostRecentCategorySample from './utils/getMostRecentCategorySample' +import getMostRecentQuantitySample from './utils/getMostRecentQuantitySample' +import getMostRecentWorkout from './utils/getMostRecentWorkout' +import getPreferredUnit from './utils/getPreferredUnit' +import getPreferredUnits from './utils/getPreferredUnits' +import getRequestStatusForAuthorization from './utils/getRequestStatusForAuthorization' +import getWorkoutPlanById from './utils/getWorkoutPlanById' +import queryCategorySamples from './utils/queryCategorySamples' +import queryCategorySamplesWithAnchor from './utils/queryCategorySamplesWithAnchor' +import queryCorrelationSamples from './utils/queryCorrelationSamples' +import queryHeartbeatSeriesSamples from './utils/queryHeartbeatSeriesSamples' +import queryHeartbeatSeriesSamplesWithAnchor from './utils/queryHeartbeatSeriesSamplesWithAnchor' +import queryQuantitySamples from './utils/queryQuantitySamples' +import queryQuantitySamplesWithAnchor from './utils/queryQuantitySamplesWithAnchor' +import querySources from './utils/querySources' +import queryStatisticsForQuantity from './utils/queryStatisticsForQuantity' +import queryWorkouts from './utils/queryWorkouts' +import requestAuthorization from './utils/requestAuthorization' +import saveCategorySample from './utils/saveCategorySample' +import saveCorrelationSample from './utils/saveCorrelationSample' +import saveQuantitySample from './utils/saveQuantitySample' +import saveWorkoutRoute from './utils/saveWorkoutRoute' +import saveWorkoutSample from './utils/saveWorkoutSample' +import subscribeToChanges from './utils/subscribeToChanges' + +const currentMajorVersionIOS = Platform.OS === 'ios' ? parseInt(Platform.Version, 10) : 0 + +const allQuantityTypesList = [...Object.values(HKQuantityTypeIdentifier)] + +const availableQuantityTypes = (majorVersionIOS = currentMajorVersionIOS) => { + if (majorVersionIOS >= 17) { + return allQuantityTypesList + } + + // remove types that are not available before iOS 17 + return allQuantityTypesList.filter((type) => ![ + HKQuantityTypeIdentifier.cyclingCadence, + HKQuantityTypeIdentifier.cyclingFunctionalThresholdPower, + HKQuantityTypeIdentifier.cyclingPower, + HKQuantityTypeIdentifier.cyclingSpeed, + HKQuantityTypeIdentifier.physicalEffort, + HKQuantityTypeIdentifier.timeInDaylight, + ].includes(type)) +} + +const authorizationStatusFor = Native.authorizationStatusFor.bind(Native) +const isHealthDataAvailable = Native.isHealthDataAvailable.bind(Native) +// Todo [>8]: Rename to align with Apple function name (isProtectedDataAvailable) +const canAccessProtectedData = Native.canAccessProtectedData.bind(Native) +const disableBackgroundDelivery = Native.disableBackgroundDelivery.bind(Native) +const disableAllBackgroundDelivery = Native.disableAllBackgroundDelivery.bind(Native) +const enableBackgroundDelivery = Native.enableBackgroundDelivery.bind(Native) +const getBiologicalSex = Native.getBiologicalSex.bind(Native) +const getFitzpatrickSkinType = Native.getFitzpatrickSkinType.bind(Native) +const getWheelchairUse = Native.getWheelchairUse.bind(Native) +const getBloodType = Native.getBloodType.bind(Native) +const getWorkoutRoutes = Native.getWorkoutRoutes.bind(Native) + +/** + * @see {@link https://developer.apple.com/documentation/healthkit/about_the_healthkit_framework About the HealthKit Framework (Apple Docs)} + */ +export default { + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614154-authorizationstatus authorizationStatus(for:) (Apple Docs) } + * @see {@link https://developer.apple.com/documentation/healthkit/authorizing_access_to_health_data Authorizing access to health data (Apple Docs) } + */ + authorizationStatusFor, + + /** + * + * @returns All available quantity types for the current iOS version (currently excluding types that are not available before iOS 17) + */ + availableQuantityTypes, + + /** + * @description By default, HealthKit data is available on iOS and watchOS. HealthKit data is also available on iPadOS 17 or later. However, devices running in an enterprise environment may restrict access to HealthKit data. + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614180-ishealthdataavailable isHealthDataAvailable() (Apple Docs)} + * @returns {boolean} true if HealthKit is available; otherwise, false. + */ + isHealthDataAvailable, + + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614181-isprotecteddataavailable isProtectedDataAvailable() (Apple Docs)} + * @see {@link https://developer.apple.com/documentation/healthkit/protecting_user_privacy#3705074 Protecting User Privacy - Access encrypted data (Apple Docs)} + * @returns {boolean} A Boolean value that indicates whether content protection is active. + */ + isProtectedDataAvailable: canAccessProtectedData, + + // Todo [>8]: Remove to align with Apple function name (isProtectedDataAvailable) + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614181-isprotecteddataavailable isProtectedDataAvailable() (Apple Docs)} + * @see {@link https://developer.apple.com/documentation/healthkit/protecting_user_privacy#3705074 Protecting User Privacy - Access encrypted data (Apple Docs)} + * @deprecated Use {@link isProtectedDataAvailable} instead. Will be removed in next major version. + * @returns {boolean} A Boolean value that indicates whether content protection is active. + */ + canAccessProtectedData, + + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614158-disableallbackgrounddelivery disableAllBackgroundDelivery(completion:) (Apple Docs)} + */ + disableAllBackgroundDelivery, + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614177-disablebackgrounddelivery disableBackgroundDelivery(for:withCompletion:) (Apple Docs)} + */ + disableBackgroundDelivery, + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614175-enablebackgrounddelivery enableBackgroundDelivery(for:frequency:withCompletion:) (Apple Docs)} + */ + enableBackgroundDelivery, + + // simple convenience getters + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614171-biologicalsex biologicalSex() (Apple Docs)} + */ + getBiologicalSex, + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614161-fitzpatrickskintype fitzpatrickSkinType() (Apple Docs)} + */ + getFitzpatrickSkinType, + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1648356-wheelchairuse wheelchairUse() (Apple Docs)} + */ + getWheelchairUse, + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614164-bloodtype bloodType() (Apple Docs)} + */ + getBloodType, + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1648357-dateofbirthcomponents dateOfBirthComponents() (Apple Docs)} + */ + getDateOfBirth, + + getMostRecentQuantitySample, + getMostRecentCategorySample, + getMostRecentWorkout, + + /** + * @see {@link https://developer.apple.com/documentation/healthkit/workouts_and_activity_rings/reading_route_data Reading route data (Apple Docs)} + * @see {@link https://developer.apple.com/documentation/healthkit/hkworkoutroutequery HKWorkoutRouteQuery (Apple Docs)} + */ + getWorkoutRoutes, + getWorkoutPlanById, + + getPreferredUnit, + getPreferredUnits, + getRequestStatusForAuthorization, + + // query methods + queryCategorySamples, + queryCategorySamplesWithAnchor, + queryCorrelationSamples, + queryHeartbeatSeriesSamples, + queryHeartbeatSeriesSamplesWithAnchor, + queryQuantitySamples, + queryQuantitySamplesWithAnchor, + queryStatisticsForQuantity, + queryWorkouts, + querySources, + + requestAuthorization, + + // delete methods + deleteQuantitySample, + deleteSamples, + + // save methods + /** + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614168-savecategorysample save(_:withCompletion:) (Apple Docs)} + * @see {@link https://developer.apple.com/documentation/healthkit/saving_data_to_healthkit Saving data to HealthKit (Apple Docs)} + */ + saveCategorySample, + saveCorrelationSample, + saveQuantitySample, + saveWorkoutSample, + saveWorkoutRoute, + + // subscriptions + subscribeToChanges, + + /** + * @returns the most recent sample for the given category type. + */ + useMostRecentCategorySample, + /** + * @returns the most recent sample for the given quantity type. + */ + useMostRecentQuantitySample, + /** + * @returns the most recent workout sample. + */ + useMostRecentWorkout, + useSubscribeToChanges, + /** + * @description By default, HealthKit data is available on iOS and watchOS. HealthKit data is also available on iPadOS 17 or later. However, devices running in an enterprise environment may restrict access to HealthKit data. + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614180-ishealthdataavailable Apple Docs} + * @returns {boolean | null} true if HealthKit is available; otherwise, false. null while initializing. + */ + useIsHealthDataAvailable, + /** + * @description Hook to retrieve the current authorization status for the given types, and request authorization if needed. + * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614152-requestauthorization Apple Docs - requestAuthorization} + * @see {@link https://developer.apple.com/documentation/healthkit/authorizing_access_to_health_data Apple Docs - Authorizing access to health data} + */ + useHealthkitAuthorization, + useSources, + useStatisticsForQuantity, +} + +const isProtectedDataAvailable = canAccessProtectedData + +export { + authorizationStatusFor, + availableQuantityTypes, + disableAllBackgroundDelivery, + disableBackgroundDelivery, + enableBackgroundDelivery, + getBiologicalSex, + getBloodType, + getDateOfBirth, + getFitzpatrickSkinType, + getMostRecentCategorySample, + getMostRecentQuantitySample, + getMostRecentWorkout, + getPreferredUnit, + getPreferredUnits, + getRequestStatusForAuthorization, + getWheelchairUse, + getWorkoutRoutes, + isHealthDataAvailable, + queryCategorySamples, + queryCategorySamplesWithAnchor, + queryCorrelationSamples, + queryHeartbeatSeriesSamples, + queryHeartbeatSeriesSamplesWithAnchor, + queryQuantitySamples, + queryQuantitySamplesWithAnchor, + queryStatisticsForQuantity, + queryWorkouts, + querySources, + requestAuthorization, + deleteQuantitySample, + deleteSamples, + getWorkoutPlanById, + saveCategorySample, + saveCorrelationSample, + saveQuantitySample, + saveWorkoutSample, + saveWorkoutRoute, + subscribeToChanges, + useMostRecentCategorySample, + useMostRecentQuantitySample, + useMostRecentWorkout, + useSubscribeToChanges, + useHealthkitAuthorization, + useIsHealthDataAvailable, + useSources, + useStatisticsForQuantity, + canAccessProtectedData, + isProtectedDataAvailable, +} + +export * from './types' diff --git a/src/index.native.tsx b/src/index.native.tsx index 7557520..5ae9b11 100644 --- a/src/index.native.tsx +++ b/src/index.native.tsx @@ -4,7 +4,7 @@ import { HKAuthorizationRequestStatus, HKAuthorizationStatus, HKBiologicalSex, HKBloodType, HKFitzpatrickSkinType, HKUnits, HKWheelchairUse, } from './native-types' -import type ReactNativeHealthkit from '.' +import type ReactNativeHealthkit from './index.ios' import type { QueryCategorySamplesFn } from './utils/queryCategorySamples' import type { QueryQuantitySamplesFn } from './utils/queryQuantitySamples' diff --git a/src/index.tsx b/src/index.tsx index 7f60ef5..85985a0 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,276 +1,5 @@ -import { Platform } from 'react-native' +import Healthkit from './index.ios' -import useHealthkitAuthorization from './hooks/useHealthkitAuthorization' -import useIsHealthDataAvailable from './hooks/useIsHealthDataAvailable' -import useMostRecentCategorySample from './hooks/useMostRecentCategorySample' -import useMostRecentQuantitySample from './hooks/useMostRecentQuantitySample' -import useMostRecentWorkout from './hooks/useMostRecentWorkout' -import useSources from './hooks/useSources' -import useStatisticsForQuantity from './hooks/useStatisticsForQuantity' -import useSubscribeToChanges from './hooks/useSubscribeToChanges' -import Native, { HKQuantityTypeIdentifier } from './native-types' -import deleteQuantitySample from './utils/deleteQuantitySample' -import deleteSamples from './utils/deleteSamples' -import getDateOfBirth from './utils/getDateOfBirth' -import getMostRecentCategorySample from './utils/getMostRecentCategorySample' -import getMostRecentQuantitySample from './utils/getMostRecentQuantitySample' -import getMostRecentWorkout from './utils/getMostRecentWorkout' -import getPreferredUnit from './utils/getPreferredUnit' -import getPreferredUnits from './utils/getPreferredUnits' -import getRequestStatusForAuthorization from './utils/getRequestStatusForAuthorization' -import getWorkoutPlanById from './utils/getWorkoutPlanById' -import queryCategorySamples from './utils/queryCategorySamples' -import queryCategorySamplesWithAnchor from './utils/queryCategorySamplesWithAnchor' -import queryCorrelationSamples from './utils/queryCorrelationSamples' -import queryHeartbeatSeriesSamples from './utils/queryHeartbeatSeriesSamples' -import queryHeartbeatSeriesSamplesWithAnchor from './utils/queryHeartbeatSeriesSamplesWithAnchor' -import queryQuantitySamples from './utils/queryQuantitySamples' -import queryQuantitySamplesWithAnchor from './utils/queryQuantitySamplesWithAnchor' -import querySources from './utils/querySources' -import queryStatisticsForQuantity from './utils/queryStatisticsForQuantity' -import queryWorkouts from './utils/queryWorkouts' -import requestAuthorization from './utils/requestAuthorization' -import saveCategorySample from './utils/saveCategorySample' -import saveCorrelationSample from './utils/saveCorrelationSample' -import saveQuantitySample from './utils/saveQuantitySample' -import saveWorkoutRoute from './utils/saveWorkoutRoute' -import saveWorkoutSample from './utils/saveWorkoutSample' -import subscribeToChanges from './utils/subscribeToChanges' +export * from './index.ios' -const currentMajorVersionIOS = Platform.OS === 'ios' ? parseInt(Platform.Version, 10) : 0 - -const allQuantityTypesList = [...Object.values(HKQuantityTypeIdentifier)] - -const availableQuantityTypes = (majorVersionIOS = currentMajorVersionIOS) => { - if (majorVersionIOS >= 17) { - return allQuantityTypesList - } - - // remove types that are not available before iOS 17 - return allQuantityTypesList.filter((type) => ![ - HKQuantityTypeIdentifier.cyclingCadence, - HKQuantityTypeIdentifier.cyclingFunctionalThresholdPower, - HKQuantityTypeIdentifier.cyclingPower, - HKQuantityTypeIdentifier.cyclingSpeed, - HKQuantityTypeIdentifier.physicalEffort, - HKQuantityTypeIdentifier.timeInDaylight, - ].includes(type)) -} - -const authorizationStatusFor = Native.authorizationStatusFor.bind(Native) -const isHealthDataAvailable = Native.isHealthDataAvailable.bind(Native) -// Todo [>8]: Rename to align with Apple function name (isProtectedDataAvailable) -const canAccessProtectedData = Native.canAccessProtectedData.bind(Native) -const disableBackgroundDelivery = Native.disableBackgroundDelivery.bind(Native) -const disableAllBackgroundDelivery = Native.disableAllBackgroundDelivery.bind(Native) -const enableBackgroundDelivery = Native.enableBackgroundDelivery.bind(Native) -const getBiologicalSex = Native.getBiologicalSex.bind(Native) -const getFitzpatrickSkinType = Native.getFitzpatrickSkinType.bind(Native) -const getWheelchairUse = Native.getWheelchairUse.bind(Native) -const getBloodType = Native.getBloodType.bind(Native) -const getWorkoutRoutes = Native.getWorkoutRoutes.bind(Native) - -/** - * @see {@link https://developer.apple.com/documentation/healthkit/about_the_healthkit_framework About the HealthKit Framework (Apple Docs)} - */ -export default { - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614154-authorizationstatus authorizationStatus(for:) (Apple Docs) } - * @see {@link https://developer.apple.com/documentation/healthkit/authorizing_access_to_health_data Authorizing access to health data (Apple Docs) } - */ - authorizationStatusFor, - - /** - * - * @returns All available quantity types for the current iOS version (currently excluding types that are not available before iOS 17) - */ - availableQuantityTypes, - - /** - * @description By default, HealthKit data is available on iOS and watchOS. HealthKit data is also available on iPadOS 17 or later. However, devices running in an enterprise environment may restrict access to HealthKit data. - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614180-ishealthdataavailable isHealthDataAvailable() (Apple Docs)} - * @returns {boolean} true if HealthKit is available; otherwise, false. - */ - isHealthDataAvailable, - - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614181-isprotecteddataavailable isProtectedDataAvailable() (Apple Docs)} - * @see {@link https://developer.apple.com/documentation/healthkit/protecting_user_privacy#3705074 Protecting User Privacy - Access encrypted data (Apple Docs)} - * @returns {boolean} A Boolean value that indicates whether content protection is active. - */ - isProtectedDataAvailable: canAccessProtectedData, - - // Todo [>8]: Remove to align with Apple function name (isProtectedDataAvailable) - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614181-isprotecteddataavailable isProtectedDataAvailable() (Apple Docs)} - * @see {@link https://developer.apple.com/documentation/healthkit/protecting_user_privacy#3705074 Protecting User Privacy - Access encrypted data (Apple Docs)} - * @deprecated Use {@link isProtectedDataAvailable} instead. Will be removed in next major version. - * @returns {boolean} A Boolean value that indicates whether content protection is active. - */ - canAccessProtectedData, - - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614158-disableallbackgrounddelivery disableAllBackgroundDelivery(completion:) (Apple Docs)} - */ - disableAllBackgroundDelivery, - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614177-disablebackgrounddelivery disableBackgroundDelivery(for:withCompletion:) (Apple Docs)} - */ - disableBackgroundDelivery, - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614175-enablebackgrounddelivery enableBackgroundDelivery(for:frequency:withCompletion:) (Apple Docs)} - */ - enableBackgroundDelivery, - - // simple convenience getters - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614171-biologicalsex biologicalSex() (Apple Docs)} - */ - getBiologicalSex, - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614161-fitzpatrickskintype fitzpatrickSkinType() (Apple Docs)} - */ - getFitzpatrickSkinType, - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1648356-wheelchairuse wheelchairUse() (Apple Docs)} - */ - getWheelchairUse, - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614164-bloodtype bloodType() (Apple Docs)} - */ - getBloodType, - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1648357-dateofbirthcomponents dateOfBirthComponents() (Apple Docs)} - */ - getDateOfBirth, - - getMostRecentQuantitySample, - getMostRecentCategorySample, - getMostRecentWorkout, - - /** - * @see {@link https://developer.apple.com/documentation/healthkit/workouts_and_activity_rings/reading_route_data Reading route data (Apple Docs)} - * @see {@link https://developer.apple.com/documentation/healthkit/hkworkoutroutequery HKWorkoutRouteQuery (Apple Docs)} - */ - getWorkoutRoutes, - getWorkoutPlanById, - - getPreferredUnit, - getPreferredUnits, - getRequestStatusForAuthorization, - - // query methods - queryCategorySamples, - queryCategorySamplesWithAnchor, - queryCorrelationSamples, - queryHeartbeatSeriesSamples, - queryHeartbeatSeriesSamplesWithAnchor, - queryQuantitySamples, - queryQuantitySamplesWithAnchor, - queryStatisticsForQuantity, - queryWorkouts, - querySources, - - requestAuthorization, - - // delete methods - deleteQuantitySample, - deleteSamples, - - // save methods - /** - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614168-savecategorysample save(_:withCompletion:) (Apple Docs)} - * @see {@link https://developer.apple.com/documentation/healthkit/saving_data_to_healthkit Saving data to HealthKit (Apple Docs)} - */ - saveCategorySample, - saveCorrelationSample, - saveQuantitySample, - saveWorkoutSample, - saveWorkoutRoute, - - // subscriptions - subscribeToChanges, - - /** - * @returns the most recent sample for the given category type. - */ - useMostRecentCategorySample, - /** - * @returns the most recent sample for the given quantity type. - */ - useMostRecentQuantitySample, - /** - * @returns the most recent workout sample. - */ - useMostRecentWorkout, - useSubscribeToChanges, - /** - * @description By default, HealthKit data is available on iOS and watchOS. HealthKit data is also available on iPadOS 17 or later. However, devices running in an enterprise environment may restrict access to HealthKit data. - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614180-ishealthdataavailable Apple Docs} - * @returns {boolean | null} true if HealthKit is available; otherwise, false. null while initializing. - */ - useIsHealthDataAvailable, - /** - * @description Hook to retrieve the current authorization status for the given types, and request authorization if needed. - * @see {@link https://developer.apple.com/documentation/healthkit/hkhealthstore/1614152-requestauthorization Apple Docs - requestAuthorization} - * @see {@link https://developer.apple.com/documentation/healthkit/authorizing_access_to_health_data Apple Docs - Authorizing access to health data} - */ - useHealthkitAuthorization, - useSources, - useStatisticsForQuantity, -} - -const isProtectedDataAvailable = canAccessProtectedData - -export { - authorizationStatusFor, - availableQuantityTypes, - disableAllBackgroundDelivery, - disableBackgroundDelivery, - enableBackgroundDelivery, - getBiologicalSex, - getBloodType, - getDateOfBirth, - getFitzpatrickSkinType, - getMostRecentCategorySample, - getMostRecentQuantitySample, - getMostRecentWorkout, - getPreferredUnit, - getPreferredUnits, - getRequestStatusForAuthorization, - getWheelchairUse, - getWorkoutRoutes, - isHealthDataAvailable, - queryCategorySamples, - queryCategorySamplesWithAnchor, - queryCorrelationSamples, - queryHeartbeatSeriesSamples, - queryHeartbeatSeriesSamplesWithAnchor, - queryQuantitySamples, - queryQuantitySamplesWithAnchor, - queryStatisticsForQuantity, - queryWorkouts, - querySources, - requestAuthorization, - deleteQuantitySample, - deleteSamples, - getWorkoutPlanById, - saveCategorySample, - saveCorrelationSample, - saveQuantitySample, - saveWorkoutSample, - saveWorkoutRoute, - subscribeToChanges, - useMostRecentCategorySample, - useMostRecentQuantitySample, - useMostRecentWorkout, - useSubscribeToChanges, - useHealthkitAuthorization, - useIsHealthDataAvailable, - useSources, - useStatisticsForQuantity, - canAccessProtectedData, - isProtectedDataAvailable, -} - -export * from './types' +export default Healthkit diff --git a/src/index.web.tsx b/src/index.web.tsx index 41b84ba..28a86a7 100644 --- a/src/index.web.tsx +++ b/src/index.web.tsx @@ -1 +1,5 @@ +import Healthkit from './index.native' + export * from './index.native' + +export default Healthkit From 2e94f738ecc1a61891466e8b870aba52a40c3816 Mon Sep 17 00:00:00 2001 From: Robert Herber Date: Mon, 23 Oct 2023 18:01:34 +0200 Subject: [PATCH 6/9] chore: release 7.3.2 --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index afbe8a7..aa05465 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.3.2](https://github.com/kingstinct/react-native-healthkit/compare/v7.3.1...v7.3.2) (2023-10-23) + + +### Bug Fixes + +* platform exports gone wrong ([95e9a84](https://github.com/kingstinct/react-native-healthkit/commit/95e9a84014e261cc21e62d8f9826ead656d48737)) + ## [7.3.1](https://github.com/kingstinct/react-native-healthkit/compare/v7.3.0...v7.3.1) (2023-10-19) # [7.3.0](https://github.com/kingstinct/react-native-healthkit/compare/v7.2.0...v7.3.0) (2023-09-13) diff --git a/package.json b/package.json index 958c6dc..a860e9b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kingstinct/react-native-healthkit", - "version": "7.3.1", + "version": "7.3.2", "description": "React Native bindings for HealthKit", "main": "lib/commonjs/index", "module": "lib/module/index", From ea7899b5eff18d1cc2c9a2cbeae62bc023dab6a5 Mon Sep 17 00:00:00 2001 From: Robert Herber Date: Sat, 28 Oct 2023 02:59:16 +0200 Subject: [PATCH 7/9] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bf2f3ff..e0064e6 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Test Status](https://github.com/Kingstinct/react-native-healthkit/actions/workflows/test.yml/badge.svg)](https://github.com/Kingstinct/react-native-healthkit/actions/workflows/test.yml) [![Latest version on NPM](https://img.shields.io/npm/v/@kingstinct/react-native-healthkit)](https://www.npmjs.com/package/@kingstinct/react-native-healthkit) [![Downloads on NPM](https://img.shields.io/npm/dt/@kingstinct/react-native-healthkit)](https://www.npmjs.com/package/@kingstinct/react-native-healthkit) -[![Discord](https://dcbadge.vercel.app/api/server/EHScS93v?style=flat)](https://discord.gg/EHScS93v) +[![Discord](https://dcbadge.vercel.app/api/server/65qtrH2t?style=flat)](https://discord.gg/65qtrH2t) React Native bindings for HealthKit with full TypeScript and Promise support covering about any kind of data. Keeping TypeScript mappings as close as possible to HealthKit - both in regards to naming and serialization. This will make it easier to keep this library up-to-date with HealthKit as well as browsing [the official documentation](https://developer.apple.com/documentation/healthkit) (and if something - metadata properties for example - is not typed it will still be accessible). From bb9ffa1ab20604d1ba16441da29529ba2264cb14 Mon Sep 17 00:00:00 2001 From: Robert Herber Date: Sat, 28 Oct 2023 03:06:56 +0200 Subject: [PATCH 8/9] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e0064e6..7037fd2 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Test Status](https://github.com/Kingstinct/react-native-healthkit/actions/workflows/test.yml/badge.svg)](https://github.com/Kingstinct/react-native-healthkit/actions/workflows/test.yml) [![Latest version on NPM](https://img.shields.io/npm/v/@kingstinct/react-native-healthkit)](https://www.npmjs.com/package/@kingstinct/react-native-healthkit) [![Downloads on NPM](https://img.shields.io/npm/dt/@kingstinct/react-native-healthkit)](https://www.npmjs.com/package/@kingstinct/react-native-healthkit) -[![Discord](https://dcbadge.vercel.app/api/server/65qtrH2t?style=flat)](https://discord.gg/65qtrH2t) +[![Discord](https://dcbadge.vercel.app/api/server/hrgnETpsJA?style=flat)](https://discord.gg/hrgnETpsJA) React Native bindings for HealthKit with full TypeScript and Promise support covering about any kind of data. Keeping TypeScript mappings as close as possible to HealthKit - both in regards to naming and serialization. This will make it easier to keep this library up-to-date with HealthKit as well as browsing [the official documentation](https://developer.apple.com/documentation/healthkit) (and if something - metadata properties for example - is not typed it will still be accessible). From 3fd3652cba6acfddae2814b2255713993ec91e8e Mon Sep 17 00:00:00 2001 From: Robert Herber Date: Sat, 28 Oct 2023 03:18:56 +0200 Subject: [PATCH 9/9] Update package.json --- package.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index a860e9b..bc56abb 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,15 @@ "react-hooks" ], "repository": "https://github.com/kingstinct/react-native-healthkit", - "author": "Robert Herber (https://github.com/robertherber)", + "funding": [ + "https://github.com/sponsors/kingstinct", + "https://github.com/sponsors/robertherber" + ], + "author": { + "name": "Robert Herber", + "email": "robert@kingstinct.com", + "url": "https://github.com/robertherber" + }, "license": "MIT", "bugs": { "url": "https://github.com/kingstinct/react-native-healthkit/issues"