add apple tv app

This commit is contained in:
Trey t
2024-06-18 12:03:56 -05:00
parent addeca4ead
commit 7d2b6b3e6e
134 changed files with 869 additions and 37 deletions

View File

@@ -0,0 +1,110 @@
//
// ActionsView.swift
// Werkout_ios
//
// Created by Trey Tartt on 7/7/23.
//
import SwiftUI
struct ActionsView: View {
@ObservedObject var bridgeModule = BridgeModule.shared
var completedWorkout: (() -> Void)?
var planWorkout: ((Workout) -> Void)?
var workout: Workout
@Environment(\.dismiss) var dismiss
var showAddToCalendar: Bool
var startWorkoutAction: (() -> Void)
var body: some View {
HStack {
if bridgeModule.isInWorkout == false {
Button(action: {
bridgeModule.resetCurrentWorkout()
dismiss()
}, label: {
Image(systemName: "xmark.octagon.fill")
.font(.title)
.frame(maxWidth: .infinity, maxHeight: .infinity)
})
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(.red)
.foregroundColor(.white)
if showAddToCalendar {
Button(action: {
planWorkout?(workout)
}, label: {
Image(systemName: "calendar.badge.plus")
.font(.title)
.frame(maxWidth: .infinity, maxHeight: .infinity)
})
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(.blue)
.foregroundColor(.white)
}
Button(action: {
startWorkoutAction()
}, label: {
Image(systemName: "arrowtriangle.forward.fill")
.font(.title)
.frame(maxWidth: .infinity, maxHeight: .infinity)
})
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(.green)
.foregroundColor(.white)
} else {
Button(action: {
nextExercise()
}, label: {
Image(systemName: "arrow.forward")
.font(.title)
.frame(maxWidth: .infinity, maxHeight: .infinity)
})
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(.green)
.foregroundColor(.white)
Button(action: {
bridgeModule.pauseWorkout()
}, label: {
bridgeModule.isPaused ?
Image(systemName: "play.circle.fill")
.font(.title)
.frame(maxWidth: .infinity, maxHeight: .infinity)
:
Image(systemName: "pause.circle.fill")
.font(.title)
.frame(maxWidth: .infinity, maxHeight: .infinity)
})
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(bridgeModule.isPaused ? .mint : .yellow)
.foregroundColor(.white)
Button(action: {
completedWorkout?()
}, label: {
Image(systemName: "checkmark")
.font(.title)
.frame(maxWidth: .infinity, maxHeight: .infinity)
})
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(.blue)
.foregroundColor(.white)
}
}
}
func nextExercise() {
bridgeModule.nextExercise()
}
}
struct ActionsView_Previews: PreviewProvider {
static var previews: some View {
ActionsView(workout: PreviewData.workout(), showAddToCalendar: true, startWorkoutAction: {})
}
}

View File

@@ -0,0 +1,56 @@
//
// AllEquipmentview.swift
// Werkout_ios
//
// Created by Trey Tartt on 6/16/24.
//
import SwiftUI
struct AllEquipmentView: View {
@Binding var selectedEquipment: [Equipment]
@State var createWorkoutItemPickerViewModel: CreateWorkoutItemPickerViewModel?
var body: some View {
VStack {
if let _ = DataStore.shared.allEquipment {
Text("Select Equipment")
.foregroundColor(.cyan)
Text("\(selectedEquipment.count) Selected")
}
}
.onTapGesture {
if let equipment = DataStore.shared.allEquipment {
var createWorkoutItemPickerModels = [CreateWorkoutItemPickerModel]()
equipment.forEach({
let model = CreateWorkoutItemPickerModel(id: $0.id,
name: $0.name.lowercased())
createWorkoutItemPickerModels.append(model)
})
createWorkoutItemPickerModels = createWorkoutItemPickerModels.sorted(by: {
$0.name < $1.name
})
let selectedIds = selectedEquipment.map { $0.id }
createWorkoutItemPickerViewModel = CreateWorkoutItemPickerViewModel(allValues: createWorkoutItemPickerModels, selectedIds: selectedIds)
}
}
.sheet(item: $createWorkoutItemPickerViewModel) { item in
CreateWorkoutItemPickerView(viewModel: item, completed: { selectedids in
if let equipment = DataStore.shared.allEquipment {
selectedEquipment.removeAll()
for id in selectedids {
if let equipment = equipment.first(where: {
$0.id == id
}) {
selectedEquipment.append(equipment)
}
}
}
})
}
}
}
//#Preview {
// AllEquipmentview()
//}

