From cee84d77767ff928a6e41585792c740ad40431e6 Mon Sep 17 00:00:00 2001 From: Trey t Date: Fri, 21 Jun 2024 14:34:23 -0500 Subject: [PATCH] misc watch stuff including taps, sounds, maybe working --- iphone/Werkout_ios/AudioEngine.swift | 26 +++++++++++-------- iphone/Werkout_ios/BridgeModule+Timer.swift | 6 ++--- iphone/Werkout_ios/BridgeModule+Watch.swift | 23 +++++++--------- .../BridgeModule+WorkoutActions.swift | 3 +-- iphone/Werkout_ios/WatchPackageModel.swift | 1 + iphone/Werkout_ios/subview/ActionsView.swift | 3 +++ .../WatchControlView.swift | 12 ++++++--- .../WatchMainViewModel+WorkoutActions.swift | 3 +++ .../WatchMainViewModel.swift | 20 +++++++++++--- 9 files changed, 61 insertions(+), 36 deletions(-) diff --git a/iphone/Werkout_ios/AudioEngine.swift b/iphone/Werkout_ios/AudioEngine.swift index dcfeefa..25eebf2 100644 --- a/iphone/Werkout_ios/AudioEngine.swift +++ b/iphone/Werkout_ios/AudioEngine.swift @@ -6,12 +6,16 @@ // import AVKit +import AVFoundation class AudioEngine { -// var audioPlayer: AVAudioPlayer? -// var avPlayer: AVPlayer? + static let shared = AudioEngine() + private init() { } - static func playRemoteAudio(fromURL url: URL) { + var audioPlayer: AVAudioPlayer? + var avPlayer: AVPlayer? + + func playRemoteAudio(fromURL url: URL) { #if os(iOS) let playerItem = AVPlayerItem(url: url) do { @@ -20,15 +24,15 @@ class AudioEngine { options: [.mixWithOthers]) try AVAudioSession.sharedInstance().setActive(true) - let avPlayer = AVPlayer(playerItem: playerItem) - avPlayer.play() + avPlayer = AVPlayer(playerItem: playerItem) + avPlayer?.play() } catch { print("ERROR") } #endif } - static func playBeep() { + func playBeep() { #if os(iOS) if let path = Bundle.main.path(forResource: "short_beep", ofType: "m4a") { do { @@ -37,8 +41,8 @@ class AudioEngine { options: [.mixWithOthers]) try AVAudioSession.sharedInstance().setActive(true) - let audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path)) - audioPlayer.play() + audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path)) + audioPlayer?.play() } catch { print("ERROR") } @@ -46,7 +50,7 @@ class AudioEngine { #endif } - static func playFinished() { + func playFinished() { #if os(iOS) if let path = Bundle.main.path(forResource: "long_beep", ofType: "m4a") { do { @@ -55,8 +59,8 @@ class AudioEngine { options: [.mixWithOthers]) try AVAudioSession.sharedInstance().setActive(true) - let audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path)) - audioPlayer.play() + audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path)) + audioPlayer?.play() } catch { print("ERROR") } diff --git a/iphone/Werkout_ios/BridgeModule+Timer.swift b/iphone/Werkout_ios/BridgeModule+Timer.swift index aad6435..2c910e6 100644 --- a/iphone/Werkout_ios/BridgeModule+Timer.swift +++ b/iphone/Werkout_ios/BridgeModule+Timer.swift @@ -42,11 +42,11 @@ extension BridgeModule { switch audioQueue.audioType { case .shortBeep: - AudioEngine.playBeep() + AudioEngine.shared.playBeep() case .finishBeep: - AudioEngine.playFinished() + AudioEngine.shared.playFinished() case .remoteURL(let url): - AudioEngine.playRemoteAudio(fromURL: url) + AudioEngine.shared.playRemoteAudio(fromURL: url) } } } diff --git a/iphone/Werkout_ios/BridgeModule+Watch.swift b/iphone/Werkout_ios/BridgeModule+Watch.swift index 6da7cf3..d0191fb 100644 --- a/iphone/Werkout_ios/BridgeModule+Watch.swift +++ b/iphone/Werkout_ios/BridgeModule+Watch.swift @@ -14,28 +14,22 @@ extension BridgeModule: WCSessionDelegate { func sendResetToWatch() { let watchModel = PhoneToWatchActions.reset let data = try! JSONEncoder().encode(watchModel) - - // user transferUserInfo b/c its guranteed to reach - // and end the workout - self.session.transferUserInfo(["package": data]) + send(data) +// self.session.transferUserInfo(["package": data]) } func sendStartWorkoutToWatch() { let model = PhoneToWatchActions.startWorkout let data = try! JSONEncoder().encode(model) - - // user transferUserInfo b/c its guranteed to reach - // and start the workout - self.session.transferUserInfo(["package": data]) + send(data) +// self.session.transferUserInfo(["package": data]) } func sendWorkoutCompleteToWatch() { let model = PhoneToWatchActions.endWorkout let data = try! JSONEncoder().encode(model) - - // user transferUserInfo b/c its guranteed to reach - // and end the workout - self.session.transferUserInfo(["package": data]) + send(data) +// self.session.transferUserInfo(["package": data]) } func sendCurrentExerciseToWatch() { @@ -43,6 +37,7 @@ extension BridgeModule: WCSessionDelegate { let duration = currentExercise.duration , duration > 0 { let watchModel = WatchPackageModel(currentExerciseName: currentExercise.exercise.name, + currentExerciseID: currentExercise.id ?? -1, currentTimeLeft: currentExerciseTimeLeft, workoutStartDate: workoutStartDate ?? Date()) let model = PhoneToWatchActions.inExercise(watchModel) @@ -55,7 +50,7 @@ extension BridgeModule: WCSessionDelegate { // if not a timer we need to set the watch display with number of reps // if timer it will set when timer updates - let watchModel = WatchPackageModel(currentExerciseName: currentExercise.exercise.name, currentTimeLeft: reps, workoutStartDate: self.workoutStartDate ?? Date()) + let watchModel = WatchPackageModel(currentExerciseName: currentExercise.exercise.name, currentExerciseID: currentExercise.id ?? -1, currentTimeLeft: reps, workoutStartDate: self.workoutStartDate ?? Date()) let model = PhoneToWatchActions.inExercise(watchModel) let data = try! JSONEncoder().encode(model) self.send(data) @@ -68,7 +63,7 @@ extension BridgeModule: WCSessionDelegate { switch model { case .nextExercise: nextExercise() - AudioEngine.playFinished() + AudioEngine.shared.playFinished() case .workoutComplete(let data): DispatchQueue.main.async { let model = try! JSONDecoder().decode(WatchFinishWorkoutModel.self, from: data) diff --git a/iphone/Werkout_ios/BridgeModule+WorkoutActions.swift b/iphone/Werkout_ios/BridgeModule+WorkoutActions.swift index 4db1fee..5a6cc37 100644 --- a/iphone/Werkout_ios/BridgeModule+WorkoutActions.swift +++ b/iphone/Werkout_ios/BridgeModule+WorkoutActions.swift @@ -77,8 +77,6 @@ extension BridgeModule { currentWorkoutRunTimer = nil isPaused = false - sendStartWorkoutToWatch() - if let superetExercise = currentExerciseInfo.currentExercise { updateCurrent(exercise: superetExercise) startWorkoutTimer() @@ -88,6 +86,7 @@ extension BridgeModule { if WCSession.isSupported() { session.delegate = self session.activate() + sendStartWorkoutToWatch() } } } diff --git a/iphone/Werkout_ios/WatchPackageModel.swift b/iphone/Werkout_ios/WatchPackageModel.swift index 68d76d3..f67f345 100644 --- a/iphone/Werkout_ios/WatchPackageModel.swift +++ b/iphone/Werkout_ios/WatchPackageModel.swift @@ -9,6 +9,7 @@ import Foundation struct WatchPackageModel: Codable { var currentExerciseName: String + var currentExerciseID: Int var currentTimeLeft: Int var workoutStartDate: Date var workoutEndDate: Date? diff --git a/iphone/Werkout_ios/subview/ActionsView.swift b/iphone/Werkout_ios/subview/ActionsView.swift index 9c9baef..938a18b 100644 --- a/iphone/Werkout_ios/subview/ActionsView.swift +++ b/iphone/Werkout_ios/subview/ActionsView.swift @@ -57,6 +57,7 @@ struct ActionsView: View { .foregroundColor(.white) } else { Button(action: { + AudioEngine.shared.playFinished() nextExercise() }, label: { Image(systemName: "arrow.forward") @@ -68,6 +69,7 @@ struct ActionsView: View { .foregroundColor(.white) Button(action: { + AudioEngine.shared.playFinished() bridgeModule.pauseWorkout() }, label: { bridgeModule.isPaused ? @@ -84,6 +86,7 @@ struct ActionsView: View { .foregroundColor(.white) Button(action: { + AudioEngine.shared.playFinished() completedWorkout?() }, label: { Image(systemName: "checkmark") diff --git a/iphone/Werkout_watch Watch App/WatchControlView.swift b/iphone/Werkout_watch Watch App/WatchControlView.swift index 6870351..4953e5b 100644 --- a/iphone/Werkout_watch Watch App/WatchControlView.swift +++ b/iphone/Werkout_watch Watch App/WatchControlView.swift @@ -44,9 +44,15 @@ struct WatchControlView: View { Button(action: { vm.pauseWorkout() }, label: { - Image(systemName: "pause") - .font(.title) - .frame(maxWidth: .infinity, maxHeight: .infinity) + if vm.isPaused { + Image(systemName: "play") + .font(.title) + .frame(maxWidth: .infinity, maxHeight: .infinity) + } else { + Image(systemName: "pause") + .font(.title) + .frame(maxWidth: .infinity, maxHeight: .infinity) + } }) .buttonStyle(BorderedButtonStyle(tint: .blue)) diff --git a/iphone/Werkout_watch Watch App/WatchMainViewModel+WorkoutActions.swift b/iphone/Werkout_watch Watch App/WatchMainViewModel+WorkoutActions.swift index c77b7f6..350cec9 100644 --- a/iphone/Werkout_watch Watch App/WatchMainViewModel+WorkoutActions.swift +++ b/iphone/Werkout_watch Watch App/WatchMainViewModel+WorkoutActions.swift @@ -51,6 +51,8 @@ extension WatchMainViewModel { } } isInWorkout = true + isPaused = false + WKInterfaceDevice.current().play(.start) } else { print("did not init workout") } @@ -69,6 +71,7 @@ extension WatchMainViewModel { self.hkBuilder = nil self.heartRates.removeAll() self.isInWorkout = false + self.isPaused = false guard let id = workout?.uuid else { return diff --git a/iphone/Werkout_watch Watch App/WatchMainViewModel.swift b/iphone/Werkout_watch Watch App/WatchMainViewModel.swift index f9a61af..3c29c5c 100644 --- a/iphone/Werkout_watch Watch App/WatchMainViewModel.swift +++ b/iphone/Werkout_watch Watch App/WatchMainViewModel.swift @@ -20,13 +20,14 @@ class WatchMainViewModel: NSObject, ObservableObject { @Published var heartValue: Int? static var defualtPackageModle: WatchPackageModel { - WatchPackageModel(currentExerciseName: "", currentTimeLeft: -1, workoutStartDate: Date()) + WatchPackageModel(currentExerciseName: "", currentExerciseID: -1, currentTimeLeft: -1, workoutStartDate: Date()) } let healthStore = HKHealthStore() var hkWorkoutSession: HKWorkoutSession? var hkBuilder: HKLiveWorkoutBuilder? var heartRates = [Int]() + @Published var isPaused = false override init() { session = WCSession.default @@ -56,38 +57,51 @@ class WatchMainViewModel: NSObject, ObservableObject { let nextExerciseAction = WatchActions.nextExercise let data = try! JSONEncoder().encode(nextExerciseAction) send(data) + WKInterfaceDevice.current().play(.start) } func restartExercise() { let nextExerciseAction = WatchActions.restartExercise let data = try! JSONEncoder().encode(nextExerciseAction) send(data) + WKInterfaceDevice.current().play(.start) } func previousExercise() { let nextExerciseAction = WatchActions.previousExercise let data = try! JSONEncoder().encode(nextExerciseAction) send(data) + WKInterfaceDevice.current().play(.start) } func completeWorkout() { let nextExerciseAction = WatchActions.stopWorkout let data = try! JSONEncoder().encode(nextExerciseAction) send(data) + WKInterfaceDevice.current().play(.start) } func pauseWorkout() { let nextExerciseAction = WatchActions.pauseWorkout let data = try! JSONEncoder().encode(nextExerciseAction) send(data) + isPaused = !isPaused + WKInterfaceDevice.current().play(.start) } func dataToAction(messageData: Data) { if let model = try? JSONDecoder().decode(PhoneToWatchActions.self, from: messageData) { DispatchQueue.main.async { switch model { - case .inExercise(let data): - self.watchPackageModel = data + case .inExercise(let newWatchPackageModel): + if !self.isInWorkout { + self.startWorkout() + } + if self.watchPackageModel.currentExerciseID != newWatchPackageModel.currentExerciseID { + self.isPaused = false + WKInterfaceDevice.current().play(.start) + } + self.watchPackageModel = newWatchPackageModel case .reset: self.isInWorkout = false self.watchPackageModel = WatchMainViewModel.defualtPackageModle