From 69c33f3c344c7d799a5c780ee6acfd4c2fb3449f Mon Sep 17 00:00:00 2001 From: Trey t Date: Tue, 20 Jun 2023 23:25:52 -0500 Subject: [PATCH] WIP --- Werkout_ios/APIModels/Exercise.swift | 2 +- Werkout_ios/BridgeModule.swift | 59 ++++++++++-- .../Views/ExternalWorkoutDetailView.swift | 85 ++++++++++++----- Werkout_ios/Views/WorkoutDetailView.swift | 91 +++++++++++-------- Werkout_ios/Werkout_iosApp.swift | 1 + 5 files changed, 169 insertions(+), 69 deletions(-) diff --git a/Werkout_ios/APIModels/Exercise.swift b/Werkout_ios/APIModels/Exercise.swift index 9853b07..8159dae 100644 --- a/Werkout_ios/APIModels/Exercise.swift +++ b/Werkout_ios/APIModels/Exercise.swift @@ -72,6 +72,6 @@ struct ExerciseExercise: Codable, Hashable { let df = DateFormatter() df.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" df.locale = Locale(identifier: "en_US_POSIX") - return df.date(from: self.createdAt ?? "") ?? Date() + return df.date(from: self.createdAt) ?? Date() } } diff --git a/Werkout_ios/BridgeModule.swift b/Werkout_ios/BridgeModule.swift index a43540e..b2c4e9e 100644 --- a/Werkout_ios/BridgeModule.swift +++ b/Werkout_ios/BridgeModule.swift @@ -14,10 +14,50 @@ class BridgeModule: ObservableObject { private var timer: Timer? @Published var timeLeft: Int = 0 - var timerCompleted: (() -> Void)? @Published var currentExercise: ExerciseElement? var currentWorkout: Workout? - @Published var currentExerciseIdx: Int = -1 + var currentExerciseIdx: Int = -1 + + @Published var currentWorkoutRunTimeInSeconds: Int = -1 + private var currentWorkoutRunTimer: Timer? + + func start(workout: Workout, atExerciseIndex: Int = 0) { + self.currentWorkout = workout + currentWorkoutRunTimeInSeconds = 0 + currentWorkoutRunTimer?.invalidate() + currentWorkoutRunTimer = nil + + currentExerciseIdx = 0 + let exercise = workout.exercises[currentExerciseIdx] + updateCurrent(exercise: exercise) + startWorkoutTimer() + } + + func completeWorkout() { + currentWorkoutRunTimeInSeconds = 0 + currentWorkoutRunTimer?.invalidate() + currentWorkoutRunTimer = nil + + currentWorkoutRunTimer?.invalidate() + currentWorkoutRunTimer = nil + + currentWorkoutRunTimeInSeconds = -1 + currentExerciseIdx = -1 + + currentExercise = nil + currentWorkout = nil + } + + private func startWorkoutTimer() { + currentWorkoutRunTimer?.invalidate() + currentWorkoutRunTimer = nil + currentWorkoutRunTimer = Timer.scheduledTimer(timeInterval: 1, + target: self, + selector: #selector(addOneToWorkoutRunTime), + userInfo: nil, + repeats: true) + currentWorkoutRunTimer?.fire() + } private func startTimerWith(duration: Int) { timer?.invalidate() @@ -37,17 +77,24 @@ class BridgeModule: ObservableObject { } else { timer?.invalidate() timer = nil - timerCompleted?() + + currentExerciseIdx += 1 + if let currentWorkout = currentWorkout { + if currentExerciseIdx < currentWorkout.exercises.count { + let nextExercise = currentWorkout.exercises[currentExerciseIdx] + updateCurrent(exercise: nextExercise) + } + } } } - func updateCurrent(workout: Workout) { - self.currentWorkout = workout + @objc func addOneToWorkoutRunTime() { + currentWorkoutRunTimeInSeconds += 1 } func updateCurrent(exercise: ExerciseElement) { self.currentExercise = exercise - + if let duration = exercise.duration { startTimerWith(duration: duration) } diff --git a/Werkout_ios/Views/ExternalWorkoutDetailView.swift b/Werkout_ios/Views/ExternalWorkoutDetailView.swift index 70645f7..eac78b6 100644 --- a/Werkout_ios/Views/ExternalWorkoutDetailView.swift +++ b/Werkout_ios/Views/ExternalWorkoutDetailView.swift @@ -12,28 +12,52 @@ struct ExternalWorkoutDetailView: View { @StateObject var bridgeModule = BridgeModule.shared var body: some View { - if let workout = bridgeModule.currentWorkout { - GeometryReader { metrics in - VStack { - Text(workout.name) - .font(Font.system(size: 100)) - .frame(width: metrics.size.width, height: metrics.size.height * 0.1) - - HStack { - if let currentExercise = bridgeModule.currentExercise { - VideoPlayerView(currentExercise: currentExercise.exercise) - .frame(width: metrics.size.width * 0.6, height: metrics.size.height * 0.7) + ZStack { + if let workout = bridgeModule.currentWorkout { + GeometryReader { metrics in + VStack { + HStack { + if let currentExercise = bridgeModule.currentExercise { + VideoPlayerView(currentExercise: currentExercise.exercise) + .frame(width: metrics.size.width * 0.6, height: metrics.size.height * 0.8) + } + + ExtExerciseList(workout: workout, + currentExerciseIdx: bridgeModule.currentExerciseIdx) + .frame(width: metrics.size.width * 0.4, height: metrics.size.height * 0.8) } - ExtExerciseList(workout: workout, - currentExerciseIdx: bridgeModule.currentExerciseIdx) - .frame(width: metrics.size.width * 0.4, height: metrics.size.height * 0.7) + ExtCountdownView() + .frame(width: metrics.size.width-50, height: metrics.size.height * 0.2) + .padding([.leading, .trailing], 50) + .background(Color(uiColor: UIColor.secondarySystemBackground)) } - - ExtCountdownView() - .frame(width: metrics.size.width-50, height: metrics.size.height * 0.2) - .padding([.leading, .trailing], 50) } + } else { + Text("nothing here bro") + } + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background(.background) + } +} + +struct TitleView: View { + @ObservedObject var bridgeModule = BridgeModule.shared + + var body: some View { + HStack { + if let workout = bridgeModule.currentWorkout { + Text(workout.name) + .font(Font.system(size: 100)) + .frame(maxWidth: .infinity, alignment: .leading) + } + + if bridgeModule.currentWorkoutRunTimeInSeconds > -1 { + Text("\(bridgeModule.currentWorkoutRunTimeInSeconds)") + .font(Font.system(size: 100)) + .frame(maxWidth: .infinity, alignment: .trailing) + .padding(.trailing, 100) } } } @@ -69,19 +93,29 @@ struct ExtCountdownView: View { var body: some View { VStack { if let currenExercise = bridgeModule.currentExercise { - Text(currenExercise.exercise.name) - .font(Font.system(size: 100)) - .frame(maxWidth: .infinity, alignment: .leading) - + HStack { + Text(currenExercise.exercise.name) + .font(Font.system(size: 100)) + .frame(maxWidth: .infinity, alignment: .leading) + + if bridgeModule.currentWorkoutRunTimeInSeconds > -1 { + Text("\(bridgeModule.currentWorkoutRunTimeInSeconds)") + .font(Font.system(size: 100)) + .frame(maxWidth: .infinity, alignment: .trailing) + .padding(.trailing, 100) + } + } HStack { if let duration = currenExercise.duration { ProgressView(value: Float(bridgeModule.timeLeft), total: Float(duration)) .scaleEffect(x: 1, y: 6, anchor: .center) Text("\(bridgeModule.timeLeft)") .font(Font.system(size: 75)) - .padding(.leading) + .padding([.leading, .trailing]) } else if let reps = currenExercise.reps { Text("\(reps)") + .font(Font.system(size: 75)) + .padding([.leading, .trailing]) } } } @@ -98,6 +132,11 @@ struct VideoPlayerView: View { .onAppear{ player = AVPlayer(url: Bundle.main.url(forResource: "Straight_Leg_Sit_Up", withExtension: "mp4")!) player.play() + + NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: nil, queue: .main) { _ in + player.seek(to: .zero) + player.play() + } } } } diff --git a/Werkout_ios/Views/WorkoutDetailView.swift b/Werkout_ios/Views/WorkoutDetailView.swift index 953cdbf..e970561 100644 --- a/Werkout_ios/Views/WorkoutDetailView.swift +++ b/Werkout_ios/Views/WorkoutDetailView.swift @@ -12,12 +12,6 @@ struct WorkoutDetailView: View { var bridgeModule = BridgeModule.shared @Environment(\.dismiss) var dismiss - @State var selectedIdx = 0 { - didSet { - runItemAt(idx: selectedIdx) - } - } - var body: some View { ZStack { switch viewModel.status { @@ -25,53 +19,70 @@ struct WorkoutDetailView: View { Text("Loading") case .showWorkout(let workout): VStack { - HStack { - Button("i dont want to do this", action: { - bridgeModule.currentWorkout = nil - dismiss() - }) - .frame(maxWidth: .infinity, maxHeight: .infinity) - .background(.red) - - Button("ohhh lets do it", action: { - bridgeModule.currentWorkout = workout - runItemAt(idx: 0) - }) - .frame(maxWidth: .infinity, maxHeight: .infinity) - .background(.green) - } + TopButtonsView(workout: workout) .frame(height: 88) + CurrentWorkoutElapsedTimeView() ExerciseListView(workout: workout) CountdownView() } - .onAppear{ - bridgeModule.timerCompleted = { - selectedIdx += 1 - } - } .interactiveDismissDisabled() } } } +} - func runItemAt(idx: Int) { - switch viewModel.status { - case .showWorkout(let workout): - if idx < workout.exercises.count { - let exercise = workout.exercises[idx] - bridgeModule.updateCurrent(exercise: exercise) - bridgeModule.currentExerciseIdx = idx +struct TopButtonsView: View { + @ObservedObject var bridgeModule = BridgeModule.shared + var workout: Workout + @Environment(\.dismiss) var dismiss + + var body: some View { + HStack { + if bridgeModule.currentWorkoutRunTimeInSeconds == -1 { + Button(action: { + bridgeModule.completeWorkout() + dismiss() + }, label: { + Image(systemName: "xmark.octagon.fill") + .font(.title) + }) + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background(.red) + .foregroundColor(.white) + + Button(action: { + bridgeModule.start(workout: workout) + }, label: { + Image(systemName: "figure.golf") + .font(.title) + }) + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background(.green) + .foregroundColor(.white) } else { - workoutComplete() + Button(action: { + bridgeModule.completeWorkout() + dismiss() + }, label: { + Image(systemName: "checkmark") + .font(.title) + }) + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background(.blue) + .foregroundColor(.white) } - default: - fatalError("no workout!!") } } +} + +struct CurrentWorkoutElapsedTimeView: View { + @ObservedObject var bridgeModule = BridgeModule.shared - private func workoutComplete() { - + var body: some View { + if bridgeModule.currentWorkoutRunTimeInSeconds > -1 { + Text("\(bridgeModule.currentWorkoutRunTimeInSeconds)") + } } } @@ -84,7 +95,9 @@ struct ExerciseListView: View { ForEach(workout.exercisesSortedByCreated_at.indices, id: \.self) { i in let obj = workout.exercisesSortedByCreated_at[i] Text(obj.exercise.name) - // .onTapGesture { selectedIdx = i } + .onTapGesture { + bridgeModule.start(workout: workout, atExerciseIndex: i) + } } } } diff --git a/Werkout_ios/Werkout_iosApp.swift b/Werkout_ios/Werkout_iosApp.swift index 834ff20..0e80e8e 100644 --- a/Werkout_ios/Werkout_iosApp.swift +++ b/Werkout_ios/Werkout_iosApp.swift @@ -83,6 +83,7 @@ struct Werkout_iosApp: App { as? UIWindowScene let view = ExternalWorkoutDetailView() + .preferredColorScheme(.dark) let controller = UIHostingController(rootView: view) window.rootViewController = controller window.isHidden = false