View File

@@ -0,0 +1,92 @@
//
// AllExerciseView.swift
// Werkout_ios
//
// Created by Trey Tartt on 6/16/24.
//
import SwiftUI
import AVKit
struct AllExerciseView: View {
@Environment(\.dismiss) var dismiss
@State var searchString: String = ""
@Binding var filteredExercises: [Exercise]
var selectedExercise: ((Exercise) -> Void)
@State var avPlayer = AVPlayer(url: URL(string: "https://dev.werkout.fitness/media/exercise_videos/2_Dumbbell_Lateral_Lunges.mp4")!)
@State var videoExercise: Exercise? {
didSet {
if let viddd = self.videoExercise?.videoURL,
let url = URL(string: BaseURLs.currentBaseURL + viddd) {
self.avPlayer = AVPlayer(url: url)
}
}
}
var body: some View {
VStack {
TextField("Filter", text: $searchString)
.padding()
List() {
ForEach(filteredExercises, id: \.self) { exercise in
if searchString.isEmpty || (exercise.name.lowercased().contains(searchString.lowercased()) || (exercise.muscleGroups ?? "").lowercased().contains(searchString.lowercased())) {
HStack {
VStack {
Text(exercise.name)
.frame(maxWidth: .infinity, alignment: .leading)
if exercise.side != nil && !exercise.side!.isEmpty {
Text(exercise.side!)
.font(.footnote)
.frame(maxWidth: .infinity, alignment: .leading)
}
if exercise.equipmentRequired != nil && !exercise.equipmentRequired!.isEmpty {
Text(exercise.spacedEquipmentRequired)
.font(.footnote)
.frame(maxWidth: .infinity, alignment: .leading)
}
if exercise.muscleGroups != nil && !exercise.muscleGroups!.isEmpty {
Text(exercise.spacedMuscleGroups)
.font(.footnote)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
.contentShape(Rectangle())
.onTapGesture {
selectedExercise(exercise)
dismiss()
}
Button(action: {
videoExercise = exercise
}) {
ZStack {
Circle()
.fill(.blue)
.frame(width: 33, height: 33)
Image(systemName: "video.fill")
.frame(width: 33, height: 33)
.foregroundColor(.white )
}
}
.frame(width: 33, height: 33)
}
}
}
}
}
.sheet(item: $videoExercise) { exercise in
PlayerView(player: $avPlayer)
.onAppear{
avPlayer.play()
}
}
}
}
//
//#Preview {
// AllExerciseView()
//}

View File

@@ -0,0 +1,66 @@
//
// AllMusclesView.swift
// Werkout_ios
//
// Created by Trey Tartt on 6/16/24.
//
import SwiftUI
struct AllMusclesView: View {
@Binding var selectedMuscles: [Muscle]
@State var createWorkoutItemPickerViewModel: CreateWorkoutItemPickerViewModel?
var body: some View {
VStack {
if let _ = DataStore.shared.allMuscles {
Text("Select Muscles")
.foregroundColor(.cyan)
Text("\(selectedMuscles.count) Selected")
}
}
.onTapGesture {
if let muscles = DataStore.shared.allMuscles {
var createWorkoutItemPickerModels = [CreateWorkoutItemPickerModel]()
muscles.forEach({
let model = CreateWorkoutItemPickerModel(id: $0.id, name: $0.name.lowercased())
createWorkoutItemPickerModels.append(model)
})
createWorkoutItemPickerModels = createWorkoutItemPickerModels.sorted(by: {
$0.name < $1.name
})
let selectedIds = selectedMuscles.map { $0.id }
createWorkoutItemPickerViewModel = CreateWorkoutItemPickerViewModel(allValues: createWorkoutItemPickerModels, selectedIds: selectedIds)
}
}
.onAppear{
if #function.hasPrefix("__preview") {
DataStore.shared.setupFakeData()
}
guard let _ = DataStore.shared.allExercise,
let muscles = DataStore.shared.allMuscles,
let _ = DataStore.shared.allEquipment else {
return
}
selectedMuscles = muscles
}
.sheet(item: $createWorkoutItemPickerViewModel) { item in
CreateWorkoutItemPickerView(viewModel: item, completed: { selectedids in
if let muscles = DataStore.shared.allMuscles {
selectedMuscles.removeAll()
for id in selectedids {
if let muscle = muscles.first(where: {
$0.id == id
}) {
selectedMuscles.append(muscle)
}
}
}
})
}
}
}
//#Preview {
// AllMusclesView()
//}

View File

@@ -0,0 +1,37 @@
//
// AllWorkoutPickerView.swift
// Werkout_ios
//
// Created by Trey Tartt on 7/7/23.
//
import SwiftUI
struct AllWorkoutPickerView: View {
var mainViews: [MainViewTypes]
@Binding var selectedSegment: MainViewTypes
@StateObject var bridgeModule = BridgeModule.shared
var showCurrentWorkout: (() -> Void)
var body: some View {
HStack {
Picker("", selection: $selectedSegment) {
ForEach(mainViews, id: \.self) { viewType in
Text(viewType.title)
}
}
.pickerStyle(.segmented)
.padding([.top, .leading, .trailing])
if bridgeModule.isInWorkout {
Button(action: {
showCurrentWorkout()
}, label: {
Image(systemName: "figure.strengthtraining.traditional")
.padding(.trailing)
})
.tint(Color("appColor"))
}
}
}
}

View File

@@ -0,0 +1,71 @@
//
// CompletedWorkoutsView.swift
// Werkout_ios
//
// Created by Trey Tartt on 6/16/24.
//
import SwiftUI
struct CompletedWorkoutsView: View {
@State var completedWorkouts: [CompletedWorkout]?
@State var showCompletedWorkouts: Bool = false
var body: some View {
VStack(alignment: .leading) {
if let completedWorkouts = completedWorkouts {
Divider()
Text("Workout History:")
HStack {
Text("Number of workouts:")
Text("\(completedWorkouts.count)")
}
if let lastWorkout = completedWorkouts.last {
HStack {
Text("Last workout:")
Text(lastWorkout.workoutStartTime)
}
Button("View All Workouts", action: {
showCompletedWorkouts = true
})
.frame(maxWidth: .infinity, alignment: .center)
.frame(height: 44)
.foregroundColor(.blue)
.background(.yellow)
.cornerRadius(8)
.padding()
.frame(maxWidth: .infinity)
}
} else {
Text("loading completed workouts")
}
}
.onAppear{
fetchCompletedWorkouts()
}
.sheet(isPresented: $showCompletedWorkouts) {
if let completedWorkouts = completedWorkouts {
WorkoutHistoryView(completedWorkouts: completedWorkouts)
}
}
}
func fetchCompletedWorkouts() {
CompletedWorkoutFetchable().fetch(completion: { result in
switch result {
case .success(let model):
completedWorkouts = model
case .failure(let failure):
fatalError(failure.localizedDescription)
}
})
}
}
#Preview {
CompletedWorkoutsView()
}

