Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more workout details to queryWorkoutSamples #72

Merged
merged 12 commits into from
Sep 1, 2023
68 changes: 66 additions & 2 deletions ios/ReactNativeHealthkit.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import HealthKit
import CoreLocation

#if canImport(WorkoutKit)
import WorkoutKit
robertherber marked this conversation as resolved.
Show resolved Hide resolved
#endif

@objc(ReactNativeHealthkit)
@available(iOS 10.0, *)
class ReactNativeHealthkit: RCTEventEmitter {
Expand Down Expand Up @@ -619,6 +623,7 @@ class ReactNativeHealthkit: RCTEventEmitter {

@objc(queryWorkoutSamples:distanceUnitString:from:to:limit:ascending:resolve:reject:)
func queryWorkoutSamples(energyUnitString: String, distanceUnitString: String, from: Date, to: Date, limit: Int, ascending: Bool, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {

guard let store = _store else {
return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
}
Expand Down Expand Up @@ -658,11 +663,70 @@ class ReactNativeHealthkit: RCTEventEmitter {
"metadata": serializeMetadata(metadata: workout.metadata),
"sourceRevision": serializeSourceRevision(_sourceRevision: workout.sourceRevision) as Any
]


//this is used for our laps functionality to get markers
//https://developer.apple.com/documentation/healthkit/hkworkoutevent
var eventArray: [[String: Any]] = []
if let events = workout.workoutEvents {
for event in events {
let eventStartDate = self._dateFormatter.string(from: event.dateInterval.start)
let eventEndDate = self._dateFormatter.string(from: event.dateInterval.end)
let eventDict: [String: Any] = [
"type": event.type.rawValue, //https://developer.apple.com/documentation/healthkit/hkworkouteventtype
"startDate": eventStartDate,
"endDate": eventEndDate
]
eventArray.append(eventDict)
}
}
dict["events"] = eventArray

//also used for our laps functionality to get activities for custom workouts defined by the user
//https://developer.apple.com/documentation/healthkit/hkworkout/1615340-init
//it seems this might be depricated in the latest beta so this might need updating!
var activitiesArray: [[String: Any]] = []
if #available(iOS 16.0, *) {
let activities: [HKWorkoutActivity] = workout.workoutActivities

if !activities.isEmpty{
for activity in activities {
var activityStartDate = ""
var activityEndDate = ""
if let start = activity.startDate as Date? {
activityStartDate = self._dateFormatter.string(from: activity.startDate)
}
if let end = activity.endDate as Date? {
activityEndDate = self._dateFormatter.string(from: activity.endDate!)
}
let activityDict: [String: Any] = [
"startDate": activityStartDate,
robertherber marked this conversation as resolved.
Show resolved Hide resolved
"endDate": activityEndDate,
"uuid": activity.uuid.uuidString,
"duration": activity.duration
]
activitiesArray.append(activityDict)
}
}
}
dict["activities"] = activitiesArray

if #available(iOS 11, *) {
dict.setValue(serializeQuantity(unit: HKUnit.count(), quantity: workout.totalFlightsClimbed), forKey: "totalFlightsClimbed")
}


#if canImport(WorkoutKit)
if #available(iOS 17.0, *) {
do {
let workoutplan = try await workout.workoutPlan
if let workoutplanId = workoutplan?.id {
dict["workoutPlanId"] = workoutplanId.uuidString
}
} catch {
// handle error
}
}
#endif

arr.add(dict)
}
}
Expand Down
89 changes: 77 additions & 12 deletions src/native-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,29 @@ import type { EmitterSubscription, NativeModule } from 'react-native'
*/
export const HKWorkoutTypeIdentifier = 'HKWorkoutTypeIdentifier' as const

/**
* Represents a type that identifies activity summary objects.
* @see {@link https://developer.apple.com/documentation/healthkit/hkactivitysummarytype Apple Docs HKActivitySummaryType}
*/
export const HKActivitySummaryType = 'HKActivitySummaryType' as const

/**
* Represents an audiogram type identifier.
* @see {@link https://developer.apple.com/documentation/healthkit/HKAudiogramSampleType Apple Docs HKAudiogramSampleType}
*/
export const HKAudiogramTypeIdentifier = 'HKAudiogramTypeIdentifier' as const
export const HKAudiogramTypeIdentifier = 'HKAudiogramSampleType' as const

/**
* Represents a workout route type identifier.
* @see {@link https://developer.apple.com/documentation/healthkit/hkworkoutroutetypeidentifier Apple Docs HKWorkoutRouteTypeIdentifier}
*/
export const HKWorkoutRouteTypeIdentifier = 'HKWorkoutRouteTypeIdentifier' as const
export const HKDataTypeIdentifierHeartbeatSeries = 'HKDataTypeIdentifierHeartbeatSeries' as const

