diff --git a/Werkout_ios.xcodeproj/project.pbxproj b/Werkout_ios.xcodeproj/project.pbxproj index d6d673b..2288798 100644 --- a/Werkout_ios.xcodeproj/project.pbxproj +++ b/Werkout_ios.xcodeproj/project.pbxproj @@ -23,6 +23,8 @@ 1C5190CC2A589D0000885849 /* CountdownView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C5190CB2A589D0000885849 /* CountdownView.swift */; }; 1C5190CE2A589D4100885849 /* AllWorkoutPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C5190CD2A589D4100885849 /* AllWorkoutPickerView.swift */; }; 1C5190D02A589D5F00885849 /* AllWorkoutsListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C5190CF2A589D5F00885849 /* AllWorkoutsListView.swift */; }; + 1C5190D22A59ACA400885849 /* WatchControlView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C5190D12A59ACA400885849 /* WatchControlView.swift */; }; + 1C5190D42A59AEDE00885849 /* MainWatchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C5190D32A59AEDE00885849 /* MainWatchView.swift */; }; 1C6BF28F2A56602B00450FD7 /* Keychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C6BF28E2A56602B00450FD7 /* Keychain.swift */; }; 1CAF4D8A2A5132F900B00E50 /* PlannedWorkout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CAF4D892A5132F900B00E50 /* PlannedWorkout.swift */; }; 1CAF4D8C2A51339200B00E50 /* PlannedWorkouts.json in Resources */ = {isa = PBXBuildFile; fileRef = 1CAF4D8B2A51339200B00E50 /* PlannedWorkouts.json */; }; @@ -128,6 +130,8 @@ 1C5190CB2A589D0000885849 /* CountdownView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CountdownView.swift; sourceTree = ""; }; 1C5190CD2A589D4100885849 /* AllWorkoutPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AllWorkoutPickerView.swift; sourceTree = ""; }; 1C5190CF2A589D5F00885849 /* AllWorkoutsListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AllWorkoutsListView.swift; sourceTree = ""; }; + 1C5190D12A59ACA400885849 /* WatchControlView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchControlView.swift; sourceTree = ""; }; + 1C5190D32A59AEDE00885849 /* MainWatchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainWatchView.swift; sourceTree = ""; }; 1C6BF28E2A56602B00450FD7 /* Keychain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keychain.swift; sourceTree = ""; }; 1C6D0A3C2A4BEC9700D98B06 /* AVKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVKit.framework; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS9.4.sdk/System/Library/Frameworks/AVKit.framework; sourceTree = DEVELOPER_DIR; }; 1C6D0A3D2A4BEC9700D98B06 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS9.4.sdk/System/Library/Frameworks/AVFoundation.framework; sourceTree = DEVELOPER_DIR; }; @@ -307,6 +311,7 @@ children = ( 1CF65A3B2A3972CE0042FFBD /* ExternalWorkoutDetailView.swift */, 1CF65A2C2A3972840042FFBD /* MainView.swift */, + 1C5190C12A57CA5F00885849 /* OvalTextFieldStyle.swift */, 1CAF4D942A52180600B00E50 /* PlanWorkoutView.swift */, 1C31C8862A55B2CC00350540 /* PlayerUIView.swift */, 1C485C8B2A49D65600A6F896 /* WorkoutHistoryView.swift */, @@ -317,7 +322,6 @@ 1CF65A6C2A3F60100042FFBD /* CreateWorkout */, 1C485C882A492BAA00A6F896 /* Login */, 1CF65A882A44B7290042FFBD /* WorkoutDetail */, - 1C5190C12A57CA5F00885849 /* OvalTextFieldStyle.swift */, ); path = Views; sourceTree = ""; @@ -400,11 +404,13 @@ 1CF65A942A452D270042FFBD /* Werkout_watch Watch App */ = { isa = PBXGroup; children = ( - 1CF65AB82A45387B0042FFBD /* Werkout-watch-Watch-App-Info.plist */, 1CF65AB72A4534DC0042FFBD /* Werkout_watch Watch App.entitlements */, - 1CF65A952A452D270042FFBD /* Werkout_watchApp.swift */, + 1CF65AB82A45387B0042FFBD /* Werkout-watch-Watch-App-Info.plist */, 1CF65A972A452D270042FFBD /* ContentView.swift */, + 1C5190D32A59AEDE00885849 /* MainWatchView.swift */, + 1C5190D12A59ACA400885849 /* WatchControlView.swift */, 1CF65AB52A4532940042FFBD /* WatchMainViewModel.swift */, + 1CF65A952A452D270042FFBD /* Werkout_watchApp.swift */, 1CF65A992A452D290042FFBD /* Assets.xcassets */, 1CF65A9B2A452D290042FFBD /* Preview Content */, ); @@ -605,6 +611,8 @@ 1CF65AAB2A452DAC0042FFBD /* PreviewData.swift in Sources */, 1CF65AA52A452D9C0042FFBD /* CompletedWorkout.swift in Sources */, 1CF65AA82A452D9C0042FFBD /* Exercise.swift in Sources */, + 1C5190D22A59ACA400885849 /* WatchControlView.swift in Sources */, + 1C5190D42A59AEDE00885849 /* MainWatchView.swift in Sources */, 1CF65AB42A4530200042FFBD /* WatchPackageModel.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Werkout_ios/BridgeModule.swift b/Werkout_ios/BridgeModule.swift index 1c66968..149ac55 100644 --- a/Werkout_ios/BridgeModule.swift +++ b/Werkout_ios/BridgeModule.swift @@ -12,6 +12,9 @@ import HealthKit enum WatchActions: Codable { case nextExercise + case restartExercise + case previousExercise + case stopWorkout case workoutComplete(Data) } @@ -169,6 +172,30 @@ class BridgeModule: NSObject, ObservableObject { } } + func previousExercise() { + currentExerciseIdx -= 1 + if currentExerciseIdx < 0 { + currentExerciseIdx = 0 + } + if let currentWorkout = currentWorkout { + if currentExerciseIdx < currentWorkout.exercises.count { + let nextExercise = currentWorkout.exercises[currentExerciseIdx] + updateCurrent(exercise: nextExercise) + } else { + completeWorkout() + } + } + } + + func restartExercise() { + if let currentWorkout = currentWorkout { + if currentExerciseIdx < currentWorkout.exercises.count { + let nextExercise = currentWorkout.exercises[currentExerciseIdx] + updateCurrent(exercise: nextExercise) + } + } + } + @objc func addOneToWorkoutRunTime() { currentWorkoutRunTimeInSeconds += 1 } @@ -265,6 +292,12 @@ extension BridgeModule: WCSessionDelegate { totalCaloire = Float(model.totalBurnedEnergery) heartRates = model.allHeartRates completedWorkout?() + case .restartExercise: + restartExercise() + case .previousExercise: + previousExercise() + case .stopWorkout: + completeWorkout() } } } diff --git a/Werkout_ios/Views/AllWorkouts/AllWorkoutsListView.swift b/Werkout_ios/Views/AllWorkouts/AllWorkoutsListView.swift index 363a896..31d9313 100644 --- a/Werkout_ios/Views/AllWorkouts/AllWorkoutsListView.swift +++ b/Werkout_ios/Views/AllWorkouts/AllWorkoutsListView.swift @@ -78,11 +78,6 @@ struct AllWorkoutsListView: View { TextField("Filter" ,text: $searchString) .padding() .textFieldStyle(OvalTextFieldStyle()) - // TextField("Filter", text: $searchString) - // .padding() - // .overlay(RoundedRectangle(cornerRadius: 10.0).strokeBorder(Color(uiColor: .darkGray), style: StrokeStyle(lineWidth: 1.0))) - // .padding() - // .background(Color(uiColor: .systemGroupedBackground)) } } } diff --git a/Werkout_watch Watch App/ContentView.swift b/Werkout_watch Watch App/ContentView.swift index e22b9d2..a3db4be 100644 --- a/Werkout_watch Watch App/ContentView.swift +++ b/Werkout_watch Watch App/ContentView.swift @@ -6,60 +6,17 @@ // import SwiftUI +import WatchKit struct ContentView: View { - let exercise = PreviewData.parseEquipment()[2] - @StateObject var vm = WatchMainViewModel() - var body: some View { - VStack { - HStack { - if let model = vm.watchPackageModel { - Text(model.currentExerciseName) - .font(Font.system(size: 55)) - .scaledToFit() - .minimumScaleFactor(0.01) - .lineLimit(1) - .foregroundColor(.white) - Divider() - Text("\(model.currentTimeLeft )") - .font(Font.system(size: 55)) - .scaledToFit() - .minimumScaleFactor(0.01) - .lineLimit(1) - .foregroundColor(.white) - } - } - - HStack { - if let heartValue = vm.heartValue { - VStack { - Image(systemName: "heart.fill") - .font(Font.system(size: 22)) - .scaledToFit() - .minimumScaleFactor(0.01) - .lineLimit(1) - .foregroundColor(.red) - Text("\(heartValue)") - .font(Font.system(size: 55)) - .scaledToFit() - .minimumScaleFactor(0.01) - .lineLimit(1) - .foregroundColor(.red) - } - .frame(maxWidth: .infinity, maxHeight: .infinity) - } - Button(action: { - vm.nextExercise() - }, label: { - Image(systemName: "arrow.forward") - .font(.title) - .frame(maxWidth: .infinity, maxHeight: .infinity) - }) - .buttonStyle(BorderedButtonStyle(tint: .blue)) - } + TabView { + MainWatchView() + WatchControlView() + NowPlayingView() } .padding() + .tabViewStyle(PageTabViewStyle()) } } diff --git a/Werkout_watch Watch App/MainWatchView.swift b/Werkout_watch Watch App/MainWatchView.swift new file mode 100644 index 0000000..a88961b --- /dev/null +++ b/Werkout_watch Watch App/MainWatchView.swift @@ -0,0 +1,68 @@ +// +// MainView.swift +// Werkout_watch Watch App +// +// Created by Trey Tartt on 7/8/23. +// + +import SwiftUI + +struct MainWatchView: View { + @StateObject var vm = WatchMainViewModel() + + var body: some View { + VStack { + HStack { + if let model = vm.watchPackageModel { + Text(model.currentExerciseName) + .font(Font.system(size: 55)) + .scaledToFit() + .minimumScaleFactor(0.01) + .lineLimit(1) + .foregroundColor(.white) + Divider() + Text("\(model.currentTimeLeft )") + .font(Font.system(size: 55)) + .scaledToFit() + .minimumScaleFactor(0.01) + .lineLimit(1) + .foregroundColor(.white) + } + } + + HStack { + if let heartValue = vm.heartValue { + VStack { + Image(systemName: "heart.fill") + .font(Font.system(size: 22)) + .scaledToFit() + .minimumScaleFactor(0.01) + .lineLimit(1) + .foregroundColor(.red) + Text("\(heartValue)") + .font(Font.system(size: 55)) + .scaledToFit() + .minimumScaleFactor(0.01) + .lineLimit(1) + .foregroundColor(.red) + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + } + Button(action: { + vm.nextExercise() + }, label: { + Image(systemName: "arrow.forward") + .font(.title) + .frame(maxWidth: .infinity, maxHeight: .infinity) + }) + .buttonStyle(BorderedButtonStyle(tint: .green)) + } + } + } +} + +//struct MainView_Previews: PreviewProvider { +// static var previews: some View { +// MainView() +// } +//} diff --git a/Werkout_watch Watch App/WatchControlView.swift b/Werkout_watch Watch App/WatchControlView.swift new file mode 100644 index 0000000..e3a36db --- /dev/null +++ b/Werkout_watch Watch App/WatchControlView.swift @@ -0,0 +1,61 @@ +// +// WatchControlView.swift +// Werkout_watch Watch App +// +// Created by Trey Tartt on 7/8/23. +// + +import SwiftUI + +struct WatchControlView: View { + @StateObject var vm = WatchMainViewModel() + + var body: some View { + HStack { + VStack { + Button(action: { + vm.completeWorkout() + }, label: { + Image(systemName: "stop.circle") + .font(.title) + .frame(maxWidth: .infinity, maxHeight: .infinity) + }) + .buttonStyle(BorderedButtonStyle(tint: .red)) + + Button(action: { + vm.restartExercise() + }, label: { + Image(systemName: "arrow.counterclockwise.circle") + .font(.title) + .frame(maxWidth: .infinity, maxHeight: .infinity) + }) + .buttonStyle(BorderedButtonStyle(tint: .yellow)) + } + VStack { + Button(action: { + vm.previousExercise() + }, label: { + Image(systemName: "arrow.backward") + .font(.title) + .frame(maxWidth: .infinity, maxHeight: .infinity) + }) + .buttonStyle(BorderedButtonStyle(tint: .blue)) + + Button(action: { + vm.nextExercise() + }, label: { + Image(systemName: "arrow.forward") + .font(.title) + .frame(maxWidth: .infinity, maxHeight: .infinity) + }) + .buttonStyle(BorderedButtonStyle(tint: .green)) + } + } + } +} + +struct WatchControlView_Previews: PreviewProvider { + static var previews: some View { + WatchControlView(vm: WatchMainViewModel()) + } +} diff --git a/Werkout_watch Watch App/WatchMainViewModel.swift b/Werkout_watch Watch App/WatchMainViewModel.swift index 74c0803..1827ae6 100644 --- a/Werkout_watch Watch App/WatchMainViewModel.swift +++ b/Werkout_watch Watch App/WatchMainViewModel.swift @@ -62,6 +62,24 @@ class WatchMainViewModel: NSObject, ObservableObject { let data = try! JSONEncoder().encode(nextExerciseAction) send(data) } + + func restartExercise() { + let nextExerciseAction = WatchActions.restartExercise + let data = try! JSONEncoder().encode(nextExerciseAction) + send(data) + } + + func previousExercise() { + let nextExerciseAction = WatchActions.previousExercise + let data = try! JSONEncoder().encode(nextExerciseAction) + send(data) + } + + func completeWorkout() { + let nextExerciseAction = WatchActions.stopWorkout + let data = try! JSONEncoder().encode(nextExerciseAction) + send(data) + } } extension WatchMainViewModel: WCSessionDelegate {