View File

@@ -0,0 +1,30 @@
//
// CountdownView.swift
// Werkout_ios
//
// Created by Trey Tartt on 7/7/23.
//
import SwiftUI
struct CountdownView: View {
@StateObject var bridgeModule = BridgeModule.shared
var body: some View {
if let duration = bridgeModule.currentExerciseInfo.currentExercise?.duration,
duration > 0 {
HStack {
if bridgeModule.currentExerciseTimeLeft >= 0 && duration > bridgeModule.currentExerciseTimeLeft {
ProgressView(value: Float(bridgeModule.currentExerciseTimeLeft), total: Float(duration))
.tint(Color("appColor"))
}
}
}
}
}
struct CountdownView_Previews: PreviewProvider {
static var previews: some View {
CountdownView()
}
}

View File

@@ -0,0 +1,81 @@
//
// ExtCountdownView.swift
// Werkout_ios
//
// Created by Trey Tartt on 6/17/24.
//
import SwiftUI
struct ExtCountdownView: View {
@StateObject var bridgeModule = BridgeModule.shared
var body: some View {
GeometryReader { metrics in
VStack {
if let currenExercise = bridgeModule.currentExerciseInfo.currentExercise {
HStack {
Text(currenExercise.exercise.extName)
.font(.system(size: 200))
.scaledToFit()
.minimumScaleFactor(0.01)
.lineLimit(1)
.frame(maxWidth: .infinity, alignment: .leading)
if bridgeModule.currentWorkoutRunTimeInSeconds > -1 {
Text("\(Double(bridgeModule.currentWorkoutRunTimeInSeconds).asString(style: .positional))")
.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,
duration > 0 {
ProgressView(value: Float(bridgeModule.currentExerciseTimeLeft), total: Float(duration))
.scaleEffect(x: 1, y: 6, anchor: .center)
Text("\(bridgeModule.currentExerciseTimeLeft)")
.font(Font.system(size: 100))
.scaledToFit()
.minimumScaleFactor(0.01)
.lineLimit(1)
.padding(.leading)
.padding(.trailing, 100)
}
if let reps = currenExercise.reps,
reps > 0 {
Text(" X \(reps)")
.font(Font.system(size: 100))
.scaledToFit()
.minimumScaleFactor(0.01)
.lineLimit(1)
.frame(maxWidth: .infinity, alignment: .leading)
}
if let weight = currenExercise.weight,
weight > 0 {
Text(" @ \(weight)")
.font(Font.system(size: 100))
.scaledToFit()
.minimumScaleFactor(0.01)
.lineLimit(1)
.padding(.trailing, 100)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
.frame(height: metrics.size.height * 0.5)
}
}
}
}
}
#Preview {
ExtCountdownView()
}

View File

@@ -0,0 +1,76 @@
//
// ExtExerciseList.swift
// Werkout_ios
//
// Created by Trey Tartt on 6/17/24.
//
import SwiftUI
struct ExtExerciseList: View {
var workout: Workout
var allSupersetExecerciseIndex: Int
var body: some View {
if let allSupersetExecercise = workout.allSupersetExecercise {
ZStack {
ScrollViewReader { proxy in
List() {
ForEach(allSupersetExecercise.indices, id: \.self) { supersetExecerciseIdx in
let supersetExecercise = allSupersetExecercise[supersetExecerciseIdx]
HStack {
if supersetExecerciseIdx == allSupersetExecerciseIndex {
Image(systemName: "figure.run")
.foregroundColor(Color("appColor"))
.font(Font.system(size: 55))
.minimumScaleFactor(0.01)
.lineLimit(1)
}
Text(supersetExecercise.exercise.name)
.font(Font.system(size: 55))
.minimumScaleFactor(0.01)
.lineLimit(3)
.padding()
Spacer()
}
.id(supersetExecerciseIdx)
}
}
.onChange(of: allSupersetExecerciseIndex, perform: { newValue in
withAnimation {
proxy.scrollTo(allSupersetExecerciseIndex, anchor: .top)
}
})
}
VStack {
Text("\(allSupersetExecerciseIndex+1)/\(workout.allSupersetExecercise?.count ?? 0)")
.font(Font.system(size: 55))
.minimumScaleFactor(0.01)
.lineLimit(1)
.padding()
.bold()
.foregroundColor(.white)
.background(
Capsule()
.strokeBorder(Color.black, lineWidth: 0.8)
.background(Color(uiColor: UIColor(red: 148/255,
green: 0,
blue: 211/255,
alpha: 0.5)))
.clipped()
)
.clipShape(Capsule())
Spacer()
}
}
}
}
}
//#Preview {
// ExtExerciseList()
//}

View File

@@ -0,0 +1,42 @@
//
// InfoView.swift
// Werkout_ios
//
// Created by Trey Tartt on 7/7/23.
//
import SwiftUI
struct InfoView: View {
@ObservedObject var bridgeModule = BridgeModule.shared
var workout: Workout
var body: some View {
VStack {
Text(workout.name)
.frame(maxWidth: .infinity, alignment: .leading)
.font(.title3)
.padding()
if let desc = workout.description {
Text(desc)
.frame(maxWidth: .infinity, alignment: .leading)
.font(.body)
.padding([.leading, .trailing])
}
if let estimatedTime = workout.estimatedTime {
Text(estimatedTime.asString(style: .abbreviated))
.frame(maxWidth: .infinity, alignment: .leading)
.font(.body)
.padding([.leading, .trailing])
}
}
}
}
struct InfoView_Previews: PreviewProvider {
static var previews: some View {
InfoView(workout: PreviewData.workout())
}
}

View File

@@ -0,0 +1,43 @@
//
// Logoutview.swift
// Werkout_ios
//
// Created by Trey Tartt on 6/16/24.
//
import SwiftUI
struct Logoutview: View {
@ObservedObject var userStore = UserStore.shared
var body: some View {
HStack {
Button("Logout", action: {
userStore.logout()
})
.frame(maxWidth: .infinity, alignment: .center)
.frame(height: 44)
.foregroundColor(.white)
.background(.red)
.cornerRadius(8)
.padding()
.frame(maxWidth: .infinity)
Button(action: {
userStore.refreshUserData()
}, label: {
Image(systemName: "arrow.triangle.2.circlepath")
})
.frame(width: 44, height: 44)
.foregroundColor(.white)
.background(.green)
.cornerRadius(8)
.padding()
.frame(maxWidth: .infinity)
}
}
}
#Preview {
Logoutview()
}

View File

@@ -0,0 +1,34 @@
//
// NameView.swift
// Werkout_ios
//
// Created by Trey Tartt on 6/16/24.
//
import SwiftUI
struct NameView: View {
@ObservedObject var userStore = UserStore.shared
var body: some View {
if let registeredUser = userStore.registeredUser {
if let nickName = registeredUser.nickName {
Text(nickName)
.font(.title)
}
HStack {
Text(registeredUser.firstName ?? "-")
Text(registeredUser.lastName ?? "-")
}
if let email = registeredUser.email {
Text(email)
}
}
}
}
#Preview {
NameView()
}

