// // ExternalView.swift // Werkout_ios // // Created by Trey Tartt on 6/13/23. // import SwiftUI import AVKit struct ExternalWorkoutDetailView: View { @StateObject var bridgeModule = BridgeModule.shared @State var avPlayer = AVPlayer(url: URL(string: "https://dev.werkout.fitness/media/exercise_videos/2_Dumbbell_Lateral_Lunges.mp4")!) @AppStorage("showNSFWVideos") private var showNSFWVideos = false var body: some View { ZStack { if let workout = bridgeModule.currentWorkout { GeometryReader { metrics in VStack { HStack { VideoPlayerView(avPlayer: $avPlayer, showDoneButton: false) .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.3, height: metrics.size.height * 0.8) } ExtCountdownView() .frame(width: metrics.size.width-50, height: metrics.size.height * 0.2) .padding([.leading, .trailing], 50) .background(Color(uiColor: UIColor.secondarySystemBackground)) } } } else { Text("nothing here bro") } } .onChange(of: bridgeModule.currentExercise, perform: { newValue in if showNSFWVideos { if let viddd = newValue?.exercise.nsfwVideoURL, let url = URL(string: BaseURLs.currentBaseURL + viddd) { avPlayer = AVPlayer(url: url) } } else { if let viddd = newValue?.exercise.videoURL, let url = URL(string: BaseURLs.currentBaseURL + viddd) { avPlayer = AVPlayer(url: url) } } }) .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) } } } } struct ExtExerciseList: View { var workout: Workout var currentExerciseIdx: Int var body: some View { ScrollViewReader { proxy in List() { ForEach(workout.exercisesSortedByCreated_at.indices, id: \.self) { i in let obj = workout.exercisesSortedByCreated_at[i] HStack { if i == currentExerciseIdx { Image(systemName: "checkmark") .font(Font.system(size: 75)) .scaledToFit() .minimumScaleFactor(0.01) .lineLimit(1) .foregroundColor(.green) } Text(obj.exercise.name) .font(Font.system(size: 75)) .scaledToFit() .minimumScaleFactor(0.01) .lineLimit(1) .padding() .id(i) } } } .onChange(of: currentExerciseIdx, perform: { newValue in withAnimation { proxy.scrollTo(newValue, anchor: .top) } }) } } } struct ExtCountdownView: View { @StateObject var bridgeModule = BridgeModule.shared var body: some View { GeometryReader { metrics in VStack { if let currenExercise = bridgeModule.currentExercise { HStack { Text(currenExercise.exercise.name) .font(.system(size: 200)) .scaledToFit() .minimumScaleFactor(0.01) .lineLimit(1) .frame(maxWidth: .infinity, alignment: .leading) if bridgeModule.currentWorkoutRunTimeInSeconds > -1 { Text("\(bridgeModule.currentWorkoutRunTimeInSeconds)") .font(Font.system(size: 100)) .scaledToFit() .minimumScaleFactor(0.01) .lineLimit(1) .frame(maxWidth: .infinity, alignment: .trailing) .padding(.trailing, 100) } } .frame(height: metrics.size.height * 0.5) HStack { if let duration = currenExercise.duration { ProgressView(value: Float(bridgeModule.currentExerciseTimeLeft), total: Float(duration)) .scaleEffect(x: 1, y: 6, anchor: .center) Text("\(bridgeModule.currentExerciseTimeLeft)") .font(Font.system(size: 75)) .scaledToFit() .minimumScaleFactor(0.01) .lineLimit(1) .padding([.leading, .trailing]) } else if let reps = currenExercise.reps { Text("\(reps)") .font(Font.system(size: 75)) .scaledToFit() .minimumScaleFactor(0.01) .lineLimit(1) .padding([.leading, .trailing]) } } .frame(height: metrics.size.height * 0.5) } } } } } struct ExternalWorkoutDetailView_Previews: PreviewProvider { static var bridge = BridgeModule.shared static var previews: some View { ExternalWorkoutDetailView().environmentObject({ () -> BridgeModule in let envObj = BridgeModule.shared envObj.currentWorkout = PreviewData.workout() bridge.currentExercise = PreviewData.workout().exercisesSortedByCreated_at.first! return envObj }() ) } }