This commit is contained in:
Trey t
2023-07-24 11:22:29 -05:00
parent 2753e31f24
commit 2dcd260887
12 changed files with 298 additions and 150 deletions

View File

@@ -8,7 +8,7 @@
import Foundation import Foundation
struct SupersetExercise: Identifiable, Codable, Equatable, Hashable { struct SupersetExercise: Identifiable, Codable, Equatable, Hashable {
var id = UUID() var id: Int
let workout: Int? let workout: Int?
let exercise: Exercise let exercise: Exercise
@@ -19,12 +19,15 @@ struct SupersetExercise: Identifiable, Codable, Equatable, Hashable {
let weightAudio: String? let weightAudio: String?
let createdAt: String let createdAt: String
let order, superset: Int let order, superset: Int
let uniqueID: String
let description: String?
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case workout, exercise, weight, reps, duration, order, superset case workout, exercise, weight, reps, duration, order, superset, id, description
case durationAudio = "duration_audio" case durationAudio = "duration_audio"
case weightAudio = "weight_audio" case weightAudio = "weight_audio"
case createdAt = "created_at" case createdAt = "created_at"
case uniqueID = "unique_id"
} }
public func hash(into hasher: inout Hasher) { public func hash(into hasher: inout Hasher) {
@@ -67,4 +70,13 @@ struct Exercise: Identifiable, Codable, Equatable {
case muscleGroups = "muscle_groups" case muscleGroups = "muscle_groups"
case synonyms case synonyms
} }
var extName: String {
if side.count > 0 {
var returnString = name + " - " + side
returnString = returnString.replacingOccurrences(of: "_", with: " ")
return returnString.capitalized
}
return name
}
} }

View File

@@ -12,6 +12,6 @@ enum BaseURLs: String {
case dev = "https://dev.werkout.fitness" case dev = "https://dev.werkout.fitness"
static var currentBaseURL: String { static var currentBaseURL: String {
return BaseURLs.local.rawValue return BaseURLs.dev.rawValue
} }
} }

View File

@@ -133,12 +133,8 @@ class BridgeModule: NSObject, ObservableObject {
if currentExerciseTimeLeft > 0 { if currentExerciseTimeLeft > 0 {
currentExerciseTimeLeft -= 1 currentExerciseTimeLeft -= 1
if currentExerciseTimeLeft == 0 { if currentExerciseTimeLeft <= 3 {
playFinished() playBeep()
} else {
if currentExerciseTimeLeft <= 3 {
playBeep()
}
} }
sendCurrentExerciseToWatch() sendCurrentExerciseToWatch()
} else { } else {
@@ -158,6 +154,7 @@ class BridgeModule: NSObject, ObservableObject {
func nextExercise() { func nextExercise() {
if let nextSupersetExercise = currentExerciseInfo.nextExercise { if let nextSupersetExercise = currentExerciseInfo.nextExercise {
updateCurrent(exercise: nextSupersetExercise) updateCurrent(exercise: nextSupersetExercise)
playFinished()
} else { } else {
completeWorkout() completeWorkout()
} }
@@ -196,6 +193,7 @@ class BridgeModule: NSObject, ObservableObject {
func completeWorkout() { func completeWorkout() {
self.currentExerciseTimer?.invalidate() self.currentExerciseTimer?.invalidate()
self.currentExerciseTimer = nil self.currentExerciseTimer = nil
self.isInWorkout = false
workoutEndDate = Date() workoutEndDate = Date()

View File

@@ -21,7 +21,13 @@ class CurrentWorkoutInfo {
var currentExercise: SupersetExercise? { var currentExercise: SupersetExercise? {
guard let supersets = workout?.supersets else { return nil } guard let supersets = workout?.supersets else { return nil }
if supersetIndex >= supersets.count { return nil }
let superset = supersets[supersetIndex] let superset = supersets[supersetIndex]
// will be -1 for a moment while going to previous workout / superset
if exerciseIndex < 0 { return nil }
if exerciseIndex > superset.exercises.count { return nil }
let exercise = superset.exercises[exerciseIndex] let exercise = superset.exercises[exerciseIndex]
return exercise return exercise
} }
@@ -62,12 +68,18 @@ class CurrentWorkoutInfo {
if exerciseIndex < 0 { if exerciseIndex < 0 {
if currentRound > 1 { if currentRound > 1 {
currentRound -= 1 currentRound -= 1
let superset = supersets[supersetIndex]
exerciseIndex = superset.exercises.count-1
} else { } else {
if supersetIndex > 1 { if supersetIndex > 0 {
supersetIndex -= 1 supersetIndex -= 1
let superset = supersets[supersetIndex]
currentRound = superset.rounds
exerciseIndex = superset.exercises.count-1
} else {
exerciseIndex = 0
} }
} }
exerciseIndex = 0
} }
let superset = supersets[supersetIndex] let superset = supersets[supersetIndex]

View File

@@ -14,6 +14,7 @@ struct AccountView: View {
@State var showCompletedWorkouts: Bool = false @State var showCompletedWorkouts: Bool = false
@AppStorage(Constants.phoneThotStyle) private var phoneThotStyle: ThotStyle = .never @AppStorage(Constants.phoneThotStyle) private var phoneThotStyle: ThotStyle = .never
@AppStorage(Constants.extThotStyle) private var extThotStyle: ThotStyle = .never @AppStorage(Constants.extThotStyle) private var extThotStyle: ThotStyle = .never
@AppStorage(Constants.extShowBothVideos) private var extShowBothVideos: Bool = false
var body: some View { var body: some View {
VStack(alignment: .leading) { VStack(alignment: .leading) {
@@ -63,26 +64,36 @@ struct AccountView: View {
} }
} }
Divider() Divider()
Text("Phone THOT Style:") Group {
Picker("Phone THOT Style:", selection: $phoneThotStyle) { Text("Phone THOT Style:")
ForEach(ThotStyle.allCases, id: \.self) { style in Picker("Phone THOT Style:", selection: $phoneThotStyle) {
Text(style.stringValue()) ForEach(ThotStyle.allCases, id: \.self) { style in
.tag(phoneThotStyle.rawValue) Text(style.stringValue())
.tag(phoneThotStyle.rawValue)
}
} }
} .pickerStyle(.segmented)
.pickerStyle(.segmented)
Divider()
Divider()
Text("External THOT Style:")
Text("External THOT Style:") Picker("External THOT Style:", selection: $extThotStyle) {
Picker("External THOT Style:", selection: $extThotStyle) { ForEach(ThotStyle.allCases, id: \.self) { style in
ForEach(ThotStyle.allCases, id: \.self) { style in Text(style.stringValue())
Text(style.stringValue()) .tag(extThotStyle.rawValue)
.tag(extThotStyle.rawValue) }
} }
.pickerStyle(.segmented)
} }
.pickerStyle(.segmented)
Group {
Divider()
Toggle(isOn: $extShowBothVideos, label: {
Text("Show both videos on external")
})
}
Spacer() Spacer()
Button("Logout", action: { Button("Logout", action: {

View File

@@ -11,8 +11,10 @@ import AVKit
struct ExternalWorkoutDetailView: View { struct ExternalWorkoutDetailView: View {
@StateObject var bridgeModule = BridgeModule.shared @StateObject var bridgeModule = BridgeModule.shared
@State var avPlayer = AVPlayer(url: URL(string: "https://dev.werkout.fitness/media/exercise_videos/2_Dumbbell_Lateral_Lunges.mp4")!) @State var avPlayer = AVPlayer(url: URL(string: "https://dev.werkout.fitness/media/exercise_videos/2_Dumbbell_Lateral_Lunges.mp4")!)
@State var smallAVPlayer = AVPlayer(url: URL(string: "https://dev.werkout.fitness/media/exercise_videos/2_Dumbbell_Lateral_Lunges.mp4")!)
@AppStorage(Constants.extThotStyle) private var extThotStyle: ThotStyle = .never @AppStorage(Constants.extThotStyle) private var extThotStyle: ThotStyle = .never
@AppStorage(Constants.extShowBothVideos) private var extShowBothVideos: Bool = false
var body: some View { var body: some View {
ZStack { ZStack {
if let workout = bridgeModule.currentExerciseInfo.workout, if let workout = bridgeModule.currentExerciseInfo.workout,
@@ -20,11 +22,13 @@ struct ExternalWorkoutDetailView: View {
GeometryReader { metrics in GeometryReader { metrics in
VStack { VStack {
HStack { HStack {
PlayerView(player: $avPlayer) if extThotStyle != .off {
.frame(width: metrics.size.width * 0.5, height: metrics.size.height * 0.8) PlayerView(player: $avPlayer)
.onAppear{ .frame(width: metrics.size.width * 0.5, height: metrics.size.height * 0.8)
avPlayer.play() .onAppear{
} avPlayer.play()
}
}
VStack { VStack {
ExtExerciseList(workout: workout, ExtExerciseList(workout: workout,
@@ -42,9 +46,25 @@ struct ExternalWorkoutDetailView: View {
.frame(width: metrics.size.width * 0.4, height: metrics.size.height * 0.8) .frame(width: metrics.size.width * 0.4, height: metrics.size.height * 0.8)
} }
ExtCountdownView() HStack {
.frame(width: metrics.size.width-50, height: metrics.size.height * 0.2) if extShowBothVideos && extThotStyle != .off {
.padding([.leading, .trailing], 50) ExtCountdownView()
.frame(width: metrics.size.width * 0.8, height: metrics.size.height * 0.2)
.padding(.leading, 50)
.padding(.trailing, 5)
PlayerView(player: $smallAVPlayer)
.frame(width: metrics.size.width * 0.2, height: metrics.size.height * 0.2)
.padding(.trailing, 50)
.onAppear{
avPlayer.play()
}
} else {
ExtCountdownView()
.frame(width: metrics.size.width-50, height: metrics.size.height * 0.2)
.padding([.leading, .trailing], 50)
}
}
} }
} }
} else { } else {
@@ -54,6 +74,29 @@ struct ExternalWorkoutDetailView: View {
.scaledToFill() .scaledToFill()
} }
} }
.onChange(of: bridgeModule.isInWorkout, perform: { newValue in
if let currentExtercise = bridgeModule.currentExerciseInfo.currentExercise {
if let videoURL = VideoURLCreator.videoURL(
thotStyle: extThotStyle,
defaultVideoURLStr: currentExtercise.exercise.videoURL,
exerciseName: currentExtercise.exercise.name,
workout: bridgeModule.currentExerciseInfo.workout) {
avPlayer = AVPlayer(url: videoURL)
avPlayer.play()
if extShowBothVideos {
if let smallVideoURL = VideoURLCreator.videoURL(
thotStyle: VideoURLCreator.otherVideoType(forVideoURL: videoURL),
defaultVideoURLStr: currentExtercise.exercise.videoURL,
exerciseName: currentExtercise.exercise.name,
workout: bridgeModule.currentExerciseInfo.workout) {
smallAVPlayer = AVPlayer(url: smallVideoURL)
smallAVPlayer.play()
}
}
}
}
})
.onChange(of: bridgeModule.currentExerciseInfo.exerciseIndex, perform: { newValue in .onChange(of: bridgeModule.currentExerciseInfo.exerciseIndex, perform: { newValue in
if let currentExtercise = bridgeModule.currentExerciseInfo.currentExercise { if let currentExtercise = bridgeModule.currentExerciseInfo.currentExercise {
if let videoURL = VideoURLCreator.videoURL( if let videoURL = VideoURLCreator.videoURL(
@@ -63,11 +106,27 @@ struct ExternalWorkoutDetailView: View {
workout: bridgeModule.currentExerciseInfo.workout) { workout: bridgeModule.currentExerciseInfo.workout) {
avPlayer = AVPlayer(url: videoURL) avPlayer = AVPlayer(url: videoURL)
avPlayer.play() avPlayer.play()
if extShowBothVideos {
if let smallVideoURL = VideoURLCreator.videoURL(
thotStyle: VideoURLCreator.otherVideoType(forVideoURL: videoURL),
defaultVideoURLStr: currentExtercise.exercise.videoURL,
exerciseName: currentExtercise.exercise.name,
workout: bridgeModule.currentExerciseInfo.workout) {
smallAVPlayer = AVPlayer(url: smallVideoURL)
smallAVPlayer.play()
}
}
} }
} }
}) })
.frame(maxWidth: .infinity, maxHeight: .infinity) .frame(maxWidth: .infinity, maxHeight: .infinity)
.background(bridgeModule.currentExerciseInfo.workout == nil ? Color(red: 157/255, green: 138/255, blue: 255/255) : Color(uiColor: .systemBackground)) .background(bridgeModule.currentExerciseInfo.workout == nil ? Color(red: 157/255, green: 138/255, blue: 255/255) : Color(uiColor: .systemBackground))
.onReceive(NotificationCenter.default.publisher(
for: UIScene.willEnterForegroundNotification)) { _ in
avPlayer.play()
smallAVPlayer.play()
}
} }
} }
@@ -116,17 +175,16 @@ struct ExtExerciseList: View {
.lineLimit(1) .lineLimit(1)
.foregroundColor(.green) .foregroundColor(.green)
} }
Text(supersetExecercise.exercise.name) Text(supersetExecercise.exercise.name)
.id(exerciseIndex)
.font(Font.system(size: 55)) .font(Font.system(size: 55))
.minimumScaleFactor(0.01) .minimumScaleFactor(0.01)
.lineLimit(3) .lineLimit(3)
.padding() .padding()
.id(exerciseIndex)
Spacer() Spacer()
} }
.id(supersetExecercise.id)
} }
}, header: { }, header: {
HStack { HStack {
@@ -148,7 +206,8 @@ struct ExtExerciseList: View {
} }
.onChange(of: currentExercise, perform: { newValue in .onChange(of: currentExercise, perform: { newValue in
withAnimation { withAnimation {
proxy.scrollTo(newValue, anchor: .top) print(newValue.id)
proxy.scrollTo(newValue.id, anchor: .top)
} }
}) })
} }
@@ -164,22 +223,13 @@ struct ExtCountdownView: View {
VStack { VStack {
if let currenExercise = bridgeModule.currentExerciseInfo.currentExercise { if let currenExercise = bridgeModule.currentExerciseInfo.currentExercise {
HStack { HStack {
Text(currenExercise.exercise.name) Text(currenExercise.exercise.extName)
.font(.system(size: 200)) .font(.system(size: 200))
.scaledToFit() .scaledToFit()
.minimumScaleFactor(0.01) .minimumScaleFactor(0.01)
.lineLimit(1) .lineLimit(1)
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: .infinity, alignment: .leading)
if currenExercise.exercise.side.count > 0 {
Text(" - " + currenExercise.exercise.side)
.font(.system(size: 200))
.scaledToFit()
.minimumScaleFactor(0.01)
.lineLimit(1)
.frame(maxWidth: .infinity, alignment: .leading)
}
if bridgeModule.currentWorkoutRunTimeInSeconds > -1 { if bridgeModule.currentWorkoutRunTimeInSeconds > -1 {
Text("\(Double(bridgeModule.currentWorkoutRunTimeInSeconds).asString(style: .positional))") Text("\(Double(bridgeModule.currentWorkoutRunTimeInSeconds).asString(style: .positional))")
.font(Font.system(size: 100)) .font(Font.system(size: 100))

View File

@@ -82,6 +82,14 @@ struct PlayerView: UIViewRepresentable {
} }
class VideoURLCreator { class VideoURLCreator {
class func otherVideoType(forVideoURL videoURL: URL) -> ThotStyle {
var otherVideoStyle = ThotStyle.never
if videoURL.absoluteString.contains("exercise_videos") {
otherVideoStyle = .always
}
return otherVideoStyle
}
class func videoURL(thotStyle: ThotStyle, defaultVideoURLStr: String?, exerciseName: String?, workout: Workout?) -> URL? { class func videoURL(thotStyle: ThotStyle, defaultVideoURLStr: String?, exerciseName: String?, workout: Workout?) -> URL? {
var urlString: String? var urlString: String?
@@ -102,6 +110,8 @@ class VideoURLCreator {
} else { } else {
urlString = defaultVideoURLStr urlString = defaultVideoURLStr
} }
case .off:
return nil
} }
if let urlString = urlString, if let urlString = urlString,

View File

@@ -12,6 +12,7 @@ enum ThotStyle: Int, CaseIterable {
case never = 2 case never = 2
case recovery = 3 case recovery = 3
case random = 4 case random = 4
case off
func stringValue() -> String { func stringValue() -> String {
switch(self) { switch(self) {
@@ -23,6 +24,8 @@ enum ThotStyle: Int, CaseIterable {
return "Recovery" return "Recovery"
case .random: case .random:
return "Random" return "Random"
case .off:
return "Off"
} }
} }
} }

View File

@@ -13,6 +13,7 @@ struct ExerciseListView: View {
@ObservedObject var bridgeModule = BridgeModule.shared @ObservedObject var bridgeModule = BridgeModule.shared
@State var avPlayer = AVPlayer(url: URL(string: "https://dev.werkout.fitness/media/exercise_videos/2_Dumbbell_Lateral_Lunges.mp4")!) @State var avPlayer = AVPlayer(url: URL(string: "https://dev.werkout.fitness/media/exercise_videos/2_Dumbbell_Lateral_Lunges.mp4")!)
var workout: Workout var workout: Workout
@Binding var showExecersizeInfo: Bool
@State var videoExercise: Exercise? { @State var videoExercise: Exercise? {
didSet { didSet {
@@ -36,74 +37,72 @@ struct ExerciseListView: View {
Section(content: { Section(content: {
ForEach(superset.exercises.indices, id: \.self) { exerciseIndex in ForEach(superset.exercises.indices, id: \.self) { exerciseIndex in
let supersetExecercise = superset.exercises[exerciseIndex] let supersetExecercise = superset.exercises[exerciseIndex]
VStack {
HStack { HStack {
if supersetExecercise.id == bridgeModule.currentExerciseInfo.currentExercise?.id { if bridgeModule.isInWorkout &&
Image(systemName: "checkmark") supersetIndex == bridgeModule.currentExerciseInfo.supersetIndex &&
.foregroundColor(.green) exerciseIndex == bridgeModule.currentExerciseInfo.exerciseIndex {
} Image(systemName: "checkmark")
.foregroundColor(.green)
Text(supersetExecercise.exercise.name) }
.id(exerciseIndex)
Text(supersetExecercise.exercise.extName)
Spacer()
Spacer()
if let reps = supersetExecercise.reps,
reps > 0 { if let reps = supersetExecercise.reps,
HStack { reps > 0 {
Image(systemName: "number") HStack {
.foregroundColor(.white) Image(systemName: "number")
.frame(width: 20, alignment: .leading) .foregroundColor(.white)
Text("\(reps)") .frame(width: 20, alignment: .leading)
.foregroundColor(.white) Text("\(reps)")
.frame(width: 30, alignment: .trailing) .foregroundColor(.white)
.frame(width: 30, alignment: .trailing)
}
.padding([.top, .bottom], 5)
.padding([.leading], 10)
.padding([.trailing], 15)
.background(.blue)
.cornerRadius(5, corners: [.topLeft, .bottomLeft])
.frame(alignment: .trailing)
}
if let duration = supersetExecercise.duration,
duration > 0 {
HStack {
Image(systemName: "stopwatch")
.foregroundColor(.white)
.frame(width: 20, alignment: .leading)
Text("\(duration)")
.foregroundColor(.white)
.frame(width: 30, alignment: .trailing)
}
.padding([.top, .bottom], 5)
.padding([.leading], 10)
.padding([.trailing], 15)
.background(.green)
.cornerRadius(5, corners: [.topLeft, .bottomLeft])
}
}
.padding(.trailing, -20)
.contentShape(Rectangle())
.onTapGesture {
if bridgeModule.isInWorkout {
bridgeModule.goToExerciseAt(section: supersetIndex, row: exerciseIndex)
} else {
videoExercise = supersetExecercise.exercise
} }
.padding([.top, .bottom], 5)
.padding([.leading], 10)
.padding([.trailing], 15)
.background(.blue)
.cornerRadius(5, corners: [.topLeft, .bottomLeft])
.frame(alignment: .trailing)
} }
if let duration = supersetExecercise.duration, if bridgeModule.isInWorkout &&
duration > 0 { supersetIndex == bridgeModule.currentExerciseInfo.supersetIndex &&
HStack { exerciseIndex == bridgeModule.currentExerciseInfo.exerciseIndex &&
Image(systemName: "stopwatch") showExecersizeInfo {
.foregroundColor(.white) detailView(forExercise: supersetExecercise)
.frame(width: 20, alignment: .leading)
Text("\(duration)")
.foregroundColor(.white)
.frame(width: 30, alignment: .trailing)
}
.padding([.top, .bottom], 5)
.padding([.leading], 10)
.padding([.trailing], 15)
.background(.green)
.cornerRadius(5, corners: [.topLeft, .bottomLeft])
} }
} }.id(supersetExecercise.id)
.padding(.trailing, -20)
.contentShape(Rectangle())
.onTapGesture {
if bridgeModule.isInWorkout {
bridgeModule.goToExerciseAt(section: supersetIndex, row: exerciseIndex)
} else {
// videoExercise = obj.exercise
}
// .onChange(of: bridgeModule.currentExerciseIdx, perform: { newValue in
// withAnimation {
// proxy.scrollTo(newValue, anchor: .top)
// }
// })
}
.sheet(item: $videoExercise) { exercise in
PlayerView(player: $avPlayer)
.onAppear{
avPlayer.play()
}
}
} }
}, header: { }, header: {
HStack { HStack {
@@ -118,13 +117,36 @@ struct ExerciseListView: View {
}) })
} }
} }
.onChange(of: bridgeModule.currentExerciseInfo.exerciseIndex, perform: { newValue in
if let newCurrentExercise = bridgeModule.currentExerciseInfo.currentExercise {
withAnimation {
proxy.scrollTo(newCurrentExercise.id, anchor: .top)
}
}
})
.sheet(item: $videoExercise) { exercise in
PlayerView(player: $avPlayer)
.onAppear{
avPlayer.play()
}
}
} }
} }
} }
func detailView(forExercise supersetExecercise: SupersetExercise) -> some View {
VStack {
Text(supersetExecercise.exercise.description)
.frame(alignment: .leading)
Divider()
Text(supersetExecercise.exercise.muscles.map({ $0.name }).joined(separator: ", "))
.frame(alignment: .leading)
}
}
} }
struct ExerciseListView_Previews: PreviewProvider { //struct ExerciseListView_Previews: PreviewProvider {
static var previews: some View { // static var previews: some View {
ExerciseListView(workout: PreviewData.workout()) // ExerciseListView(workout: PreviewData.workout(), showExecersizeInfo: )
} // }
} //}

View File

@@ -23,6 +23,7 @@ struct WorkoutDetailView: View {
@State var presentedSheet: Sheet? @State var presentedSheet: Sheet?
@State var workoutToPlan: Workout? @State var workoutToPlan: Workout?
@State var showExecersizeInfo: Bool = false
var body: some View { var body: some View {
ZStack { ZStack {
@@ -39,33 +40,47 @@ struct WorkoutDetailView: View {
.padding() .padding()
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
GeometryReader { metrics in if phoneThotStyle != .off {
ZStack { GeometryReader { metrics in
PlayerView(player: $avPlayer) ZStack {
.frame(width: metrics.size.width * 1, height: metrics.size.height * 1)
.onAppear{ PlayerView(player: $avPlayer)
avPlayer.play() .frame(width: metrics.size.width * 1, height: metrics.size.height * 1)
} .onAppear{
avPlayer.play()
}
}
Button(action: { Button(action: {
if let assetURL = ((avPlayer.currentItem?.asset) as? AVURLAsset)?.url { if let assetURL = ((avPlayer.currentItem?.asset) as? AVURLAsset)?.url,
if assetURL.absoluteString.lowercased().contains("exercise_videos") { let currentExtercise = bridgeModule.currentExerciseInfo.currentExercise,
let otherVideoURL = VideoURLCreator.videoURL(
} else { thotStyle: VideoURLCreator.otherVideoType(forVideoURL: assetURL),
defaultVideoURLStr: currentExtercise.exercise.videoURL,
} exerciseName: currentExtercise.exercise.name,
// avPlayer = AVPlayer(url: videoURL) workout: bridgeModule.currentExerciseInfo.workout) {
// avPlayer.play() avPlayer = AVPlayer(url: otherVideoURL)
avPlayer.play()
} }
}, label: { }, label: {
Text("Toggle THOT") Image(systemName: "arrow.triangle.2.circlepath.camera.fill")
.padding() .frame(width: 44, height: 44)
}) })
.background(.yellow)
.foregroundColor(.blue) .foregroundColor(.blue)
.cornerRadius(4) .cornerRadius(4)
.frame(width: 160, height: 60) .frame(width: 160, height: 120)
.position(x: metrics.size.width - 80, y: metrics.size.height - 30) .position(x: metrics.size.width - 22, y: metrics.size.height - 30)
Button(action: {
showExecersizeInfo.toggle()
}, label: {
Image(systemName: "info.circle.fill")
.frame(width: 44, height: 44)
})
.foregroundColor(.blue)
.cornerRadius(4)
.frame(width: 120, height: 120)
.position(x: 22, y: metrics.size.height - 30)
} }
} }
} }
@@ -73,7 +88,7 @@ struct WorkoutDetailView: View {
InfoView(workout: workout) InfoView(workout: workout)
.padding(.bottom) .padding(.bottom)
ExerciseListView(workout: workout) ExerciseListView(workout: workout, showExecersizeInfo: $showExecersizeInfo)
ActionsView(completedWorkout: { ActionsView(completedWorkout: {
bridgeModule.completeWorkout() bridgeModule.completeWorkout()
@@ -112,6 +127,18 @@ struct WorkoutDetailView: View {
} }
} }
}) })
.onChange(of: bridgeModule.isInWorkout, perform: { newValue in
if let currentExtercise = bridgeModule.currentExerciseInfo.currentExercise {
if let videoURL = VideoURLCreator.videoURL(
thotStyle: phoneThotStyle,
defaultVideoURLStr: currentExtercise.exercise.videoURL,
exerciseName: currentExtercise.exercise.name,
workout: bridgeModule.currentExerciseInfo.workout) {
avPlayer = AVPlayer(url: videoURL)
avPlayer.play()
}
}
})
.onAppear{ .onAppear{
if let currentExtercise = bridgeModule.currentExerciseInfo.currentExercise { if let currentExtercise = bridgeModule.currentExerciseInfo.currentExercise {
if let videoURL = VideoURLCreator.videoURL( if let videoURL = VideoURLCreator.videoURL(
@@ -131,7 +158,10 @@ struct WorkoutDetailView: View {
} }
} }
} }
.onReceive(NotificationCenter.default.publisher(
for: UIScene.willEnterForegroundNotification)) { _ in
avPlayer.play()
}
} }
func createWorkoutData() -> [String:Any]? { func createWorkoutData() -> [String:Any]? {

View File

@@ -13,6 +13,7 @@ import AVKit
struct Constants { struct Constants {
static let phoneThotStyle = "phoneThotStyle" static let phoneThotStyle = "phoneThotStyle"
static let extThotStyle = "extThotStyle" static let extThotStyle = "extThotStyle"
static let extShowBothVideos = "extShowBothVideos"
} }
@main @main

View File

@@ -15,18 +15,17 @@ struct MainWatchView: View {
HStack { HStack {
if vm.isInWorkout { if vm.isInWorkout {
Text(vm.watchPackageModel.currentExerciseName) Text(vm.watchPackageModel.currentExerciseName)
.font(Font.system(size: 55)) .font(.body)
.scaledToFit()
.minimumScaleFactor(0.01)
.lineLimit(1)
.foregroundColor(.white) .foregroundColor(.white)
.lineLimit(10)
.fixedSize(horizontal: false, vertical: true)
.frame(maxWidth: .infinity, alignment: .leading)
Divider() Divider()
Text("\(vm.watchPackageModel.currentTimeLeft )") Text("\(vm.watchPackageModel.currentTimeLeft )")
.font(Font.system(size: 55)) .font(.title)
.scaledToFit()
.minimumScaleFactor(0.01)
.lineLimit(1)
.foregroundColor(.white) .foregroundColor(.white)
.lineLimit(10)
.fixedSize(horizontal: false, vertical: true)
} }
} }