This commit is contained in:
Trey t
2023-06-23 13:34:29 -05:00
parent a43acc9c27
commit 48f23f8e77
15 changed files with 644 additions and 6 deletions

View File

@@ -2,6 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSHealthShareUsageDescription</key>
<string>Read your heart reate</string>
<key>NSHealthUpdateUsageDescription</key>
<string>Read your heart reate</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UIBackgroundModes</key>
<array/>
<key>WKBackgroundModes</key>
<array>
<string>workout-processing</string>
</array>
</dict>
</plist>

View File

@@ -43,8 +43,53 @@
1CF65A852A43E8060042FFBD /* CompletedWorkout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A842A43E8060042FFBD /* CompletedWorkout.swift */; };
1CF65A872A4400E10042FFBD /* ToDo in Resources */ = {isa = PBXBuildFile; fileRef = 1CF65A862A4400E10042FFBD /* ToDo */; };
1CF65A8E2A44B78B0042FFBD /* CompletedWorkoutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A8D2A44B78B0042FFBD /* CompletedWorkoutView.swift */; };
1CF65A962A452D270042FFBD /* Werkout_watchApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A952A452D270042FFBD /* Werkout_watchApp.swift */; };
1CF65A982A452D270042FFBD /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A972A452D270042FFBD /* ContentView.swift */; };
1CF65A9A2A452D290042FFBD /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1CF65A992A452D290042FFBD /* Assets.xcassets */; };
1CF65A9D2A452D290042FFBD /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1CF65A9C2A452D290042FFBD /* Preview Assets.xcassets */; };
1CF65AA12A452D290042FFBD /* Werkout_watch Watch App.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 1CF65A932A452D270042FFBD /* Werkout_watch Watch App.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
1CF65AA52A452D9C0042FFBD /* CompletedWorkout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A842A43E8060042FFBD /* CompletedWorkout.swift */; };
1CF65AA62A452D9C0042FFBD /* Equipment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A5A2A3BF4BE0042FFBD /* Equipment.swift */; };
1CF65AA72A452D9C0042FFBD /* Muscle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A582A3BF4B60042FFBD /* Muscle.swift */; };
1CF65AA82A452D9C0042FFBD /* Exercise.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A442A39FB550042FFBD /* Exercise.swift */; };
1CF65AA92A452D9C0042FFBD /* Workout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A422A39FB410042FFBD /* Workout.swift */; };
1CF65AAA2A452D9C0042FFBD /* RegisteredUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A462A39FB6C0042FFBD /* RegisteredUser.swift */; };
1CF65AAB2A452DAC0042FFBD /* PreviewWorkout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A512A3A90A00042FFBD /* PreviewWorkout.swift */; };
1CF65AAC2A452DF50042FFBD /* WorkoutOne.json in Resources */ = {isa = PBXBuildFile; fileRef = 1CF65A492A39FBB10042FFBD /* WorkoutOne.json */; };
1CF65AAD2A452DF50042FFBD /* Exercises.json in Resources */ = {isa = PBXBuildFile; fileRef = 1CF65A662A3BFF840042FFBD /* Exercises.json */; };
1CF65AAE2A452DF50042FFBD /* AllWorkouts.json in Resources */ = {isa = PBXBuildFile; fileRef = 1CF65A642A3BF6BE0042FFBD /* AllWorkouts.json */; };
1CF65AAF2A452DF50042FFBD /* AllMuscles.json in Resources */ = {isa = PBXBuildFile; fileRef = 1CF65A562A3BF3830042FFBD /* AllMuscles.json */; };
1CF65AB02A452DF50042FFBD /* Equipment.json in Resources */ = {isa = PBXBuildFile; fileRef = 1CF65A5E2A3BF5A60042FFBD /* Equipment.json */; };
1CF65AB12A452E1A0042FFBD /* BridgeModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A4F2A3A1EA90042FFBD /* BridgeModule.swift */; };
1CF65AB32A452F360042FFBD /* WatchPackageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65AB22A452F360042FFBD /* WatchPackageModel.swift */; };
1CF65AB42A4530200042FFBD /* WatchPackageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65AB22A452F360042FFBD /* WatchPackageModel.swift */; };
1CF65AB62A4532940042FFBD /* WatchMainViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65AB52A4532940042FFBD /* WatchMainViewModel.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
1CF65A9E2A452D290042FFBD /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 1CF65A1A2A3972840042FFBD /* Project object */;
proxyType = 1;
remoteGlobalIDString = 1CF65A922A452D270042FFBD;
remoteInfo = "Werkout_watch Watch App";
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
1CF65AA02A452D290042FFBD /* Embed Watch Content */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "$(CONTENTS_FOLDER_PATH)/Watch";
dstSubfolderSpec = 16;
files = (
1CF65AA12A452D290042FFBD /* Werkout_watch Watch App.app in Embed Watch Content */,
);
name = "Embed Watch Content";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1CF65A222A3972840042FFBD /* Werkout_ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Werkout_ios.app; sourceTree = BUILT_PRODUCTS_DIR; };
1CF65A252A3972840042FFBD /* Werkout_iosApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Werkout_iosApp.swift; sourceTree = "<group>"; };
@@ -85,6 +130,15 @@
1CF65A842A43E8060042FFBD /* CompletedWorkout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletedWorkout.swift; sourceTree = "<group>"; };
1CF65A862A4400E10042FFBD /* ToDo */ = {isa = PBXFileReference; lastKnownFileType = text; path = ToDo; sourceTree = "<group>"; };
1CF65A8D2A44B78B0042FFBD /* CompletedWorkoutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletedWorkoutView.swift; sourceTree = "<group>"; };
1CF65A932A452D270042FFBD /* Werkout_watch Watch App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Werkout_watch Watch App.app"; sourceTree = BUILT_PRODUCTS_DIR; };
1CF65A952A452D270042FFBD /* Werkout_watchApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Werkout_watchApp.swift; sourceTree = "<group>"; };
1CF65A972A452D270042FFBD /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
1CF65A992A452D290042FFBD /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
1CF65A9C2A452D290042FFBD /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
1CF65AB22A452F360042FFBD /* WatchPackageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchPackageModel.swift; sourceTree = "<group>"; };
1CF65AB52A4532940042FFBD /* WatchMainViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchMainViewModel.swift; sourceTree = "<group>"; };
1CF65AB72A4534DC0042FFBD /* Werkout_watch Watch App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Werkout_watch Watch App.entitlements"; sourceTree = "<group>"; };
1CF65AB82A45387B0042FFBD /* Werkout-watch-Watch-App-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Werkout-watch-Watch-App-Info.plist"; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -95,6 +149,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
1CF65A902A452D270042FFBD /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
@@ -102,6 +163,7 @@
isa = PBXGroup;
children = (
1CF65A242A3972840042FFBD /* Werkout_ios */,
1CF65A942A452D270042FFBD /* Werkout_watch Watch App */,
1CF65A232A3972840042FFBD /* Products */,
);
sourceTree = "<group>";
@@ -110,6 +172,7 @@
isa = PBXGroup;
children = (
1CF65A222A3972840042FFBD /* Werkout_ios.app */,
1CF65A932A452D270042FFBD /* Werkout_watch Watch App.app */,
);
name = Products;
sourceTree = "<group>";
@@ -120,6 +183,7 @@
1CF65A552A3AA6800042FFBD /* Werkout-ios-Info.plist */,
1CF65A482A39FB910042FFBD /* JSON */,
1CF65A252A3972840042FFBD /* Werkout_iosApp.swift */,
1CF65AB22A452F360042FFBD /* WatchPackageModel.swift */,
1CF65A822A42347D0042FFBD /* Extensions.swift */,
1CF65A272A3972840042FFBD /* Persistence.swift */,
1CF65A4F2A3A1EA90042FFBD /* BridgeModule.swift */,
@@ -247,6 +311,28 @@
path = CompletedWorkout;
sourceTree = "<group>";
};
1CF65A942A452D270042FFBD /* Werkout_watch Watch App */ = {
isa = PBXGroup;
children = (
1CF65AB82A45387B0042FFBD /* Werkout-watch-Watch-App-Info.plist */,
1CF65AB72A4534DC0042FFBD /* Werkout_watch Watch App.entitlements */,
1CF65A952A452D270042FFBD /* Werkout_watchApp.swift */,
1CF65A972A452D270042FFBD /* ContentView.swift */,
1CF65AB52A4532940042FFBD /* WatchMainViewModel.swift */,
1CF65A992A452D290042FFBD /* Assets.xcassets */,
1CF65A9B2A452D290042FFBD /* Preview Content */,
);
path = "Werkout_watch Watch App";
sourceTree = "<group>";
};
1CF65A9B2A452D290042FFBD /* Preview Content */ = {
isa = PBXGroup;
children = (
1CF65A9C2A452D290042FFBD /* Preview Assets.xcassets */,
);
path = "Preview Content";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -257,14 +343,33 @@
1CF65A1E2A3972840042FFBD /* Sources */,
1CF65A1F2A3972840042FFBD /* Frameworks */,
1CF65A202A3972840042FFBD /* Resources */,
1CF65AA02A452D290042FFBD /* Embed Watch Content */,
);
buildRules = (
);
dependencies = (
1CF65A9F2A452D290042FFBD /* PBXTargetDependency */,
);
name = Werkout_ios;
productName = Werkout_ios;
productReference = 1CF65A222A3972840042FFBD /* Werkout_ios.app */;
productType = "com.apple.product-type.application";
};
1CF65A922A452D270042FFBD /* Werkout_watch Watch App */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1CF65AA22A452D290042FFBD /* Build configuration list for PBXNativeTarget "Werkout_watch Watch App" */;
buildPhases = (
1CF65A8F2A452D270042FFBD /* Sources */,
1CF65A902A452D270042FFBD /* Frameworks */,
1CF65A912A452D270042FFBD /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = Werkout_ios;
productName = Werkout_ios;
productReference = 1CF65A222A3972840042FFBD /* Werkout_ios.app */;
name = "Werkout_watch Watch App";
productName = "Werkout_watch Watch App";
productReference = 1CF65A932A452D270042FFBD /* Werkout_watch Watch App.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
@@ -280,6 +385,9 @@
1CF65A212A3972840042FFBD = {
CreatedOnToolsVersion = 14.3;
};
1CF65A922A452D270042FFBD = {
CreatedOnToolsVersion = 14.3;
};
};
};
buildConfigurationList = 1CF65A1D2A3972840042FFBD /* Build configuration list for PBXProject "Werkout_ios" */;
@@ -296,6 +404,7 @@
projectRoot = "";
targets = (
1CF65A212A3972840042FFBD /* Werkout_ios */,
1CF65A922A452D270042FFBD /* Werkout_watch Watch App */,
);
};
/* End PBXProject section */
@@ -317,6 +426,20 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
1CF65A912A452D270042FFBD /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1CF65AAF2A452DF50042FFBD /* AllMuscles.json in Resources */,
1CF65AAC2A452DF50042FFBD /* WorkoutOne.json in Resources */,
1CF65AAD2A452DF50042FFBD /* Exercises.json in Resources */,
1CF65AB02A452DF50042FFBD /* Equipment.json in Resources */,
1CF65A9D2A452D290042FFBD /* Preview Assets.xcassets in Resources */,
1CF65A9A2A452D290042FFBD /* Assets.xcassets in Resources */,
1CF65AAE2A452DF50042FFBD /* AllWorkouts.json in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -334,6 +457,7 @@
1CF65A692A3C018F0042FFBD /* AccountView.swift in Sources */,
1CF65A4E2A39FF200042FFBD /* WorkoutDetailViewModel.swift in Sources */,
1CF65A472A39FB6C0042FFBD /* RegisteredUser.swift in Sources */,
1CF65AB32A452F360042FFBD /* WatchPackageModel.swift in Sources */,
1CF65A522A3A90A00042FFBD /* PreviewWorkout.swift in Sources */,
1CF65A852A43E8060042FFBD /* CompletedWorkout.swift in Sources */,
1CF65A6E2A3F60480042FFBD /* CreateViewModels.swift in Sources */,
@@ -354,8 +478,35 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
1CF65A8F2A452D270042FFBD /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1CF65A982A452D270042FFBD /* ContentView.swift in Sources */,
1CF65A962A452D270042FFBD /* Werkout_watchApp.swift in Sources */,
1CF65AA92A452D9C0042FFBD /* Workout.swift in Sources */,
1CF65AA62A452D9C0042FFBD /* Equipment.swift in Sources */,
1CF65AB12A452E1A0042FFBD /* BridgeModule.swift in Sources */,
1CF65AAA2A452D9C0042FFBD /* RegisteredUser.swift in Sources */,
1CF65AB62A4532940042FFBD /* WatchMainViewModel.swift in Sources */,
1CF65AA72A452D9C0042FFBD /* Muscle.swift in Sources */,
1CF65AAB2A452DAC0042FFBD /* PreviewWorkout.swift in Sources */,
1CF65AA52A452D9C0042FFBD /* CompletedWorkout.swift in Sources */,
1CF65AA82A452D9C0042FFBD /* Exercise.swift in Sources */,
1CF65AB42A4530200042FFBD /* WatchPackageModel.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
1CF65A9F2A452D290042FFBD /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 1CF65A922A452D270042FFBD /* Werkout_watch Watch App */;
targetProxy = 1CF65A9E2A452D290042FFBD /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
1CF65A342A3972850042FFBD /* Debug */ = {
isa = XCBuildConfiguration;
@@ -469,6 +620,7 @@
1CF65A372A3972850042FFBD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = Werkout_ios/Werkout_ios.entitlements;
@@ -508,6 +660,7 @@
1CF65A382A3972850042FFBD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = Werkout_ios/Werkout_ios.entitlements;
@@ -544,6 +697,75 @@
};
name = Release;
};
1CF65AA32A452D290042FFBD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = "Werkout_watch Watch App/Werkout_watch Watch App.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"Werkout_watch Watch App/Preview Content\"";
DEVELOPMENT_TEAM = V3PF3M6B6U;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "Werkout-watch-Watch-App-Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = Werkout_watch;
INFOPLIST_KEY_NSHealthShareUsageDescription = "Read your heart reate";
INFOPLIST_KEY_NSHealthUpdateUsageDescription = "Read your heart reate";
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
INFOPLIST_KEY_WKCompanionAppBundleIdentifier = "com.t-t.Werkout-ios";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.t-t.Werkout-ios.watchkitapp";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = watchos;
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 4;
WATCHOS_DEPLOYMENT_TARGET = 9.4;
};
name = Debug;
};
1CF65AA42A452D290042FFBD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = "Werkout_watch Watch App/Werkout_watch Watch App.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"Werkout_watch Watch App/Preview Content\"";
DEVELOPMENT_TEAM = V3PF3M6B6U;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "Werkout-watch-Watch-App-Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = Werkout_watch;
INFOPLIST_KEY_NSHealthShareUsageDescription = "Read your heart reate";
INFOPLIST_KEY_NSHealthUpdateUsageDescription = "Read your heart reate";
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
INFOPLIST_KEY_WKCompanionAppBundleIdentifier = "com.t-t.Werkout-ios";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.t-t.Werkout-ios.watchkitapp";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = watchos;
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 4;
VALIDATE_PRODUCT = YES;
WATCHOS_DEPLOYMENT_TARGET = 9.4;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@@ -565,6 +787,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
1CF65AA22A452D290042FFBD /* Build configuration list for PBXNativeTarget "Werkout_watch Watch App" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1CF65AA32A452D290042FFBD /* Debug */,
1CF65AA42A452D290042FFBD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCVersionGroup section */

