From 38be95ea76f710d40ed820ddd88ff00692146b9f Mon Sep 17 00:00:00 2001 From: Trey t Date: Mon, 3 Jul 2023 21:47:51 -0500 Subject: [PATCH] WIP --- Werkout_ios.xcodeproj/project.pbxproj | 10 ++++ Werkout_ios/BridgeModule.swift | 44 ++++++++++++++++-- .../Views/ExternalWorkoutDetailView.swift | 10 ++-- Werkout_ios/Werkout_ios.entitlements | 14 ++++-- Werkout_ios/long_beep.m4a | Bin 0 -> 5431 bytes Werkout_ios/short_beep.m4a | Bin 0 -> 3527 bytes .../Werkout_watch Watch App.entitlements | 2 + 7 files changed, 69 insertions(+), 11 deletions(-) create mode 100644 Werkout_ios/long_beep.m4a create mode 100644 Werkout_ios/short_beep.m4a diff --git a/Werkout_ios.xcodeproj/project.pbxproj b/Werkout_ios.xcodeproj/project.pbxproj index 88bf8f3..94d26e0 100644 --- a/Werkout_ios.xcodeproj/project.pbxproj +++ b/Werkout_ios.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 1C31C8842A53AE3E00350540 /* short_beep.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 1C31C8822A53AE3E00350540 /* short_beep.m4a */; }; + 1C31C8852A53AE3E00350540 /* long_beep.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 1C31C8832A53AE3E00350540 /* long_beep.m4a */; }; 1C485C832A489B9C00A6F896 /* CompletedWorkouts.json in Resources */ = {isa = PBXBuildFile; fileRef = 1C485C822A489B9C00A6F896 /* CompletedWorkouts.json */; }; 1C485C872A4915C400A6F896 /* CreateWorkoutItemPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C485C862A4915C400A6F896 /* CreateWorkoutItemPickerView.swift */; }; 1C485C8A2A492BB400A6F896 /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C485C892A492BB400A6F896 /* LoginView.swift */; }; @@ -102,6 +104,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 1C31C8822A53AE3E00350540 /* short_beep.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = short_beep.m4a; sourceTree = ""; }; + 1C31C8832A53AE3E00350540 /* long_beep.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = long_beep.m4a; sourceTree = ""; }; 1C485C822A489B9C00A6F896 /* CompletedWorkouts.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = CompletedWorkouts.json; sourceTree = ""; }; 1C485C862A4915C400A6F896 /* CreateWorkoutItemPickerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateWorkoutItemPickerView.swift; sourceTree = ""; }; 1C485C892A492BB400A6F896 /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = ""; }; @@ -223,6 +227,8 @@ 1CF65A242A3972840042FFBD /* Werkout_ios */ = { isa = PBXGroup; children = ( + 1C31C8832A53AE3E00350540 /* long_beep.m4a */, + 1C31C8822A53AE3E00350540 /* short_beep.m4a */, 1CF65A552A3AA6800042FFBD /* Werkout-ios-Info.plist */, 1CF65A482A39FB910042FFBD /* JSON */, 1CF65A252A3972840042FFBD /* Werkout_iosApp.swift */, @@ -473,6 +479,7 @@ files = ( 1CF65A5F2A3BF5A60042FFBD /* Equipment.json in Resources */, 1C485C832A489B9C00A6F896 /* CompletedWorkouts.json in Resources */, + 1C31C8852A53AE3E00350540 /* long_beep.m4a in Resources */, 1CF65A4A2A39FBB10042FFBD /* WorkoutOne.json in Resources */, 1CF65A652A3BF6BE0042FFBD /* AllWorkouts.json in Resources */, 1CF65A332A3972850042FFBD /* Preview Assets.xcassets in Resources */, @@ -483,6 +490,7 @@ 1CF65A542A3A9AF30042FFBD /* Straight_Leg_Sit_Up.mp4 in Resources */, 1CF65A2F2A3972850042FFBD /* Assets.xcassets in Resources */, 1CF65A872A4400E10042FFBD /* ToDo in Resources */, + 1C31C8842A53AE3E00350540 /* short_beep.m4a in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -770,6 +778,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; CODE_SIGN_ENTITLEMENTS = "Werkout_watch Watch App/Werkout_watch Watch App.entitlements"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; @@ -804,6 +813,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; CODE_SIGN_ENTITLEMENTS = "Werkout_watch Watch App/Werkout_watch Watch App.entitlements"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; diff --git a/Werkout_ios/BridgeModule.swift b/Werkout_ios/BridgeModule.swift index 3dc99ad..c6ffbb2 100644 --- a/Werkout_ios/BridgeModule.swift +++ b/Werkout_ios/BridgeModule.swift @@ -8,6 +8,7 @@ import Foundation import WatchConnectivity import AVFoundation +import HealthKit enum WatchActions: Codable { case nextExercise @@ -40,6 +41,8 @@ class BridgeModule: NSObject, ObservableObject { public private(set) var totalCaloire: Float? public private(set) var heartRates: [Int]? + var audioPlayer: AVAudioPlayer? + func start(workout: Workout) { self.currentWorkout = workout currentWorkoutRunTimeInSeconds = 0 @@ -52,11 +55,12 @@ class BridgeModule: NSObject, ObservableObject { startWorkoutTimer() workoutStartDate = Date() isInWorkout = true - + if WCSession.isSupported() { WCSession.default.delegate = self WCSession.default.activate() } + } func goToExerciseAt(index: Int) { @@ -178,13 +182,37 @@ class BridgeModule: NSObject, ObservableObject { func playBeep() { #if os(iOS) - AudioServicesPlaySystemSound(SystemSoundID(1052)) + if let path = Bundle.main.path(forResource: "short_beep", ofType: "m4a") { + do { + try AVAudioSession.sharedInstance().setCategory(.playback, + mode: .default, + options: [.mixWithOthers, .allowAirPlay]) + try AVAudioSession.sharedInstance().setActive(true) + + audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path)) + audioPlayer?.play() + } catch { + print("ERROR") + } + } #endif } func playFinished() { #if os(iOS) - AudioServicesPlaySystemSound(SystemSoundID(1070)) + if let path = Bundle.main.path(forResource: "long_beep", ofType: "m4a") { + do { + try AVAudioSession.sharedInstance().setCategory(.playback, + mode: .default, + options: [.mixWithOthers, .allowAirPlay]) + try AVAudioSession.sharedInstance().setActive(true) + + audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path)) + audioPlayer?.play() + } catch { + print("ERROR") + } + } #endif } } @@ -221,6 +249,16 @@ extension BridgeModule: WCSessionDelegate { print("inactive") case .activated: print("activated") +#if os(iOS) + let workoutConfiguration = HKWorkoutConfiguration() + workoutConfiguration.activityType = .traditionalStrengthTraining + workoutConfiguration.locationType = .indoor + if WCSession.isSupported(), WCSession.default.activationState == .activated, WCSession.default.isWatchAppInstalled { + HKHealthStore().startWatchApp(with: workoutConfiguration, completion: { (success, error) in + print(error.debugDescription) + }) + } +#endif } } #if os(iOS) diff --git a/Werkout_ios/Views/ExternalWorkoutDetailView.swift b/Werkout_ios/Views/ExternalWorkoutDetailView.swift index 2584772..78147e3 100644 --- a/Werkout_ios/Views/ExternalWorkoutDetailView.swift +++ b/Werkout_ios/Views/ExternalWorkoutDetailView.swift @@ -89,7 +89,7 @@ struct ExtExerciseList: View { HStack { if i == currentExerciseIdx { Image(systemName: "checkmark") - .font(Font.system(size: 75)) + .font(Font.system(size: 55)) .scaledToFit() .minimumScaleFactor(0.01) .lineLimit(1) @@ -97,7 +97,7 @@ struct ExtExerciseList: View { } Text(obj.exercise.name) - .font(Font.system(size: 75)) + .font(Font.system(size: 55)) .scaledToFit() .minimumScaleFactor(0.01) .lineLimit(1) @@ -151,14 +151,16 @@ struct ExtCountdownView: View { .scaledToFit() .minimumScaleFactor(0.01) .lineLimit(1) - .padding([.leading, .trailing]) + .padding(.leading) + .padding(.trailing, 100) } else if let reps = currenExercise.reps { Text("\(reps)") .font(Font.system(size: 75)) .scaledToFit() .minimumScaleFactor(0.01) .lineLimit(1) - .padding([.leading, .trailing]) + .padding(.leading) + .padding(.trailing, 100) } } .frame(height: metrics.size.height * 0.5) diff --git a/Werkout_ios/Werkout_ios.entitlements b/Werkout_ios/Werkout_ios.entitlements index f2ef3ae..73896b4 100644 --- a/Werkout_ios/Werkout_ios.entitlements +++ b/Werkout_ios/Werkout_ios.entitlements @@ -2,9 +2,15 @@ - com.apple.security.app-sandbox - - com.apple.security.files.user-selected.read-only - + com.apple.developer.healthkit + + com.apple.developer.healthkit.access + + com.apple.developer.healthkit.background-delivery + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + diff --git a/Werkout_ios/long_beep.m4a b/Werkout_ios/long_beep.m4a new file mode 100644 index 0000000000000000000000000000000000000000..8528558cffaaabd2138ff33e2cb77ace3debc8ea GIT binary patch literal 5431 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 com.apple.developer.healthkit.access + com.apple.developer.healthkit.background-delivery +