This commit is contained in:
Trey t
2023-06-24 00:01:32 -05:00
parent 36400d1f79
commit 01915752b6
6 changed files with 120 additions and 46 deletions

View File

@@ -8,8 +8,9 @@
import Foundation
import WatchConnectivity
enum WatchActions: String, Codable {
enum WatchActions: Codable {
case nextExercise
case workoutComplete(Data)
}
class BridgeModule: NSObject, ObservableObject {
@@ -26,11 +27,17 @@ class BridgeModule: NSObject, ObservableObject {
var currentExerciseIdx: Int = -1
var workoutStartDate: Date?
// workoutEndDate ties into WatchPackageModel.workoutEndDate which
// tells the watch app to stop the workout
var workoutEndDate: Date?
@Published var currentWorkoutRunTimeInSeconds: Int = -1
private var currentWorkoutRunTimer: Timer?
@Published var isInWorkout = false
var completedWorkoutFromWatch: (() -> Void)?
var totalCaloire: Float?
var heartRates: [Int]?
func start(workout: Workout, atExerciseIndex: Int = 0) {
self.currentWorkout = workout
@@ -64,15 +71,14 @@ class BridgeModule: NSObject, ObservableObject {
currentExercise = nil
currentWorkout = nil
if isInWorkout {
let watchModel = WatchPackageModel(currentExerciseName: currentExercise?.exercise.name ?? "-", currentTimeLeft: timeLeft, workoutStartDate: workoutStartDate ?? Date(), workoutEndDate: Date())
let data = try! JSONEncoder().encode(watchModel)
send(data)
}
isInWorkout = false
workoutStartDate = nil
workoutEndDate = nil
let watchModel = WatchPackageModel(currentExerciseName: "", currentTimeLeft: -100, workoutStartDate: Date())
let data = try! JSONEncoder().encode(watchModel)
send(data)
}
private func startWorkoutTimer() {
@@ -140,11 +146,22 @@ class BridgeModule: NSObject, ObservableObject {
}
extension BridgeModule: WCSessionDelegate {
func sendWorkoutCompleteToWatch() {
let watchModel = WatchPackageModel(currentExerciseName: currentExercise?.exercise.name ?? "-", currentTimeLeft: timeLeft, workoutStartDate: workoutStartDate ?? Date(), workoutEndDate: Date())
let data = try! JSONEncoder().encode(watchModel)
send(data)
}
func session(_ session: WCSession, didReceiveMessageData messageData: Data) {
if let model = try? JSONDecoder().decode(WatchActions.self, from: messageData) {
switch model {
case .nextExercise:
nextExercise()
case .workoutComplete(let data):
let model = try! JSONDecoder().decode(WatchFinishWorkoutModel.self, from: data)
totalCaloire = Float(model.totalBurnedEnergery)
heartRates = model.allHeartRates
completedWorkoutFromWatch?()
}
}
}

View File

@@ -1,9 +1,12 @@
completed workout view
add notes and slider for difficulty
-completed workout view
- add notes and slider for difficulty
-apple watch
account view
workout history view
apple watch
calorie upload
edit weights on workouts
video view on iphone during workout
edit weights on workouts

View File

@@ -19,37 +19,18 @@ struct CompletedWorkoutView: View {
var body: some View {
VStack {
Text(workout.name)
.frame(maxWidth: .infinity, alignment: .leading)
.font(.title3)
.padding(.top
)
if let desc = workout.description {
Text(desc)
.frame(maxWidth: .infinity, alignment: .leading)
.font(.body)
.padding(.top)
}
topViews()
Divider()
calsBurned()
Text("how hard was this shit")
HStack {
Text("easy")
Spacer()
Text("Death")
}
Slider(value: $difficulty, in: 0...5, step: 1)
heartRates()
rateWorkout()
Divider()
TextField("Notes", text: $notes)
// Divider()
Spacer()
Button("Upload", action: {
@@ -66,6 +47,57 @@ struct CompletedWorkoutView: View {
.padding([.leading, .trailing])
}
func topViews() -> some View {
VStack {
Text(workout.name)
.frame(maxWidth: .infinity, alignment: .leading)
.font(.title3)
.padding(.top
)
if let desc = workout.description {
Text(desc)
.frame(maxWidth: .infinity, alignment: .leading)
.font(.body)
.padding(.top)
}
}
}
func calsBurned() -> some View {
VStack {
Divider()
Text("calroies burned")
Text("\(postData["total_calories"] as! Float)")
}
}
func rateWorkout() -> some View {
VStack {
Divider()
Text("how hard was this shit")
HStack {
Text("easy")
Spacer()
Text("Death")
}
Slider(value: $difficulty, in: 0...5, step: 1)
}
}
func heartRates() -> some View {
VStack {
Divider()
if let heartRates = postData["heart_rates"] as? [Int] {
let avg = heartRates.reduce(0, +)/heartRates.count
Text("Avg heart rate: \(avg)")
}
}
}
func upload(postBody: [String: Any]) {
var _postBody = postBody
_postBody["difficulty"] = difficulty

View File

@@ -34,10 +34,7 @@ struct WorkoutDetailView: View {
ExerciseListView(workout: workout)
ActionsView(completedWorkout: {
bridgeModule.workoutEndDate = Date()
if let workoutData = createWorkoutData() {
presentedSheet = .completedWorkout(workoutData)
bridgeModule.resetCurrentWorkout()
}
bridgeModule.sendWorkoutCompleteToWatch()
}, workout: workout)
.frame(height: 44)
@@ -55,6 +52,14 @@ struct WorkoutDetailView: View {
.interactiveDismissDisabled()
}
}
.onAppear{
bridgeModule.completedWorkoutFromWatch = {
if let workoutData = createWorkoutData() {
presentedSheet = .completedWorkout(workoutData)
bridgeModule.resetCurrentWorkout()
}
}
}
}
func createWorkoutData() -> [String:Any]? {
@@ -68,7 +73,9 @@ struct WorkoutDetailView: View {
"workout_start_time": startTime,
"workout_end_time": endTime,
"workout": workoutid,
"total_time": bridgeModule.currentWorkoutRunTimeInSeconds
"total_time": bridgeModule.currentWorkoutRunTimeInSeconds,
"total_calories": bridgeModule.totalCaloire ?? -1,
"heart_rates": bridgeModule.heartRates ?? [Int]()
] as [String : Any]
return postBody

View File

@@ -13,3 +13,8 @@ struct WatchPackageModel: Codable {
var workoutStartDate: Date
var workoutEndDate: Date?
}
struct WatchFinishWorkoutModel: Codable {
var totalBurnedEnergery: Double
var allHeartRates: [Int]
}

View File

@@ -16,12 +16,9 @@ class WatchMainViewModel: NSObject, ObservableObject {
@Published var heartValue: Int?
let healthStore = HKHealthStore()
var hkWorkoutSession: HKWorkoutSession? {
didSet {
print("here")
}
}
var hkWorkoutSession: HKWorkoutSession?
var hkBuilder: HKLiveWorkoutBuilder?
var heartRates = [Int]()
override init() {
session = WCSession.default
@@ -71,6 +68,10 @@ extension WatchMainViewModel: WCSessionDelegate {
func session(_ session: WCSession, didReceiveMessageData messageData: Data) {
if let model = try? JSONDecoder().decode(WatchPackageModel.self, from: messageData) {
DispatchQueue.main.async {
if model.currentTimeLeft == -100 {
self.watchPackageModel = nil
return
}
if self.watchPackageModel?.workoutEndDate != nil {
self.watchPackageModel = nil
self.stopWorkout()
@@ -157,6 +158,14 @@ extension WatchMainViewModel: HKWorkoutSessionDelegate, HKLiveWorkoutBuilderDele
DispatchQueue.main.async() {
self.hkWorkoutSession = nil
self.hkBuilder = nil
let totalEnergy = workout?.totalEnergyBurned?.doubleValue(for: .kilocalorie()) ?? -1
let watchFinishWorkoutModel = WatchFinishWorkoutModel(totalBurnedEnergery: totalEnergy, allHeartRates: self.heartRates)
let data = try! JSONEncoder().encode(watchFinishWorkoutModel)
let watchAction = WatchActions.workoutComplete(data)
let watchActionData = try! JSONEncoder().encode(watchAction)
self.send(watchActionData)
self.heartRates.removeAll()
}
}
}
@@ -182,6 +191,7 @@ extension WatchMainViewModel: HKWorkoutSessionDelegate, HKLiveWorkoutBuilderDele
let heartRateUnit = HKUnit.count().unitDivided(by: HKUnit.minute())
let value = statistics!.mostRecentQuantity()?.doubleValue(for: heartRateUnit)
self.heartValue = Int(Double(round(1 * value!) / 1))
self.heartRates.append(Int(Double(round(1 * value!) / 1)))
print("[workoutBuilder] Heart Rate: \(String(describing: self.heartValue))")
}
default: