WIP
This commit is contained in:
@@ -15,6 +15,8 @@
|
||||
1C485C8A2A492BB400A6F896 /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C485C892A492BB400A6F896 /* LoginView.swift */; };
|
||||
1C485C8C2A49D65600A6F896 /* WorkoutHistoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C485C8B2A49D65600A6F896 /* WorkoutHistoryView.swift */; };
|
||||
1C485C8D2A49D95700A6F896 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A822A42347D0042FFBD /* Extensions.swift */; };
|
||||
1C4AFF152A60F25F0027710B /* ThotStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C4AFF142A60F25E0027710B /* ThotStyle.swift */; };
|
||||
1C4AFF162A60F27E0027710B /* ThotStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C4AFF142A60F25E0027710B /* ThotStyle.swift */; };
|
||||
1C5190C22A57CA5F00885849 /* OvalTextFieldStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C5190C12A57CA5F00885849 /* OvalTextFieldStyle.swift */; };
|
||||
1C5190C42A589CAC00885849 /* InfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C5190C32A589CAC00885849 /* InfoView.swift */; };
|
||||
1C5190C62A589CC100885849 /* ActionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C5190C52A589CC100885849 /* ActionsView.swift */; };
|
||||
@@ -126,6 +128,7 @@
|
||||
1C485C862A4915C400A6F896 /* CreateWorkoutItemPickerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateWorkoutItemPickerView.swift; sourceTree = "<group>"; };
|
||||
1C485C892A492BB400A6F896 /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = "<group>"; };
|
||||
1C485C8B2A49D65600A6F896 /* WorkoutHistoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkoutHistoryView.swift; sourceTree = "<group>"; };
|
||||
1C4AFF142A60F25E0027710B /* ThotStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThotStyle.swift; sourceTree = "<group>"; };
|
||||
1C5190C12A57CA5F00885849 /* OvalTextFieldStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OvalTextFieldStyle.swift; sourceTree = "<group>"; };
|
||||
1C5190C32A589CAC00885849 /* InfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoView.swift; sourceTree = "<group>"; };
|
||||
1C5190C52A589CC100885849 /* ActionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionsView.swift; sourceTree = "<group>"; };
|
||||
@@ -323,6 +326,7 @@
|
||||
1C5190C12A57CA5F00885849 /* OvalTextFieldStyle.swift */,
|
||||
1CAF4D942A52180600B00E50 /* PlanWorkoutView.swift */,
|
||||
1C31C8862A55B2CC00350540 /* PlayerUIView.swift */,
|
||||
1C4AFF142A60F25E0027710B /* ThotStyle.swift */,
|
||||
1C485C8B2A49D65600A6F896 /* WorkoutHistoryView.swift */,
|
||||
1CF65A8B2A44B7590042FFBD /* AccountView */,
|
||||
1CF65A8A2A44B74D0042FFBD /* AddExercise */,
|
||||
@@ -601,6 +605,7 @@
|
||||
1CAF4D952A52180600B00E50 /* PlanWorkoutView.swift in Sources */,
|
||||
1C5190C62A589CC100885849 /* ActionsView.swift in Sources */,
|
||||
1CF65A5B2A3BF4BE0042FFBD /* Equipment.swift in Sources */,
|
||||
1C4AFF152A60F25F0027710B /* ThotStyle.swift in Sources */,
|
||||
1C5190C82A589CDA00885849 /* CurrentWorkoutElapsedTimeView.swift in Sources */,
|
||||
1CF65A452A39FB550042FFBD /* Exercise.swift in Sources */,
|
||||
1CF65A612A3BF6020042FFBD /* AddExerciseView.swift in Sources */,
|
||||
@@ -616,6 +621,7 @@
|
||||
1CF65A962A452D270042FFBD /* Werkout_watchApp.swift in Sources */,
|
||||
1CF65AA92A452D9C0042FFBD /* Workout.swift in Sources */,
|
||||
1CF65AA62A452D9C0042FFBD /* Equipment.swift in Sources */,
|
||||
1C4AFF162A60F27E0027710B /* ThotStyle.swift in Sources */,
|
||||
1CF65AB12A452E1A0042FFBD /* BridgeModule.swift in Sources */,
|
||||
1CF65AAA2A452D9C0042FFBD /* RegisteredUser.swift in Sources */,
|
||||
1CF65AB62A4532940042FFBD /* WatchMainViewModel.swift in Sources */,
|
||||
|
||||
@@ -26,22 +26,33 @@ struct ExerciseElement: Codable, Equatable {
|
||||
}
|
||||
|
||||
extension ExerciseElement {
|
||||
func videoURL(nsfw: Bool) -> URL? {
|
||||
var _url: URL?
|
||||
func videoURL(thotStyle: ThotStyle) -> URL? {
|
||||
var urlString: String?
|
||||
|
||||
if nsfw {
|
||||
let viddd = exercise.nsfwVideoURL
|
||||
if let url = URL(string: BaseURLs.currentBaseURL + viddd) {
|
||||
_url = url
|
||||
switch thotStyle {
|
||||
case .always:
|
||||
urlString = exercise.nsfwVideoURL
|
||||
case .never:
|
||||
urlString = exercise.videoURL
|
||||
case .recovery:
|
||||
if self.exercise.name.lowercased() == "recover" {
|
||||
urlString = exercise.nsfwVideoURL
|
||||
} else {
|
||||
urlString = exercise.videoURL
|
||||
}
|
||||
} else {
|
||||
let viddd = exercise.videoURL
|
||||
if let url = URL(string: BaseURLs.currentBaseURL + viddd) {
|
||||
_url = url
|
||||
case .random:
|
||||
if Bool.random() {
|
||||
urlString = exercise.nsfwVideoURL
|
||||
} else {
|
||||
urlString = exercise.videoURL
|
||||
}
|
||||
}
|
||||
|
||||
return _url
|
||||
if let urlString = urlString,
|
||||
let url = URL(string: BaseURLs.currentBaseURL + urlString) {
|
||||
return url
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,21 +95,32 @@ struct ExerciseExercise: Codable, Hashable, Identifiable {
|
||||
}
|
||||
|
||||
extension ExerciseExercise {
|
||||
func videoURL(nsfw: Bool) -> URL? {
|
||||
var _url: URL?
|
||||
func videoURL(thotStyle: ThotStyle) -> URL? {
|
||||
var urlString: String?
|
||||
|
||||
if nsfw {
|
||||
let viddd = nsfwVideoURL
|
||||
if let url = URL(string: BaseURLs.currentBaseURL + viddd) {
|
||||
_url = url
|
||||
switch thotStyle {
|
||||
case .always:
|
||||
urlString = nsfwVideoURL
|
||||
case .never:
|
||||
urlString = videoURL
|
||||
case .recovery:
|
||||
if self.name.lowercased() == "recovery" {
|
||||
urlString = nsfwVideoURL
|
||||
} else {
|
||||
urlString = videoURL
|
||||
}
|
||||
} else {
|
||||
let viddd = videoURL
|
||||
if let url = URL(string: BaseURLs.currentBaseURL + viddd) {
|
||||
_url = url
|
||||
case .random:
|
||||
if Bool.random() {
|
||||
urlString = nsfwVideoURL
|
||||
} else {
|
||||
urlString = videoURL
|
||||
}
|
||||
}
|
||||
|
||||
return _url
|
||||
if let urlString = urlString,
|
||||
let url = URL(string: BaseURLs.currentBaseURL + urlString) {
|
||||
return url
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ class BridgeModule: NSObject, ObservableObject {
|
||||
if currentExerciseTimeLeft == 0 {
|
||||
playFinished()
|
||||
} else {
|
||||
if currentExerciseTimeLeft <= 4 {
|
||||
if currentExerciseTimeLeft <= 3 {
|
||||
playBeep()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ struct AccountView: View {
|
||||
@State var completedWorkouts: [CompletedWorkout]?
|
||||
@ObservedObject var userStore = UserStore.shared
|
||||
@State var showCompletedWorkouts: Bool = false
|
||||
@AppStorage("showNSFWVideos") private var showNSFWVideos = false
|
||||
@AppStorage("thotStyle") private var thotStyle: ThotStyle = .never
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
@@ -62,7 +62,15 @@ struct AccountView: View {
|
||||
}
|
||||
}
|
||||
Divider()
|
||||
Toggle("Show NSFW Videos", isOn: $showNSFWVideos)
|
||||
|
||||
Picker("THOT Style:", selection: $thotStyle) {
|
||||
ForEach(ThotStyle.allCases, id: \.self) { style in
|
||||
Text(style.stringValue())
|
||||
.tag(thotStyle.rawValue)
|
||||
}
|
||||
}
|
||||
.pickerStyle(.segmented)
|
||||
|
||||
Spacer()
|
||||
|
||||
Button("Logout", action: {
|
||||
|
||||
@@ -16,47 +16,54 @@ struct CompletedWorkoutView: View {
|
||||
@State var difficulty: Float = 0
|
||||
@State var notes: String = ""
|
||||
let completedWorkoutDismissed: ((Bool) -> Void)?
|
||||
@State var isUploading: Bool = false
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
topViews()
|
||||
|
||||
Divider()
|
||||
|
||||
HStack {
|
||||
calsBurned()
|
||||
.frame(maxWidth: .infinity)
|
||||
|
||||
heartRates()
|
||||
.frame(maxWidth: .infinity)
|
||||
ZStack {
|
||||
if isUploading {
|
||||
ProgressView("Uploading")
|
||||
}
|
||||
|
||||
rateWorkout()
|
||||
.frame(maxHeight: 88)
|
||||
|
||||
Divider()
|
||||
|
||||
TextField("Notes", text: $notes)
|
||||
.frame(height: 55)
|
||||
.textFieldStyle(PlainTextFieldStyle())
|
||||
.padding([.horizontal], 4)
|
||||
.overlay(RoundedRectangle(cornerRadius: 16).stroke(Color(uiColor: .clear))).background(Color(uiColor: .init(red: 200/255, green: 200/255, blue: 200/255, alpha: 0.2)))
|
||||
VStack {
|
||||
topViews()
|
||||
|
||||
Divider()
|
||||
|
||||
HStack {
|
||||
calsBurned()
|
||||
.frame(maxWidth: .infinity)
|
||||
|
||||
heartRates()
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
|
||||
rateWorkout()
|
||||
.frame(maxHeight: 88)
|
||||
|
||||
Divider()
|
||||
|
||||
TextField("Notes", text: $notes)
|
||||
.frame(height: 55)
|
||||
.textFieldStyle(PlainTextFieldStyle())
|
||||
.padding([.horizontal], 4)
|
||||
.overlay(RoundedRectangle(cornerRadius: 16).stroke(Color(uiColor: .clear))).background(Color(uiColor: .init(red: 200/255, green: 200/255, blue: 200/255, alpha: 0.2)))
|
||||
.cornerRadius(8)
|
||||
|
||||
Spacer()
|
||||
|
||||
Button("Upload", action: {
|
||||
isUploading = true
|
||||
upload(postBody: postData)
|
||||
})
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
.frame(height: 44)
|
||||
.foregroundColor(.blue)
|
||||
.background(.yellow)
|
||||
.cornerRadius(8)
|
||||
|
||||
Spacer()
|
||||
|
||||
Button("Upload", action: {
|
||||
upload(postBody: postData)
|
||||
})
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
.frame(height: 44)
|
||||
.foregroundColor(.blue)
|
||||
.background(.yellow)
|
||||
.cornerRadius(8)
|
||||
.padding()
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding()
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
.padding([.leading, .trailing])
|
||||
}
|
||||
.padding([.leading, .trailing])
|
||||
}
|
||||
|
||||
func topViews() -> some View {
|
||||
|
||||
@@ -14,39 +14,41 @@ struct CreateExerciseActionsView: View {
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
if workoutExercise.exercise.isReps {
|
||||
HStack {
|
||||
HStack {
|
||||
VStack {
|
||||
VStack {
|
||||
HStack {
|
||||
Text("Reps: ")
|
||||
Text("\(workoutExercise.reps)")
|
||||
}
|
||||
Stepper("", onIncrement: {
|
||||
workoutExercise.increaseReps()
|
||||
}, onDecrement: {
|
||||
workoutExercise.decreaseReps()
|
||||
})
|
||||
.labelsHidden()
|
||||
Text("Reps: ")
|
||||
Text("\(workoutExercise.reps)")
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
Divider()
|
||||
VStack{
|
||||
HStack {
|
||||
Text("Weight: ")
|
||||
Text("\(workoutExercise.weight)")
|
||||
}
|
||||
Stepper("", onIncrement: {
|
||||
workoutExercise.increaseWeight()
|
||||
}, onDecrement: {
|
||||
workoutExercise.decreaseWeight()
|
||||
})
|
||||
.labelsHidden()
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
Stepper("", onIncrement: {
|
||||
workoutExercise.increaseReps()
|
||||
}, onDecrement: {
|
||||
workoutExercise.decreaseReps()
|
||||
})
|
||||
.labelsHidden()
|
||||
}
|
||||
} else if workoutExercise.exercise.isDuration {
|
||||
.frame(maxWidth: .infinity)
|
||||
|
||||
Divider()
|
||||
|
||||
VStack{
|
||||
HStack {
|
||||
VStack {
|
||||
Text("Weight: ")
|
||||
Text("\(workoutExercise.weight)")
|
||||
}
|
||||
Stepper("", onIncrement: {
|
||||
workoutExercise.increaseWeight()
|
||||
}, onDecrement: {
|
||||
workoutExercise.decreaseWeight()
|
||||
})
|
||||
.labelsHidden()
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
|
||||
Divider()
|
||||
|
||||
VStack{
|
||||
VStack {
|
||||
Text("Duration: ")
|
||||
Text("\(workoutExercise.duration)")
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ class CreateWorkoutExercise: ObservableObject, Identifiable {
|
||||
|
||||
func increaseDuration() {
|
||||
self.duration += 15
|
||||
self.reps = 0
|
||||
}
|
||||
|
||||
func decreaseDuration() {
|
||||
@@ -58,7 +59,7 @@ class CreateWorkoutExercise: ObservableObject, Identifiable {
|
||||
class CreateWorkoutSuperSet: ObservableObject, Identifiable {
|
||||
let id = UUID()
|
||||
@Published var exercises = [CreateWorkoutExercise]()
|
||||
@Published var numberOfRounds = 1
|
||||
@Published var numberOfRounds = 0
|
||||
|
||||
func increaseNumberOfRounds() {
|
||||
self.numberOfRounds += 1
|
||||
@@ -66,8 +67,8 @@ class CreateWorkoutSuperSet: ObservableObject, Identifiable {
|
||||
|
||||
func decreaseNumberOfRounds() {
|
||||
self.numberOfRounds -= 1
|
||||
if self.numberOfRounds < 1 {
|
||||
self.numberOfRounds = 1
|
||||
if self.numberOfRounds < 0 {
|
||||
self.numberOfRounds = 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,11 +98,30 @@ class WorkoutViewModel: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
func showRoundsError() {
|
||||
|
||||
}
|
||||
|
||||
func showNoDurationOrReps() {
|
||||
|
||||
}
|
||||
|
||||
func uploadWorkout() {
|
||||
var exercises = [[String: Any]]()
|
||||
superSets.forEach({ superset in
|
||||
if superset.numberOfRounds == 0 {
|
||||
showRoundsError()
|
||||
return
|
||||
}
|
||||
|
||||
for _ in 0 ..< superset.numberOfRounds {
|
||||
for exercise in superset.exercises {
|
||||
|
||||
if exercise.reps == 0 && exercise.duration == 0 {
|
||||
showNoDurationOrReps()
|
||||
return
|
||||
}
|
||||
|
||||
let item = ["id": exercise.exercise.id,
|
||||
"reps": exercise.reps,
|
||||
"weight": exercise.weight,
|
||||
|
||||
@@ -57,6 +57,7 @@ struct CreateWorkoutMainView: View {
|
||||
viewModel.objectWillChange.send()
|
||||
})
|
||||
Text("\(superset.wrappedValue.numberOfRounds)")
|
||||
.foregroundColor(superset.numberOfRounds.wrappedValue > 0 ? .black : .red)
|
||||
}
|
||||
|
||||
CreateWorkoutSupersetActionsView(workoutSuperSet: superset.wrappedValue,
|
||||
|
||||
@@ -11,7 +11,7 @@ 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
|
||||
@AppStorage("thotStyle") private var thotStyle: ThotStyle = .never
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
@@ -54,7 +54,7 @@ struct ExternalWorkoutDetailView: View {
|
||||
}
|
||||
}
|
||||
.onChange(of: bridgeModule.currentExercise, perform: { newValue in
|
||||
if let videoURL = newValue?.videoURL(nsfw: showNSFWVideos) {
|
||||
if let videoURL = newValue?.videoURL(thotStyle: thotStyle) {
|
||||
avPlayer = AVPlayer(url: videoURL)
|
||||
avPlayer.play()
|
||||
}
|
||||
|
||||
28
Werkout_ios/Views/ThotStyle.swift
Normal file
28
Werkout_ios/Views/ThotStyle.swift
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// ThotStyle.swift
|
||||
// Werkout_ios
|
||||
//
|
||||
// Created by Trey Tartt on 7/13/23.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum ThotStyle: Int, CaseIterable {
|
||||
case always = 1
|
||||
case never = 2
|
||||
case recovery = 3
|
||||
case random = 4
|
||||
|
||||
func stringValue() -> String {
|
||||
switch(self) {
|
||||
case .always:
|
||||
return "Always"
|
||||
case .never:
|
||||
return "Never"
|
||||
case .recovery:
|
||||
return "Recovery"
|
||||
case .random:
|
||||
return "Random"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,14 @@ import SwiftUI
|
||||
import AVKit
|
||||
|
||||
struct ExerciseListView: View {
|
||||
@AppStorage("showNSFWVideos") private var showNSFWVideos = false
|
||||
@AppStorage("thotStyle") private var thotStyle: ThotStyle = .never
|
||||
@ObservedObject var bridgeModule = BridgeModule.shared
|
||||
var workout: Workout
|
||||
@State var avPlayer = AVPlayer(url: URL(string: "https://dev.werkout.fitness/media/exercise_videos/2_Dumbbell_Lateral_Lunges.mp4")!)
|
||||
|
||||
@State var videoExercise: ExerciseExercise? {
|
||||
didSet {
|
||||
if let videoURL = self.videoExercise?.videoURL(nsfw: showNSFWVideos) {
|
||||
if let videoURL = self.videoExercise?.videoURL(thotStyle: thotStyle) {
|
||||
avPlayer = AVPlayer(url: videoURL)
|
||||
avPlayer.play()
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ struct WorkoutDetailView: View {
|
||||
|
||||
@StateObject var bridgeModule = BridgeModule.shared
|
||||
@Environment(\.dismiss) var dismiss
|
||||
@AppStorage("showNSFWVideos") private var showNSFWVideos = false
|
||||
@AppStorage("thotStyle") private var thotStyle: ThotStyle = .never
|
||||
|
||||
enum Sheet: Identifiable {
|
||||
case completedWorkout([String: Any])
|
||||
@@ -80,13 +80,13 @@ struct WorkoutDetailView: View {
|
||||
}
|
||||
}
|
||||
.onChange(of: bridgeModule.currentExercise, perform: { newValue in
|
||||
if let videoURL = newValue?.videoURL(nsfw: showNSFWVideos) {
|
||||
if let videoURL = newValue?.videoURL(thotStyle: thotStyle) {
|
||||
avPlayer = AVPlayer(url: videoURL)
|
||||
avPlayer.play()
|
||||
}
|
||||
})
|
||||
.onAppear{
|
||||
if let videoURL = bridgeModule.currentExercise?.videoURL(nsfw: showNSFWVideos) {
|
||||
if let videoURL = bridgeModule.currentExercise?.videoURL(thotStyle: thotStyle) {
|
||||
avPlayer = AVPlayer(url: videoURL)
|
||||
avPlayer.play()
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ struct WorkoutHistoryView: View {
|
||||
|
||||
let completedWorkouts: [CompletedWorkout]
|
||||
|
||||
@State private var selectedPlannedWorkout: Workout?
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
ForEach(completedWorkouts, id:\.self.id) { completedWorkout in
|
||||
@@ -48,9 +50,6 @@ struct WorkoutHistoryView: View {
|
||||
}
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
|
||||
}
|
||||
Text(completedWorkout.workout.name)
|
||||
.font(.title3)
|
||||
|
||||
@@ -71,9 +70,18 @@ struct WorkoutHistoryView: View {
|
||||
}
|
||||
}
|
||||
.padding(.leading)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture {
|
||||
selectedPlannedWorkout = completedWorkout.workout
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
.sheet(item: $selectedPlannedWorkout) { item in
|
||||
let viewModel = WorkoutDetailViewModel(workout: item)
|
||||
WorkoutDetailView(viewModel: viewModel, showAddToCalendar: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user