View File

@@ -0,0 +1,18 @@
//
// OvalTextFieldStyle.swift
// Werkout_ios
//
// Created by Trey Tartt on 7/6/23.
//
import SwiftUI
struct OvalTextFieldStyle: TextFieldStyle {
func _body(configuration: TextField<Self._Label>) -> some View {
configuration
.padding(10)
.background(LinearGradient(gradient: Gradient(colors: [Color(uiColor: .secondarySystemBackground), Color(uiColor: .secondarySystemBackground)]), startPoint: .topLeading, endPoint: .bottomTrailing))
.cornerRadius(20)
.shadow(color: Color(red: 120/255, green: 120/255, blue: 120/255, opacity: 1), radius: 5)
}
}

View File

@@ -0,0 +1,127 @@
//
// PlayerUIView.swift
// Werkout_ios
//
// Created by Trey Tartt on 7/5/23.
//
import SwiftUI
import AVKit
class PlayerUIView: UIView {
// MARK: Class Property
let playerLayer = AVPlayerLayer()
// MARK: Init
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
init(player: AVPlayer) {
super.init(frame: .zero)
self.playerSetup(player: player)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
// MARK: Life-Cycle
override func layoutSubviews() {
super.layoutSubviews()
playerLayer.frame = bounds
}
// MARK: Class Methods
private func playerSetup(player: AVPlayer) {
playerLayer.player = player
player.actionAtItemEnd = .none
layer.addSublayer(playerLayer)
self.setObserver()
}
func setObserver() {
NotificationCenter.default.removeObserver(self)
NotificationCenter.default.addObserver(self, selector: #selector(playerItemDidReachEnd(notification:)),
name: .AVPlayerItemDidPlayToEndTime,
object: playerLayer.player?.currentItem)
}
@objc func playerItemDidReachEnd(notification: Notification) {
if let playerItem = notification.object as? AVPlayerItem {
playerItem.seek(to: .zero, completionHandler: nil)
self.playerLayer.player?.play()
}
}
}
struct PlayerView: UIViewRepresentable {
@Binding var player: AVPlayer
func makeUIView(context: Context) -> PlayerUIView {
return PlayerUIView(player: player)
}
func updateUIView(_ uiView: PlayerUIView, context: UIViewRepresentableContext<PlayerView>) {
uiView.playerLayer.player = player
//Add player observer.
uiView.setObserver()
}
}
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, gender: String, defaultVideoURLStr: String?, exerciseName: String?, workout: Workout?) -> URL? {
var urlString: String?
if UserStore.shared.registeredUser?.NSFWValue ?? false {
switch thotStyle {
case .always:
urlString = DataStore.shared.randomVideoFor(gender: gender)
case .never:
urlString = defaultVideoURLStr
case .recovery:
if exerciseName?.lowercased() == "recover" {
urlString = DataStore.shared.randomVideoFor(gender: gender)
} else {
urlString = defaultVideoURLStr
}
case .random:
if Bool.random() {
urlString = DataStore.shared.randomVideoFor(gender: gender)
} else {
urlString = defaultVideoURLStr
}
case .off:
return nil
}
} else {
urlString = defaultVideoURLStr
}
if let urlString = urlString,
let url = URL(string: BaseURLs.currentBaseURL + urlString) {
return url
}
return nil
}
}

