d5915a9552
- Redesign the watch app into an active-workout runner: a root gate shows the in-progress workout's exercises or prompts to start one on iPhone, and each exercise runs as a horizontally-paged HIIT cycle (count-up work, count-down rest with final-three-second haptics + auto-advance, One More / Done on the last set). Replaces the old history list. - Add a configurable rest-between-sets duration in iPhone Settings (default 45s), synced to the watch over WatchConnectivity. - Launch the watch app into the session when a workout starts on the phone via HealthKit (startWatchApp); the watch runs an HKWorkoutSession for foreground runtime and ends it when the workout finishes. Adds the HealthKit entitlement + Health usage strings on both targets and WKBackgroundModes on the watch. Claude-Session: https://claude.ai/code/session_018gg69MaUetDNzWzBXisfMV
41 lines
1.5 KiB
Swift
41 lines
1.5 KiB
Swift
//
|
|
// WorkoutLauncher.swift
|
|
// Workouts
|
|
//
|
|
// Copyright 2025 Rouslan Zenetl. All Rights Reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import HealthKit
|
|
|
|
/// Launches the companion Watch app into a workout when a session starts on the phone.
|
|
///
|
|
/// An iPhone app can't foreground its Watch app on its own — the only sanctioned path
|
|
/// is HealthKit's `startWatchApp(toHandle:)`, which hands watchOS a workout
|
|
/// configuration and brings the Watch app up to run a matching `HKWorkoutSession`.
|
|
/// Calling it requires authorization to *share* workouts first.
|
|
@MainActor
|
|
final class WorkoutLauncher {
|
|
private let healthStore = HKHealthStore()
|
|
|
|
/// Strength/HIIT configuration handed to watchOS; the watch starts a session with
|
|
/// the same shape (see `WorkoutSessionManager`).
|
|
static func makeConfiguration() -> HKWorkoutConfiguration {
|
|
let configuration = HKWorkoutConfiguration()
|
|
configuration.activityType = .traditionalStrengthTraining
|
|
configuration.locationType = .indoor
|
|
return configuration
|
|
}
|
|
|
|
/// Ask watchOS to launch the Watch app into the workout. Best-effort: no-ops where
|
|
/// HealthKit is unavailable (e.g. iPad without it) and silently tolerates a missing
|
|
/// or unreachable paired watch.
|
|
func launchWatchWorkout() {
|
|
guard HKHealthStore.isHealthDataAvailable() else { return }
|
|
Task {
|
|
try? await healthStore.requestAuthorization(toShare: [.workoutType()], read: [])
|
|
try? await healthStore.startWatchApp(toHandle: Self.makeConfiguration())
|
|
}
|
|
}
|
|
}
|