View File

@@ -9,6 +9,11 @@
<key>orderHint</key>
<integer>0</integer>
</dict>
<key>Werkout_watch Watch App.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
</dict>
</dict>
</dict>
</plist>

View File

@@ -6,8 +6,15 @@
//
import Foundation
import WatchConnectivity
enum WatchActions: String, Codable {
case nextExercise
}
class BridgeModule: NSObject, ObservableObject {
private let kMessageKey = "message"
class BridgeModule: ObservableObject {
static let shared = BridgeModule()
@Published var isShowingOnExternalDisplay = false
@@ -19,6 +26,7 @@ class BridgeModule: ObservableObject {
var currentExerciseIdx: Int = -1
var workoutStartDate: Date?
var workoutEndDate: Date?
@Published var currentWorkoutRunTimeInSeconds: Int = -1
private var currentWorkoutRunTimer: Timer?
@@ -36,6 +44,11 @@ class BridgeModule: ObservableObject {
startWorkoutTimer()
workoutStartDate = Date()
isInWorkout = true
if WCSession.isSupported() {
WCSession.default.delegate = self
WCSession.default.activate()
}
}
func resetCurrentWorkout() {
@@ -52,8 +65,14 @@ class BridgeModule: ObservableObject {
currentExercise = nil
currentWorkout = nil
if isInWorkout {
let watchModel = WatchPackageModel(currentExerciseName: currentExercise?.exercise.name ?? "-", currentTimeLeft: timeLeft, workoutStartDate: workoutStartDate ?? Date(), workoutEndDate: Date())
let data = try! JSONEncoder().encode(watchModel)
send(data)
}
isInWorkout = false
workoutStartDate = nil
workoutEndDate = nil
}
private func startWorkoutTimer() {
@@ -82,6 +101,11 @@ class BridgeModule: ObservableObject {
@objc func updateCounter() {
if timeLeft > 0 {
timeLeft -= 1
let watchModel = WatchPackageModel(currentExerciseName: currentExercise?.exercise.name ?? "-", currentTimeLeft: timeLeft, workoutStartDate: workoutStartDate ?? Date())
let data = try! JSONEncoder().encode(watchModel)
send(data)
} else {
timer?.invalidate()
timer = nil
@@ -114,3 +138,46 @@ class BridgeModule: ObservableObject {
}
}
}
extension BridgeModule: WCSessionDelegate {
func session(_ session: WCSession, didReceiveMessageData messageData: Data) {
if let model = try? JSONDecoder().decode(WatchActions.self, from: messageData) {
switch model {
case .nextExercise:
nextExercise()
}
}
}
func session(_ session: WCSession,
activationDidCompleteWith activationState: WCSessionActivationState,
error: Error?) {}
#if os(iOS)
func sessionDidBecomeInactive(_ session: WCSession) {}
func sessionDidDeactivate(_ session: WCSession) {
session.activate()
}
#endif
func send(_ data: Data) {
guard WCSession.default.activationState == .activated else {
return
}
#if os(iOS)
guard WCSession.default.isWatchAppInstalled else {
return
}
#else
guard WCSession.default.isCompanionAppInstalled else {
return
}
#endif
WCSession.default.sendMessageData(data, replyHandler: nil)
{ error in
print("Cannot send message: \(String(describing: error))")
}
}
}

View File

@@ -33,11 +33,11 @@ struct WorkoutDetailView: View {
CountdownView()
ExerciseListView(workout: workout)
ActionsView(completedWorkout: {
bridgeModule.workoutEndDate = Date()
if let workoutData = createWorkoutData() {
presentedSheet = .completedWorkout(workoutData)
bridgeModule.resetCurrentWorkout()
}
}, workout: workout)
.frame(height: 44)
@@ -59,12 +59,14 @@ struct WorkoutDetailView: View {
func createWorkoutData() -> [String:Any]? {
guard let workoutid = bridgeModule.currentWorkout?.id,
let startTime = bridgeModule.workoutStartDate?.timeFormatForUpload else {
let startTime = bridgeModule.workoutStartDate?.timeFormatForUpload,
let endTime = bridgeModule.workoutEndDate?.timeFormatForUpload else {
return nil
}
let postBody = [
"difficulty": 1,
"workout_start_time": startTime,
"workout_end_time": endTime,
"workout": workoutid,
"total_time": bridgeModule.currentWorkoutRunTimeInSeconds
] as [String : Any]

View File

@@ -0,0 +1,15 @@
//
// WatchPackageModel.swift
// Werkout_ios
//
// Created by Trey Tartt on 6/22/23.
//
import Foundation
struct WatchPackageModel: Codable {
var currentExerciseName: String
var currentTimeLeft: Int
var workoutStartDate: Date
var workoutEndDate: Date?
}

View File

@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,13 @@
{
"images" : [
{
"idiom" : "universal",
"platform" : "watchos",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,44 @@
//
// ContentView.swift
// Werkout_watch Watch App
//
// Created by Trey Tartt on 6/22/23.
//
import SwiftUI
struct ContentView: View {
let exercise = PreviewWorkout.parseEquipment()[2]
@StateObject var vm = WatchMainViewModel()
var body: some View {
VStack {
if let model = vm.watchPackageModel {
Text(model.currentExerciseName)
Text("\(model.currentTimeLeft )")
}
if let heartValue = vm.heartValue {
HStack {
Image(systemName: "heart.fill")
Text("\(heartValue)")
}
}
Button(action: {
vm.nextExercise()
}, label: {
Image(systemName: "arrow.forward")
.font(.title)
.frame(maxWidth: .infinity, maxHeight: .infinity)
})
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,195 @@
//
// WatchMainViewMoel.swift
// Werkout_watch Watch App
//
// Created by Trey Tartt on 6/22/23.
//
import Foundation
import WatchConnectivity
import SwiftUI
import HealthKit
class WatchMainViewModel: NSObject, ObservableObject {
var session: WCSession
@Published var watchPackageModel: WatchPackageModel?
@Published var heartValue: Int?
let healthStore = HKHealthStore()
var hkWorkoutSession: HKWorkoutSession? {
didSet {
print("here")
}
}
var hkBuilder: HKLiveWorkoutBuilder?
override init() {
session = WCSession.default
super.init()
session.delegate = self
session.activate()
autorizeHealthKit()
}
func autorizeHealthKit() {
let healthKitTypes: Set = [
HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate)!,
HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)!,
HKQuantityType.workoutType()
]
healthStore.requestAuthorization(toShare: healthKitTypes, read: healthKitTypes) { (succ, error) in
if !succ {
fatalError("Error requesting authorization from health store: \(String(describing: error)))")
}
}
}
private func startHeartRateQuery(quantityTypeIdentifier: HKQuantityTypeIdentifier) {
let devicePredicate = HKQuery.predicateForObjects(from: [HKDevice.local()])
let updateHandler: (HKAnchoredObjectQuery, [HKSample]?, [HKDeletedObject]?, HKQueryAnchor?, Error?) -> Void = {
query, samples, deletedObjects, queryAnchor, error in
guard let samples = samples as? [HKQuantitySample] else {
return
}
}
let query = HKAnchoredObjectQuery(type: HKObjectType.quantityType(forIdentifier: quantityTypeIdentifier)!, predicate: devicePredicate, anchor: nil, limit: HKObjectQueryNoLimit, resultsHandler: updateHandler)
query.updateHandler = updateHandler
healthStore.execute(query)
}
func nextExercise() {
let nextExerciseAction = WatchActions.nextExercise
let data = try! JSONEncoder().encode(nextExerciseAction)
send(data)
}
}
extension WatchMainViewModel: WCSessionDelegate {
func session(_ session: WCSession, didReceiveMessageData messageData: Data) {
if let model = try? JSONDecoder().decode(WatchPackageModel.self, from: messageData) {
DispatchQueue.main.async {
if self.watchPackageModel?.workoutEndDate != nil {
self.watchPackageModel = nil
self.stopWorkout()
} else if self.watchPackageModel == nil {
self.startWorkout()
}
self.watchPackageModel = model
}
}
}
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
}
func send(_ data: Data) {
guard WCSession.default.activationState == .activated else {
return
}
#if os(iOS)
guard WCSession.default.isWatchAppInstalled else {
return
}
#else
guard WCSession.default.isCompanionAppInstalled else {
return
}
#endif
WCSession.default.sendMessageData(data, replyHandler: nil)
{ error in
print("Cannot send message: \(String(describing: error))")
}
}
}
extension WatchMainViewModel: HKWorkoutSessionDelegate, HKLiveWorkoutBuilderDelegate {
func initWorkout() {
let configuration = HKWorkoutConfiguration()
configuration.activityType = .functionalStrengthTraining
do {
hkWorkoutSession = try HKWorkoutSession(healthStore: healthStore, configuration: configuration)
hkBuilder = hkWorkoutSession?.associatedWorkoutBuilder()
} catch {
fatalError("Unable to create the workout session!")
}
guard let hkWorkoutSession = hkWorkoutSession, let hkBuilder = hkBuilder else {
return
}
// Setup session and builder.
hkWorkoutSession.delegate = self
hkBuilder.delegate = self
/// Set the workout builder's data source.
hkBuilder.dataSource = HKLiveWorkoutDataSource(healthStore: healthStore,
workoutConfiguration: configuration)
}
func startWorkout() {
// Initialize our workout
initWorkout()
guard let hkWorkoutSession = hkWorkoutSession, let hkBuilder = hkBuilder else {
return
}
// Start the workout session and begin data collection
hkWorkoutSession.startActivity(with: Date())
hkBuilder.beginCollection(withStart: Date()) { (succ, error) in
if !succ {
fatalError("Error beginning collection from builder: \(String(describing: error)))")
}
}
}
func stopWorkout() {
guard let hkWorkoutSession = hkWorkoutSession, let hkBuilder = hkBuilder else {
return
}
hkWorkoutSession.end()
hkBuilder.endCollection(withEnd: Date()) { (success, error) in
hkBuilder.finishWorkout { (workout, error) in
DispatchQueue.main.async() {
self.hkWorkoutSession = nil
self.hkBuilder = nil
}
}
}
}
func workoutSession(_ workoutSession: HKWorkoutSession, didChangeTo toState: HKWorkoutSessionState, from fromState: HKWorkoutSessionState, date: Date) {
print("[workoutSession] Changed State: \(toState.rawValue)")
}
func workoutSession(_ workoutSession: HKWorkoutSession, didFailWithError error: Error) {
print("[workoutSession] Encountered an error: \(error)")
}
func workoutBuilder(_ workoutBuilder: HKLiveWorkoutBuilder, didCollectDataOf collectedTypes: Set<HKSampleType>) {
for type in collectedTypes {
guard let quantityType = type as? HKQuantityType else {
return
}
switch quantityType {
case HKQuantityType.quantityType(forIdentifier: .heartRate):
let statistics = workoutBuilder.statistics(for: quantityType)
let heartRateUnit = HKUnit.count().unitDivided(by: HKUnit.minute())
let value = statistics!.mostRecentQuantity()?.doubleValue(for: heartRateUnit)
heartValue = Int(Double(round(1 * value!) / 1))
print("[workoutBuilder] Heart Rate: \(String(describing: heartValue))")
default:
return
}
}
}
func workoutBuilderDidCollectEvent(_ workoutBuilder: HKLiveWorkoutBuilder) {
guard let workoutEventType = workoutBuilder.workoutEvents.last?.type else { return }
print("[workoutBuilderDidCollectEvent] Workout Builder changed event: \(workoutEventType.rawValue)")
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.healthkit</key>
<true/>
<key>com.apple.developer.healthkit.access</key>
<array/>
</dict>
</plist>

View File

@@ -0,0 +1,17 @@
//
// Werkout_watchApp.swift
// Werkout_watch Watch App
//
// Created by Trey Tartt on 6/22/23.
//
import SwiftUI
@main
struct Werkout_watch_Watch_AppApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}