View File

@@ -0,0 +1,22 @@
//
// ShowNextUpView.swift
// Werkout_ios
//
// Created by Trey Tartt on 6/16/24.
//
import SwiftUI
struct ShowNextUpView: View {
@AppStorage(Constants.extShowNextVideo) private var extShowNextVideo: Bool = false
var body: some View {
Toggle(isOn: $extShowNextVideo, label: {
Text("Show next up video")
})
}
}
#Preview {
ShowNextUpView()
}

View File

@@ -0,0 +1,57 @@
//
// ThosPreferenceView.swift
// Werkout_ios
//
// Created by Trey Tartt on 6/16/24.
//
import SwiftUI
struct ThotPreferenceView: View {
@ObservedObject var userStore = UserStore.shared
@AppStorage(Constants.phoneThotStyle) private var phoneThotStyle: ThotStyle = .never
@AppStorage(Constants.extThotStyle) private var extThotStyle: ThotStyle = .never
@AppStorage(Constants.thotGenderOption) private var thotGenderOption: String = "female"
var body: some View {
if userStore.registeredUser?.NSFWValue ?? false {
Group {
Text("Phone THOT Style:")
Picker("Phone THOT Style:", selection: $phoneThotStyle) {
ForEach(ThotStyle.allCases, id: \.self) { style in
Text(style.stringValue())
.tag(phoneThotStyle.rawValue)
}
}
.pickerStyle(.segmented)
Divider()
Text("External THOT Style:")
Picker("External THOT Style:", selection: $extThotStyle) {
ForEach(ThotStyle.allCases, id: \.self) { style in
Text(style.stringValue())
.tag(extThotStyle.rawValue)
}
}
.pickerStyle(.segmented)
if let genderOptions = DataStore.shared.nsfwGenderOptions {
Divider()
Text("Video Gender:")
Picker("Video Gender:", selection: $thotGenderOption) {
ForEach(genderOptions, id: \.self) { option in
Text(option.capitalized)
.tag(option.lowercased())
}
}
.pickerStyle(.segmented)
}
}
}
}
}
#Preview {
ThotPreferenceView()
}

