diff --git a/Workout Spinner WatchKit App/Info.plist b/Workout Spinner WatchKit App/Info.plist
index 673fa3d..1520c64 100644
--- a/Workout Spinner WatchKit App/Info.plist
+++ b/Workout Spinner WatchKit App/Info.plist
@@ -19,7 +19,7 @@
CFBundleShortVersionString
1.0
CFBundleVersion
- 283
+ 374
UISupportedInterfaceOrientations
UIInterfaceOrientationPortrait
diff --git a/Workout Spinner WatchKit Extension/Extensions/Color-extension.swift b/Workout Spinner WatchKit Extension/Extensions/Color-extension.swift
index 2592fde..8f2ff53 100644
--- a/Workout Spinner WatchKit Extension/Extensions/Color-extension.swift
+++ b/Workout Spinner WatchKit Extension/Extensions/Color-extension.swift
@@ -22,6 +22,33 @@ extension Color {
}
}
+extension Color {
+ init(hex: String) {
+ let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
+ var int: UInt64 = 0
+ Scanner(string: hex).scanHexInt64(&int)
+ let a, r, g, b: UInt64
+ switch hex.count {
+ case 3: // RGB (12-bit)
+ (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
+ case 6: // RGB (24-bit)
+ (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
+ case 8: // ARGB (32-bit)
+ (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
+ default:
+ (a, r, g, b) = (1, 1, 1, 0)
+ }
+
+ self.init(
+ .sRGB,
+ red: Double(r) / 255,
+ green: Double(g) / 255,
+ blue: Double(b) / 255,
+ opacity: Double(a) / 255
+ )
+ }
+}
+
struct CustomColors_Previews: PreviewProvider {
static var customColors: [Color] = [.workoutGreen, .darkGray, .deepRed, .deepRed2, .pastelDarkRed, .pastelDarkRed2]
@@ -38,8 +65,10 @@ struct CustomColors_Previews: PreviewProvider {
}
extension Color {
- static let workoutGreen = Color(red: 194, green: 255, blue: 60)
- static let workoutRed = Color(red: 214, green: 26, blue: 82)
+ static let workoutGreen = Color(red: 175, green: 245, blue: 58)
+ static let darkWorkoutRed = Color(red: 227, green: 2, blue: 25)
+ static let workoutRed = Color(red: 237, green: 20, blue: 66)
+ static let lightWorkoutRed = Color(red: 249, green: 39, blue: 110)
static let darkGray = Color(red: 40, green: 40, blue: 40)
static let deepRed = Color(red: 232, green: 39, blue: 39)
static let deepRed2 = Color(red: 200, green: 20, blue: 20)
diff --git a/Workout Spinner WatchKit Extension/Info.plist b/Workout Spinner WatchKit Extension/Info.plist
index 04fb8c7..e10e4e1 100644
--- a/Workout Spinner WatchKit Extension/Info.plist
+++ b/Workout Spinner WatchKit Extension/Info.plist
@@ -19,7 +19,7 @@
CFBundleShortVersionString
1.0
CFBundleVersion
- 283
+ 374
CLKComplicationPrincipalClass
$(PRODUCT_MODULE_NAME).ComplicationController
CLKComplicationSupportedFamilies
diff --git a/Workout Spinner WatchKit Extension/Models/WorkoutTracker.swift b/Workout Spinner WatchKit Extension/Models/WorkoutTracker.swift
index fe8f8d1..6a4b23f 100644
--- a/Workout Spinner WatchKit Extension/Models/WorkoutTracker.swift
+++ b/Workout Spinner WatchKit Extension/Models/WorkoutTracker.swift
@@ -19,12 +19,17 @@ class WorkoutTracker: NSObject, ObservableObject {
/// Total active calories.
var totalActiveCalories: Double {
- return data.map { $0.activeCalories }.reduce(0, +)
+ data.map { $0.activeCalories }.reduce(0, +)
}
/// Total duration.
var totalDuration: Double {
- return data.map { $0.duration }.reduce(0, +)
+ data.map { $0.duration }.reduce(0, +)
+ }
+
+ /// The total number of heart rate measurements.
+ var numberOfHeartRateMeasurements: Int {
+ data.map { $0.heartRate.count }.reduce(0, +)
}
/// Average heart rate reading.
diff --git a/Workout Spinner WatchKit Extension/Views/ExercisePicker.swift b/Workout Spinner WatchKit Extension/Views/ExercisePicker.swift
index 7e5f627..f8bd539 100644
--- a/Workout Spinner WatchKit Extension/Views/ExercisePicker.swift
+++ b/Workout Spinner WatchKit Extension/Views/ExercisePicker.swift
@@ -57,7 +57,9 @@ struct ExercisePicker: View {
.animation(.default)
HStack {
- SpinnerPointer().frame(width: 20, height: 15)
+ SpinnerPointer()
+ .frame(width: 35, height: 25)
+ .opacity(0.8)
Spacer()
}
}
diff --git a/Workout Spinner WatchKit Extension/Views/ExerciseView.swift b/Workout Spinner WatchKit Extension/Views/ExerciseView.swift
index 1675a62..c77ce79 100644
--- a/Workout Spinner WatchKit Extension/Views/ExerciseView.swift
+++ b/Workout Spinner WatchKit Extension/Views/ExerciseView.swift
@@ -76,9 +76,9 @@ struct ExerciseView: View {
Spacer()
- Button(action: finishExercise, label: {
- Text("Done").foregroundColor(.green).bold()
- })
+ DoneButton(action: finishExercise)
+ .padding(.horizontal, 8)
+ .padding(.top, 4)
}
}
diff --git a/Workout Spinner WatchKit Extension/View Modifiers/ButtonStyles.swift b/Workout Spinner WatchKit Extension/Views/General Components/ButtonStyles.swift
similarity index 82%
rename from Workout Spinner WatchKit Extension/View Modifiers/ButtonStyles.swift
rename to Workout Spinner WatchKit Extension/Views/General Components/ButtonStyles.swift
index 2818406..702a5ad 100644
--- a/Workout Spinner WatchKit Extension/View Modifiers/ButtonStyles.swift
+++ b/Workout Spinner WatchKit Extension/Views/General Components/ButtonStyles.swift
@@ -10,12 +10,12 @@ import SwiftUI
struct DoneButtonStyle: ButtonStyle {
var padding: CGFloat = 5.0
- var cornerRadius: CGFloat = 5.0
- var color = Color.workoutGreen
+ var cornerRadius: CGFloat = 18.0
+ var color = Color.workoutRed
func makeBody(configuration: Configuration) -> some View {
configuration.label
- .padding(padding)
+ .padding(.vertical, padding)
.background(
RoundedRectangle(cornerRadius: cornerRadius, style: .continuous)
.fill(color)
@@ -31,8 +31,10 @@ struct StartWorkoutButtonStyle: ButtonStyle {
.padding(20)
.background(
RoundedRectangle(cornerRadius: 8, style: .continuous)
- .fill(Color.darkGray)
+ .fill(Color.workoutRed)
)
+ .scaleEffect(configuration.isPressed ? 0.97 : 1.0)
+ .animation(.linear(duration: 0.2))
}
}
diff --git a/Workout Spinner WatchKit Extension/Views/General Components/Buttons.swift b/Workout Spinner WatchKit Extension/Views/General Components/Buttons.swift
index fadac63..2f44fc3 100644
--- a/Workout Spinner WatchKit Extension/Views/General Components/Buttons.swift
+++ b/Workout Spinner WatchKit Extension/Views/General Components/Buttons.swift
@@ -8,23 +8,63 @@
import SwiftUI
+struct CleanListViewButtonModifications: ViewModifier {
+ func body(content: Content) -> some View {
+ content
+ .listStyle(PlainListStyle())
+ .listRowPlatterColor(.clear)
+ }
+}
+
struct ListViewTextButton: View {
- var label: String
+ var text: String
var action: () -> Void
var body: some View {
Button(action: action) {
- Text(label)
+ Text(text)
.foregroundColor(.black)
.frame(minWidth: 0, maxWidth: .infinity)
}
- .listStyle(PlainListStyle())
- .listRowPlatterColor(.clear)
+ .modifier(CleanListViewButtonModifications())
+ }
+}
+
+struct ListViewDoneButton: View {
+ var text: String = "Done"
+ var action: () -> Void
+ var verticalTextPadding: CGFloat = 3
+
+ var body: some View {
+ Button(action: action) {
+ Text(text)
+ .bold()
+ .padding(.vertical, verticalTextPadding)
+ .modifier(DoneButtonText())
+ }
+ .modifier(CleanListViewButtonModifications())
+ .buttonStyle(DoneButtonStyle())
+ }
+}
+
+struct DoneButton: View {
+ var text: String = "Done"
+ var action: () -> Void
+ var verticalTextPadding: CGFloat = 3
+
+ var body: some View {
+ Button(action: action) {
+ Text(text)
+ .bold()
+ .padding(.vertical, verticalTextPadding)
+ .modifier(DoneButtonText())
+ }
+ .buttonStyle(DoneButtonStyle())
}
}
struct Buttons_Previews: PreviewProvider {
static var previews: some View {
- ListViewTextButton(label: "Button") {}
+ ListViewTextButton(text: "Button") {}
}
}
diff --git a/Workout Spinner WatchKit Extension/View Modifiers/SpinnerRotationModifier.swift b/Workout Spinner WatchKit Extension/Views/General Components/SpinnerRotationModifier.swift
similarity index 100%
rename from Workout Spinner WatchKit Extension/View Modifiers/SpinnerRotationModifier.swift
rename to Workout Spinner WatchKit Extension/Views/General Components/SpinnerRotationModifier.swift
diff --git a/Workout Spinner WatchKit Extension/Views/General Components/Text ViewModifiers.swift b/Workout Spinner WatchKit Extension/Views/General Components/Text ViewModifiers.swift
new file mode 100644
index 0000000..c83f34c
--- /dev/null
+++ b/Workout Spinner WatchKit Extension/Views/General Components/Text ViewModifiers.swift
@@ -0,0 +1,18 @@
+//
+// Text ViewModifiers.swift
+// Workout Spinner WatchKit Extension
+//
+// Created by Joshua on 12/3/20.
+// Copyright © 2020 Joshua Cook. All rights reserved.
+//
+
+import SwiftUI
+
+struct DoneButtonText: ViewModifier {
+ func body(content: Content) -> some View {
+ content
+ .font(.system(.body, design: .rounded))
+ .foregroundColor(.white)
+ .frame(minWidth: 0, maxWidth: .infinity)
+ }
+}
diff --git a/Workout Spinner WatchKit Extension/Views/HeartRateGraph/GraphBackgroundSegment.swift b/Workout Spinner WatchKit Extension/Views/HeartRateGraph/GraphBackgroundSegment.swift
index a0d0a32..992ab66 100644
--- a/Workout Spinner WatchKit Extension/Views/HeartRateGraph/GraphBackgroundSegment.swift
+++ b/Workout Spinner WatchKit Extension/Views/HeartRateGraph/GraphBackgroundSegment.swift
@@ -44,7 +44,11 @@ struct GraphBackgroundSegment: View {
/// - Parameter width: Width to be scaled.
/// - Returns: Scaled width.
func scaleWidth(_ width: Double) -> CGFloat {
- CGFloat(width.rangeMap(inMin: 0, inMax: totalSegmentWidth, outMin: 0, outMax: Double(size.width)))
+ let x = CGFloat(width.rangeMap(inMin: 0, inMax: totalSegmentWidth, outMin: 0, outMax: Double(size.width)))
+ print("scaled width from \(width) to \(x)")
+ print(" totalSegmentWidth: \(totalSegmentWidth)")
+ print(" size.width: \(size.width)")
+ return x
}
/// Scale a value to the height of the entire frame.
@@ -74,7 +78,7 @@ struct GraphBackgroundSegment: View {
let maxX = xValues.max()!
let minY = graphData.minY
let maxY = graphData.maxY
- data.append(RectangleSegment(width: maxX - minX, height: maxY - minY, color: colors[idx]))
+ data.append(RectangleSegment(width: max(1.0, maxX - minX), height: maxY - minY, color: colors[idx]))
}
return data
diff --git a/Workout Spinner WatchKit Extension/Views/Settings Views/EditExerciseView.swift b/Workout Spinner WatchKit Extension/Views/Settings Views/EditExerciseView.swift
index 4abfa44..4eca4b3 100644
--- a/Workout Spinner WatchKit Extension/Views/Settings Views/EditExerciseView.swift
+++ b/Workout Spinner WatchKit Extension/Views/Settings Views/EditExerciseView.swift
@@ -126,9 +126,9 @@ struct EditExerciseView: View {
}
}
- ListViewTextButton(label: "Save", action: saveAndFinish)
- .buttonStyle(DoneButtonStyle(color: .workoutRed))
+ ListViewDoneButton(text: "Save", action: saveAndFinish)
.disabled(name.trimmingCharacters(in: .whitespacesAndNewlines) == "")
+ .opacity(name.trimmingCharacters(in: .whitespacesAndNewlines) == "" ? 0.7 : 1.0)
}
}
}
diff --git a/Workout Spinner WatchKit Extension/Views/Spinner Subviews/SpinnerPointer.swift b/Workout Spinner WatchKit Extension/Views/Spinner Subviews/SpinnerPointer.swift
index 9731d8e..5e0b7cd 100644
--- a/Workout Spinner WatchKit Extension/Views/Spinner Subviews/SpinnerPointer.swift
+++ b/Workout Spinner WatchKit Extension/Views/Spinner Subviews/SpinnerPointer.swift
@@ -22,8 +22,8 @@ struct PointerTriangle: Shape {
struct SpinnerPointer: View {
var body: some View {
PointerTriangle()
- .foregroundColor(.white)
- .shadow(color: .black, radius: 5, x: 5, y: 5)
+ .foregroundColor(.workoutRed)
+ .shadow(color: .black, radius: 5, x: 3, y: 3)
}
}
diff --git a/Workout Spinner WatchKit Extension/Views/Spinner Subviews/SpinnerSlice.swift b/Workout Spinner WatchKit Extension/Views/Spinner Subviews/SpinnerSlice.swift
index dbc59f9..3a39ffe 100644
--- a/Workout Spinner WatchKit Extension/Views/Spinner Subviews/SpinnerSlice.swift
+++ b/Workout Spinner WatchKit Extension/Views/Spinner Subviews/SpinnerSlice.swift
@@ -39,10 +39,12 @@ struct SpinnerSlice: View {
var body: some View {
ZStack {
- Color.darkGray
+// Color.darkGray
+// LinearGradient(gradient: Gradient(colors: [.gray, .darkGray]), startPoint: .leading, endPoint: .trailing)
+ Color.white
.clipShape(SpinnerSliceShape(radius: width / 2.0, angle: sliceAngle))
SpinnerSliceShape(radius: width / 2.0, angle: sliceAngle)
- .stroke(Color.gray, lineWidth: 3)
+ .stroke(Color.black, lineWidth: 3)
.frame(width: width, height: width)
}
.rotationEffect(rotationAngle)
diff --git a/Workout Spinner WatchKit Extension/Views/Spinner Subviews/WorkoutSlice.swift b/Workout Spinner WatchKit Extension/Views/Spinner Subviews/WorkoutSlice.swift
index efae44b..59b00f9 100644
--- a/Workout Spinner WatchKit Extension/Views/Spinner Subviews/WorkoutSlice.swift
+++ b/Workout Spinner WatchKit Extension/Views/Spinner Subviews/WorkoutSlice.swift
@@ -27,7 +27,7 @@ struct WorkoutSlice: View {
Text(workoutInfo.displayName)
.rotationEffect(.degrees(180))
.font(.system(size: 20))
- .foregroundColor(.white)
+ .foregroundColor(.black)
.lineLimit(1)
.padding(.horizontal, 5)
.frame(width: size / 2 - offset, height: nil, alignment: .trailing)
diff --git a/Workout Spinner WatchKit Extension/Views/WelcomeView.swift b/Workout Spinner WatchKit Extension/Views/WelcomeView.swift
index f2a67fb..770099a 100644
--- a/Workout Spinner WatchKit Extension/Views/WelcomeView.swift
+++ b/Workout Spinner WatchKit Extension/Views/WelcomeView.swift
@@ -13,6 +13,8 @@ struct WelcomeView: View {
@ObservedObject var workoutTracker: WorkoutTracker
@ObservedObject var exerciseOptions: ExerciseOptions
+ @State var arrowButtonSize: CGFloat = 1.0
+
@State private var startWorkout = false
@State private var presentSettingsView = false
@State private var showInstructions = false
@@ -21,15 +23,25 @@ struct WelcomeView: View {
VStack {
Spacer(minLength: 0)
+ Text("Start Workout")
+ .font(.system(size: 25))
+ .foregroundColor(.white)
+ .bold()
+ .multilineTextAlignment(.center)
+ .padding()
+
NavigationLink(destination: WorkoutPagingView(workoutManager: workoutManager, workoutTracker: workoutTracker, exerciseOptions: exerciseOptions)) {
- Text("Start Workout")
- .font(.system(size: 30))
+ Image(systemName: "arrow.right.circle.fill")
+ .font(.system(size: 80))
.foregroundColor(.workoutRed)
- .bold()
- .multilineTextAlignment(.center)
+ .scaleEffect(arrowButtonSize)
+ .animation(
+ Animation.easeInOut(duration: 1.0)
+ .repeatForever(autoreverses: true)
+ )
}
- .buttonStyle(StartWorkoutButtonStyle())
- .padding(.bottom, 5)
+ .buttonStyle(PlainButtonStyle())
+ .padding(.vertical, 5)
Spacer(minLength: 0)
@@ -69,6 +81,7 @@ struct WelcomeView: View {
})
}
.onAppear {
+ self.arrowButtonSize = 0.9
workoutManager.requestAuthorization()
workoutManager.setupWorkout()
}
diff --git a/Workout Spinner WatchKit Extension/Views/WorkoutFinishView.swift b/Workout Spinner WatchKit Extension/Views/WorkoutFinishView.swift
index 48d400d..75bd0f8 100644
--- a/Workout Spinner WatchKit Extension/Views/WorkoutFinishView.swift
+++ b/Workout Spinner WatchKit Extension/Views/WorkoutFinishView.swift
@@ -58,16 +58,20 @@ struct WorkoutFinishView: View {
@Environment(\.presentationMode) var presentationMode
+ private var heartRateGraphIsAvailable: Bool {
+ workoutTracker.numberOfHeartRateMeasurements > 1
+ }
+
private var averageHR: String {
- return valueAsIntStringOrNA(workoutTracker.averageHeartRate)
+ valueAsIntStringOrNA(workoutTracker.averageHeartRate)
}
private var minHR: String {
- return valueAsIntStringOrNA(workoutTracker.minHeartRate)
+ valueAsIntStringOrNA(workoutTracker.minHeartRate)
}
private var maxHR: String {
- return valueAsIntStringOrNA(workoutTracker.maxHeartRate)
+ valueAsIntStringOrNA(workoutTracker.maxHeartRate)
}
@State private var showAllExercises: Bool = false
@@ -92,8 +96,8 @@ struct WorkoutFinishView: View {
InfoRowView(title: "Active Calories", titleColor: .yellow, value: "\(Int(workoutTracker.totalActiveCalories))")
- LinkedInfoRowView(title: "Average heart rate", titleColor: .red, value: averageHR, showEllipsis: averageHR != "NA") {
- if averageHR != "NA" {
+ LinkedInfoRowView(title: "Average heart rate", titleColor: .red, value: averageHR, showEllipsis: heartRateGraphIsAvailable) {
+ if heartRateGraphIsAvailable {
showHeartRateChartView = true
}
}
@@ -110,11 +114,10 @@ struct WorkoutFinishView: View {
InfoRowView(title: "Min/Max heart rate", titleColor: .red, value: "\(minHR) / \(maxHR)")
- ListViewTextButton(label: "Done") {
+ ListViewDoneButton {
presentationMode.wrappedValue.dismiss()
workoutTracker.clear()
}
- .buttonStyle(DoneButtonStyle(color: .workoutRed))
}
}
.navigationBarBackButtonHidden(true)