/**
* Represents a series sample containing heartbeat data..
* @see {@link https://developer.apple.com/documentation/healthkit/HKDataTypeIdentifierHeartbeatSeries Apple Docs HKDataTypeIdentifierHeartbeatSeries}
*/
export declare const HKDataTypeIdentifierHeartbeatSeries: 'HKDataTypeIdentifierHeartbeatSeries'

/**
* Represents a quantity type identifier.
Expand Down Expand Up @@ -670,6 +682,41 @@ export enum HKQuantityTypeIdentifier {
* @since iOS 16
*/
heartRateRecoveryOneMinute = 'HKQuantityTypeIdentifierHeartRateRecoveryOneMinute',

/**
* Running Ground Contact Time
* @see {@link https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifierrunninggroundcontacttime Apple Docs HKQuantityTypeIdentifierRunningGroundContactTime}
* @since iOS 16
*/
runningGroundContactTime = 'HKQuantityTypeIdentifierRunningGroundContactTime',

/**
* Running Stride Length
* @see {@link https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifierrunningstridelength Apple Docs HKQuantityTypeIdentifierRunningStrideLength}
* @since iOS 16
*/
runningStrideLength = 'HKQuantityTypeIdentifierRunningStrideLength',

/**
* Running Power
* @see {@link https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifierrunningpower Apple Docs HKQuantityTypeIdentifierRunningPower}
* @since iOS 16
*/
runningPower = 'HKQuantityTypeIdentifierRunningPower',

/**
* Running Vertical Oscillation
* @see {@link https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifierrunningverticaloscillation Apple Docs HKQuantityTypeIdentifierRunningVerticalOscillation}
* @since iOS 16
*/
runningVerticalOscillation = 'HKQuantityTypeIdentifierRunningVerticalOscillation',

/**
* Running Speed
* @see {@link https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifierrunningspeed Apple Docs HKQuantityTypeIdentifierRunningSpeed}
* @since iOS 16
*/
runningSpeed = 'HKQuantityTypeIdentifierRunningSpeed',
}

export type TypeToUnitMapping = {
Expand Down Expand Up @@ -768,16 +815,7 @@ export enum HKCategoryTypeIdentifier {
}

export type HKSampleTypeIdentifier =
| HKCategoryTypeIdentifier
| HKCorrelationTypeIdentifier
| HKQuantityTypeIdentifier
| typeof HKAudiogramTypeIdentifier
| typeof HKDataTypeIdentifierHeartbeatSeries
| typeof HKWorkoutRouteTypeIdentifier
| typeof HKWorkoutTypeIdentifier
| `${HKCategoryTypeIdentifier}`
| `${HKCorrelationTypeIdentifier}`
| `${HKQuantityTypeIdentifier}`;
HKCategoryTypeIdentifier | HKCorrelationTypeIdentifier | HKQuantityTypeIdentifier | typeof HKActivitySummaryType | typeof HKAudiogramTypeIdentifier | typeof HKDataTypeIdentifierHeartbeatSeries | typeof HKWorkoutRouteTypeIdentifier | typeof HKWorkoutTypeIdentifier | `${HKCategoryTypeIdentifier}` | `${HKCorrelationTypeIdentifier}` | `${HKQuantityTypeIdentifier}`;

export type HealthkitReadAuthorization =
| HKCharacteristicTypeIdentifier
Expand Down Expand Up @@ -1673,6 +1711,30 @@ HKCategorySampleRaw<TCategory>,
'device' | 'endDate' | 'startDate' | 'uuid'
>;

export interface HKWorkoutEvent {
readonly type: HKWorkoutEventType,
readonly startDate: string,
readonly endDate: string,
}

export enum HKWorkoutEventType {
pause = 1,
resume = 2,
lap = 3,
marker = 4,
motionPaused = 5,
motionResumed = 6,
segment = 7,
pauseOrResumeRequest = 8,
}

export interface HKWorkoutActivity {
readonly startDate: string,
readonly endDate: string,
readonly uuid: string,
readonly duration: number,
}

export type HKWorkoutRaw<
TEnergy extends EnergyUnit,
TDistance extends LengthUnit
Expand All @@ -1695,6 +1757,9 @@ export type HKWorkoutRaw<
readonly endDate: string;
readonly metadata?: HKWorkoutMetadata;
readonly sourceRevision?: HKSourceRevision;
readonly events?: readonly HKWorkoutEvent[];
readonly activities?: readonly HKWorkoutActivity[];
readonly workoutPlanId?: string;
};

// Straight mapping to https://developer.apple.com/documentation/healthkit/hkcharacteristictypeidentifier
Expand Down
Loading