View File

@@ -0,0 +1,33 @@
//
// TitleView.swift
// Werkout_ios
//
// Created by Trey Tartt on 6/17/24.
//
import SwiftUI
struct TitleView: View {
@ObservedObject var bridgeModule = BridgeModule.shared
var body: some View {
HStack {
if let workout = bridgeModule.currentExerciseInfo.workout {
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)
}
}
}
}
#Preview {
TitleView()
}

View File

@@ -0,0 +1,71 @@
//
// WorkoutOverviewView.swift
// Werkout_ios
//
// Created by Trey Tartt on 7/9/23.
//
import SwiftUI
struct WorkoutOverviewView: View {
let workout: Workout
var body: some View {
VStack {
HStack {
VStack {
Text(workout.name)
.font(.title2)
.frame(maxWidth: .infinity, alignment: .leading)
Text(workout.description ?? "")
.frame(maxWidth: .infinity, alignment: .leading)
if let estimatedTime = workout.estimatedTime {
Text("Time: " + estimatedTime.asString(style: .abbreviated))
.frame(maxWidth: .infinity, alignment: .leading)
}
if let createdAt = workout.createdAt {
Text(createdAt, style: .date)
.font(.footnote)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
if let exerciseCount = workout.exercise_count {
VStack {
Text("\(exerciseCount)")
.font(.body.bold())
Text("exercises")
.font(.footnote)
.foregroundColor(Color(uiColor: .systemGray2))
}
}
}
if let muscles = workout.muscles,
muscles.joined(separator: ", ").count > 0{
Divider()
Text(muscles.joined(separator: ", "))
.font(.footnote)
.frame(maxWidth: .infinity, alignment: .leading)
}
if let equipment = workout.equipment,
equipment.joined(separator: ", ").count > 0 {
Divider()
Text(equipment.joined(separator: ", "))
.font(.footnote)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
.padding()
.background(Color(uiColor: .secondarySystemBackground))
.cornerRadius(15)
}
}
struct WorkoutOverviewView_Previews: PreviewProvider {
static var previews: some View {
WorkoutOverviewView(workout: PreviewData.allWorkouts()[2])
}
}