diff --git a/ios/App/App.xcodeproj/project.pbxproj b/ios/App/App.xcodeproj/project.pbxproj index 175437c..f13883b 100644 --- a/ios/App/App.xcodeproj/project.pbxproj +++ b/ios/App/App.xcodeproj/project.pbxproj @@ -30,6 +30,7 @@ 548F8BFA06417B35474BD69E /* CoachLiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 340B99D5EA4DB985D7DFDA10 /* CoachLiveView.swift */; }; 60061E60061E60061E060001 /* CoachGoogleAuth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60061E60061E60061E060002 /* CoachGoogleAuth.swift */; }; 6442A95576AFC77377D0DC61 /* RoutineGuidedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2D78A1BF31D30C5AEC24E7C /* RoutineGuidedView.swift */; }; + A1B2C3D4E5F60718293A4B5D /* VmaTestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F60718293A4B5C /* VmaTestView.swift */; }; 694B2F69591CAA85CE5DEC3A /* CoachLiveActivityWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBBF61A35F291A021BA75C60 /* CoachLiveActivityWidget.swift */; }; 79A94FD334CC9EC24D1FB700 /* CoachWidgets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0276928E86E785EEA434057C /* CoachWidgets.swift */; }; 880A76D1302B601000F582D5 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 880A76D0302B601000F582D5 /* WidgetKit.framework */; }; @@ -167,6 +168,7 @@ B93DA6B121E94B11DF938C90 /* LiveActivityManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiveActivityManager.swift; sourceTree = ""; }; C0AC4A07811751FB78AA0002 /* CoachAuth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoachAuth.swift; sourceTree = ""; }; C2D78A1BF31D30C5AEC24E7C /* RoutineGuidedView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = RoutineGuidedView.swift; sourceTree = ""; }; + A1B2C3D4E5F60718293A4B5C /* VmaTestView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = VmaTestView.swift; sourceTree = ""; }; D09B589FA572B2C14E8CD835 /* CoachWatch.entitlements */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.entitlements; path = CoachWatch.entitlements; sourceTree = ""; }; D1BD5B1990CF3F2B9C5D0002 /* CoachWorkoutKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoachWorkoutKit.swift; sourceTree = ""; }; D61D7B2F5AFEF834423E07AB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; @@ -319,6 +321,7 @@ A420239FC6D065C8A599B61C /* ConnectivityManager.swift */, AA5C5902EFB7F60563678E46 /* RoutineView.swift */, C2D78A1BF31D30C5AEC24E7C /* RoutineGuidedView.swift */, + A1B2C3D4E5F60718293A4B5C /* VmaTestView.swift */, 969DB880395BDEB107C9F2FE /* RoutineStore.swift */, 8AC9C9B9971F55027D227A06 /* WorkoutManager.swift */, 3342ACCE085010828CF63565 /* Assets.xcassets */, @@ -574,6 +577,7 @@ B06AB24B350B221F38D99E17 /* ConnectivityManager.swift in Sources */, 95D0478A499056FE922211EA /* RoutineView.swift in Sources */, 6442A95576AFC77377D0DC61 /* RoutineGuidedView.swift in Sources */, + A1B2C3D4E5F60718293A4B5D /* VmaTestView.swift in Sources */, 23F47FD81F646516727B5317 /* RoutineStore.swift in Sources */, 436442D6BF54833C59D9E668 /* WorkoutManager.swift in Sources */, ); diff --git a/ios/App/App.xcodeproj/project.pbxproj.bak-vma b/ios/App/App.xcodeproj/project.pbxproj.bak-vma new file mode 100644 index 0000000..175437c --- /dev/null +++ b/ios/App/App.xcodeproj/project.pbxproj.bak-vma @@ -0,0 +1,1075 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 70; + objects = { + +/* Begin PBXBuildFile section */ + 01468471ECA28EA66AFE2D6C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0EB6C76F68679844EC72178F /* Foundation.framework */; }; + 0318E7E610501FC1F958251B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3342ACCE085010828CF63565 /* Assets.xcassets */; }; + 19F735674999FD63AB1C566F /* CoachWidgetSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96752F30FFA0FAA9E42F9BBA /* CoachWidgetSnapshot.swift */; }; + 1B690F0D16AB76A6854CA1F7 /* CoachLiveActivityAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 431C7B10248D8EED4D397AB0 /* CoachLiveActivityAttributes.swift */; }; + 21B242F8E61FB07C476C477C /* CoachLiveBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9DF3346C49A690C3C3DF2F3 /* CoachLiveBridge.swift */; }; + 23F47FD81F646516727B5317 /* RoutineStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 969DB880395BDEB107C9F2FE /* RoutineStore.swift */; }; + 290D0F17978B7EF3DDB3A792 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A06CDFF5B4F7852B6329862 /* ContentView.swift */; }; + 2BAD3233026A4DFEEA02EAE8 /* CoachWidgetBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11ECAD3DB1486DE606285921 /* CoachWidgetBridge.swift */; }; + 2F86A358498667B66E5EFC60 /* CoachRoutineBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97BC6E07E6984342AE95C312 /* CoachRoutineBridge.swift */; }; + 2FAD9763203C412B000D30F8 /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 2FAD9762203C412B000D30F8 /* config.xml */; }; + 3E6740C521EF14892687BCF7 /* CoachWatch.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 2517374227A4072A4D6AFC15 /* CoachWatch.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 436442D6BF54833C59D9E668 /* WorkoutManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AC9C9B9971F55027D227A06 /* WorkoutManager.swift */; }; + 4D22ABE92AF431CB00220026 /* CapApp-SPM in Frameworks */ = {isa = PBXBuildFile; productRef = 4D22ABE82AF431CB00220026 /* CapApp-SPM */; }; + 50379B232058CBB4000EE86E /* capacitor.config.json in Resources */ = {isa = PBXBuildFile; fileRef = 50379B222058CBB4000EE86E /* capacitor.config.json */; }; + 504EC3081FED79650016851F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504EC3071FED79650016851F /* AppDelegate.swift */; }; + 504EC30D1FED79650016851F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30B1FED79650016851F /* Main.storyboard */; }; + 504EC30F1FED79650016851F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 504EC30E1FED79650016851F /* Assets.xcassets */; }; + 504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 504EC3101FED79650016851F /* LaunchScreen.storyboard */; }; + 50B271D11FEDC1A000F3C39B /* public in Resources */ = {isa = PBXBuildFile; fileRef = 50B271D01FEDC1A000F3C39B /* public */; }; + 543A7005429A43F54C0EC61B /* CoachWatchApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6BEAEF6F6274D61CAF22636 /* CoachWatchApp.swift */; }; + 548F8BFA06417B35474BD69E /* CoachLiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 340B99D5EA4DB985D7DFDA10 /* CoachLiveView.swift */; }; + 60061E60061E60061E060001 /* CoachGoogleAuth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60061E60061E60061E060002 /* CoachGoogleAuth.swift */; }; + 6442A95576AFC77377D0DC61 /* RoutineGuidedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2D78A1BF31D30C5AEC24E7C /* RoutineGuidedView.swift */; }; + 694B2F69591CAA85CE5DEC3A /* CoachLiveActivityWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBBF61A35F291A021BA75C60 /* CoachLiveActivityWidget.swift */; }; + 79A94FD334CC9EC24D1FB700 /* CoachWidgets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0276928E86E785EEA434057C /* CoachWidgets.swift */; }; + 880A76D1302B601000F582D5 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 880A76D0302B601000F582D5 /* WidgetKit.framework */; }; + 880A76D3302B601000F582D5 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 880A76D2302B601000F582D5 /* SwiftUI.framework */; }; + 880A76DE302B601100F582D5 /* CoachWatchWidgetsExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 880A76CF302B601000F582D5 /* CoachWatchWidgetsExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 880A76E6302B62FB00F582D5 /* CoachWidgetSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96752F30FFA0FAA9E42F9BBA /* CoachWidgetSnapshot.swift */; }; + 88924CCE2FD2A733002F3A80 /* GoogleSignIn in Frameworks */ = {isa = PBXBuildFile; productRef = 88924CCD2FD2A733002F3A80 /* GoogleSignIn */; }; + 88ABE0043024C45A002636FD /* CoachQuickLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88ABE0023024C45A002636FD /* CoachQuickLog.swift */; }; + 88ABE0053024C45A002636FD /* CoachQuickSync.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88ABE0033024C45A002636FD /* CoachQuickSync.swift */; }; + 88ABE0073024C498002636FD /* CoachQuickLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88ABE0023024C45A002636FD /* CoachQuickLog.swift */; }; + 88ABE0093024C51D002636FD /* CoachQuickWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88ABE0083024C51D002636FD /* CoachQuickWidget.swift */; }; + 88D1DD5E302B46B000B9BA42 /* CoachAuth.swift.example in Resources */ = {isa = PBXBuildFile; fileRef = 88D1DD5D302B46B000B9BA42 /* CoachAuth.swift.example */; }; + 88D1DD5F302B46B000B9BA42 /* CoachAuth.swift.example in Resources */ = {isa = PBXBuildFile; fileRef = 88D1DD5D302B46B000B9BA42 /* CoachAuth.swift.example */; }; + 88F28EB12FBB330E00E8306E /* CoachWorkoutObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F28EB02FBB330E00E8306E /* CoachWorkoutObserver.swift */; }; + 95D0478A499056FE922211EA /* RoutineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA5C5902EFB7F60563678E46 /* RoutineView.swift */; }; + 97116C31D4CC40F71A6A0FE7 /* LiveStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6030BD533EBC2D1D26DB9479 /* LiveStore.swift */; }; + 97600B69ADF2F19B56E79621 /* CoachWidgetSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96752F30FFA0FAA9E42F9BBA /* CoachWidgetSnapshot.swift */; }; + 9BED4C04C38FCB8634CE2A94 /* CoachLiveActivity.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 9B5664FCDB4DDE62514D3A1E /* CoachLiveActivity.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 9E88D51C0B0255D24274DACC /* CoachLiveActivityBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BA75EEC3CBF1F46A9028C66 /* CoachLiveActivityBundle.swift */; }; + A99E51A99E51A99E51A90001 /* CoachAppleAuth.swift in Sources */ = {isa = PBXBuildFile; fileRef = A99E51A99E51A99E51A90002 /* CoachAppleAuth.swift */; }; + B06AB24B350B221F38D99E17 /* ConnectivityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A420239FC6D065C8A599B61C /* ConnectivityManager.swift */; }; + B130613187FE0661DDF636C9 /* CoachWidgetSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96752F30FFA0FAA9E42F9BBA /* CoachWidgetSnapshot.swift */; }; + C0AC4A07811751FB78AA0001 /* CoachAuth.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0AC4A07811751FB78AA0002 /* CoachAuth.swift */; }; + D1384CFA4960060CDBF05FC3 /* CoachLiveActivityAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 431C7B10248D8EED4D397AB0 /* CoachLiveActivityAttributes.swift */; }; + D1BD5B1990CF3F2B9C5D0001 /* CoachWorkoutKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1BD5B1990CF3F2B9C5D0002 /* CoachWorkoutKit.swift */; }; + E1E8BD7CF9C19E56CE0F57C4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D61D7B2F5AFEF834423E07AB /* Foundation.framework */; }; + E2CE6C2AA1DF4F3CAD6E0001 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2CE6C2AA1DF4F3CAD6E0002 /* MainViewController.swift */; }; + E547F675B2F61C3475D2A787 /* LiveActivityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B93DA6B121E94B11DF938C90 /* LiveActivityManager.swift */; }; + F1ABCDEF0123456789AB0001 /* CoachHealthRoute.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1ABCDEF0123456789AB0002 /* CoachHealthRoute.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 3063F4D3E3903D2EB4956B44 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 504EC2FC1FED79650016851F /* Project object */; + proxyType = 1; + remoteGlobalIDString = D5BF41648D334DC24770B9D2; + remoteInfo = CoachWatch; + }; + 880A76DC302B601100F582D5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 504EC2FC1FED79650016851F /* Project object */; + proxyType = 1; + remoteGlobalIDString = 880A76CE302B601000F582D5; + remoteInfo = CoachWatchWidgetsExtension; + }; + 9D160400D2AE8723B1112F2F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 504EC2FC1FED79650016851F /* Project object */; + proxyType = 1; + remoteGlobalIDString = 28FB3582F417B2F3C6BFC5D1; + remoteInfo = CoachLiveActivity; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 880A76DF302B601100F582D5 /* Embed Foundation Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 880A76DE302B601100F582D5 /* CoachWatchWidgetsExtension.appex in Embed Foundation Extensions */, + ); + name = "Embed Foundation Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; + C4916F81E61FABAAD62EE4F9 /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 9BED4C04C38FCB8634CE2A94 /* CoachLiveActivity.appex in Embed App Extensions */, + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; + F50D9A7DFABB52EE96BB93D6 /* Embed Watch Content */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(CONTENTS_FOLDER_PATH)/Watch"; + dstSubfolderSpec = 16; + files = ( + 3E6740C521EF14892687BCF7 /* CoachWatch.app in Embed Watch Content */, + ); + name = "Embed Watch Content"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0276928E86E785EEA434057C /* CoachWidgets.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CoachWidgets.swift; sourceTree = ""; }; + 0EB6C76F68679844EC72178F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS11.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 11ECAD3DB1486DE606285921 /* CoachWidgetBridge.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CoachWidgetBridge.swift; sourceTree = ""; }; + 1BA75EEC3CBF1F46A9028C66 /* CoachLiveActivityBundle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CoachLiveActivityBundle.swift; sourceTree = ""; }; + 2517374227A4072A4D6AFC15 /* CoachWatch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CoachWatch.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 2FAD9762203C412B000D30F8 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = config.xml; sourceTree = ""; }; + 3342ACCE085010828CF63565 /* Assets.xcassets */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 340B99D5EA4DB985D7DFDA10 /* CoachLiveView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CoachLiveView.swift; sourceTree = ""; }; + 431C7B10248D8EED4D397AB0 /* CoachLiveActivityAttributes.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CoachLiveActivityAttributes.swift; sourceTree = ""; }; + 50379B222058CBB4000EE86E /* capacitor.config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = capacitor.config.json; sourceTree = ""; }; + 504EC3041FED79650016851F /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 504EC3071FED79650016851F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 504EC30C1FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 504EC30E1FED79650016851F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 504EC3111FED79650016851F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 504EC3131FED79650016851F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 50B271D01FEDC1A000F3C39B /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = ""; }; + 60061E60061E60061E060002 /* CoachGoogleAuth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoachGoogleAuth.swift; sourceTree = ""; }; + 6030BD533EBC2D1D26DB9479 /* LiveStore.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiveStore.swift; sourceTree = ""; }; + 82122ACF7E5A608AD1D55D24 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 880A76CF302B601000F582D5 /* CoachWatchWidgetsExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = CoachWatchWidgetsExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 880A76D0302B601000F582D5 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; }; + 880A76D2302B601000F582D5 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; }; + 880A76E7302B634400F582D5 /* CoachWatchWidgetsExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = CoachWatchWidgetsExtension.entitlements; sourceTree = ""; }; + 884A1F9D3020E3C100457184 /* CoachLiveActivity.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = CoachLiveActivity.entitlements; sourceTree = ""; }; + 88A837392FAA741C00DDD144 /* App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = App.entitlements; sourceTree = ""; }; + 88ABE0023024C45A002636FD /* CoachQuickLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoachQuickLog.swift; sourceTree = ""; }; + 88ABE0033024C45A002636FD /* CoachQuickSync.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoachQuickSync.swift; sourceTree = ""; }; + 88ABE0083024C51D002636FD /* CoachQuickWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoachQuickWidget.swift; sourceTree = ""; }; + 88D1DD5D302B46B000B9BA42 /* CoachAuth.swift.example */ = {isa = PBXFileReference; lastKnownFileType = text; path = CoachAuth.swift.example; sourceTree = ""; }; + 88F28EB02FBB330E00E8306E /* CoachWorkoutObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoachWorkoutObserver.swift; sourceTree = ""; }; + 8A06CDFF5B4F7852B6329862 /* ContentView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 8AC9C9B9971F55027D227A06 /* WorkoutManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WorkoutManager.swift; sourceTree = ""; }; + 958DCC722DB07C7200EA8C5F /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = debug.xcconfig; path = ../debug.xcconfig; sourceTree = SOURCE_ROOT; }; + 96752F30FFA0FAA9E42F9BBA /* CoachWidgetSnapshot.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CoachWidgetSnapshot.swift; sourceTree = ""; }; + 969DB880395BDEB107C9F2FE /* RoutineStore.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = RoutineStore.swift; sourceTree = ""; }; + 97BC6E07E6984342AE95C312 /* CoachRoutineBridge.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CoachRoutineBridge.swift; sourceTree = ""; }; + 9B5664FCDB4DDE62514D3A1E /* CoachLiveActivity.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = CoachLiveActivity.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + A420239FC6D065C8A599B61C /* ConnectivityManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ConnectivityManager.swift; sourceTree = ""; }; + A99E51A99E51A99E51A90002 /* CoachAppleAuth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoachAppleAuth.swift; sourceTree = ""; }; + A9DF3346C49A690C3C3DF2F3 /* CoachLiveBridge.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CoachLiveBridge.swift; sourceTree = ""; }; + AA5C5902EFB7F60563678E46 /* RoutineView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = RoutineView.swift; sourceTree = ""; }; + B93DA6B121E94B11DF938C90 /* LiveActivityManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LiveActivityManager.swift; sourceTree = ""; }; + C0AC4A07811751FB78AA0002 /* CoachAuth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoachAuth.swift; sourceTree = ""; }; + C2D78A1BF31D30C5AEC24E7C /* RoutineGuidedView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = RoutineGuidedView.swift; sourceTree = ""; }; + D09B589FA572B2C14E8CD835 /* CoachWatch.entitlements */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.entitlements; path = CoachWatch.entitlements; sourceTree = ""; }; + D1BD5B1990CF3F2B9C5D0002 /* CoachWorkoutKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoachWorkoutKit.swift; sourceTree = ""; }; + D61D7B2F5AFEF834423E07AB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + E2CE6C2AA1DF4F3CAD6E0002 /* MainViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = ""; }; + EBBF61A35F291A021BA75C60 /* CoachLiveActivityWidget.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CoachLiveActivityWidget.swift; sourceTree = ""; }; + F1ABCDEF0123456789AB0002 /* CoachHealthRoute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoachHealthRoute.swift; sourceTree = ""; }; + F6BEAEF6F6274D61CAF22636 /* CoachWatchApp.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CoachWatchApp.swift; sourceTree = ""; }; + FBFCA969A1B083CD3178D9B2 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + 880A76E2302B601100F582D5 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Info.plist, + ); + target = 880A76CE302B601000F582D5 /* CoachWatchWidgetsExtension */; + }; +/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + 880A76D4302B601000F582D5 /* CoachWatchWidgets */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (880A76E2302B601100F582D5 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = CoachWatchWidgets; sourceTree = ""; }; +/* End PBXFileSystemSynchronizedRootGroup section */ + +/* Begin PBXFrameworksBuildPhase section */ + 504EC3011FED79650016851F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D22ABE92AF431CB00220026 /* CapApp-SPM in Frameworks */, + 88924CCE2FD2A733002F3A80 /* GoogleSignIn in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 85FFFE3727FD44280013FE19 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 01468471ECA28EA66AFE2D6C /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 880A76CC302B601000F582D5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 880A76D3302B601000F582D5 /* SwiftUI.framework in Frameworks */, + 880A76D1302B601000F582D5 /* WidgetKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D8B443A150F5A7E1C135ABAA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E1E8BD7CF9C19E56CE0F57C4 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 3E58B60E9B4F1CA14B5EC667 /* watchOS */ = { + isa = PBXGroup; + children = ( + 0EB6C76F68679844EC72178F /* Foundation.framework */, + ); + name = watchOS; + sourceTree = ""; + }; + 460F58BF290358F572689016 /* CoachLiveActivity */ = { + isa = PBXGroup; + children = ( + 88ABE0083024C51D002636FD /* CoachQuickWidget.swift */, + 884A1F9D3020E3C100457184 /* CoachLiveActivity.entitlements */, + 431C7B10248D8EED4D397AB0 /* CoachLiveActivityAttributes.swift */, + EBBF61A35F291A021BA75C60 /* CoachLiveActivityWidget.swift */, + 1BA75EEC3CBF1F46A9028C66 /* CoachLiveActivityBundle.swift */, + 0276928E86E785EEA434057C /* CoachWidgets.swift */, + FBFCA969A1B083CD3178D9B2 /* Info.plist */, + ); + path = CoachLiveActivity; + sourceTree = ""; + }; + 504EC2FB1FED79650016851F = { + isa = PBXGroup; + children = ( + 880A76E7302B634400F582D5 /* CoachWatchWidgetsExtension.entitlements */, + 958DCC722DB07C7200EA8C5F /* debug.xcconfig */, + 504EC3061FED79650016851F /* App */, + 880A76D4302B601000F582D5 /* CoachWatchWidgets */, + 504EC3051FED79650016851F /* Products */, + B91ACF72653FD495148698CF /* Frameworks */, + 5A8EA0CF92316E437E9053A0 /* CoachWatch */, + 460F58BF290358F572689016 /* CoachLiveActivity */, + ); + sourceTree = ""; + }; + 504EC3051FED79650016851F /* Products */ = { + isa = PBXGroup; + children = ( + 504EC3041FED79650016851F /* App.app */, + 2517374227A4072A4D6AFC15 /* CoachWatch.app */, + 9B5664FCDB4DDE62514D3A1E /* CoachLiveActivity.appex */, + 880A76CF302B601000F582D5 /* CoachWatchWidgetsExtension.appex */, + ); + name = Products; + sourceTree = ""; + }; + 504EC3061FED79650016851F /* App */ = { + isa = PBXGroup; + children = ( + 88ABE0023024C45A002636FD /* CoachQuickLog.swift */, + 88ABE0033024C45A002636FD /* CoachQuickSync.swift */, + 88A837392FAA741C00DDD144 /* App.entitlements */, + 88D1DD5D302B46B000B9BA42 /* CoachAuth.swift.example */, + 88F28EB02FBB330E00E8306E /* CoachWorkoutObserver.swift */, + 50379B222058CBB4000EE86E /* capacitor.config.json */, + 504EC3071FED79650016851F /* AppDelegate.swift */, + C0AC4A07811751FB78AA0002 /* CoachAuth.swift */, + D1BD5B1990CF3F2B9C5D0002 /* CoachWorkoutKit.swift */, + F1ABCDEF0123456789AB0002 /* CoachHealthRoute.swift */, + A99E51A99E51A99E51A90002 /* CoachAppleAuth.swift */, + 60061E60061E60061E060002 /* CoachGoogleAuth.swift */, + E2CE6C2AA1DF4F3CAD6E0002 /* MainViewController.swift */, + 504EC30B1FED79650016851F /* Main.storyboard */, + 504EC30E1FED79650016851F /* Assets.xcassets */, + 504EC3101FED79650016851F /* LaunchScreen.storyboard */, + 504EC3131FED79650016851F /* Info.plist */, + 2FAD9762203C412B000D30F8 /* config.xml */, + 50B271D01FEDC1A000F3C39B /* public */, + A9DF3346C49A690C3C3DF2F3 /* CoachLiveBridge.swift */, + 96752F30FFA0FAA9E42F9BBA /* CoachWidgetSnapshot.swift */, + 11ECAD3DB1486DE606285921 /* CoachWidgetBridge.swift */, + 97BC6E07E6984342AE95C312 /* CoachRoutineBridge.swift */, + 6030BD533EBC2D1D26DB9479 /* LiveStore.swift */, + 340B99D5EA4DB985D7DFDA10 /* CoachLiveView.swift */, + B93DA6B121E94B11DF938C90 /* LiveActivityManager.swift */, + ); + path = App; + sourceTree = ""; + }; + 5A8EA0CF92316E437E9053A0 /* CoachWatch */ = { + isa = PBXGroup; + children = ( + F6BEAEF6F6274D61CAF22636 /* CoachWatchApp.swift */, + 8A06CDFF5B4F7852B6329862 /* ContentView.swift */, + 82122ACF7E5A608AD1D55D24 /* Info.plist */, + D09B589FA572B2C14E8CD835 /* CoachWatch.entitlements */, + A420239FC6D065C8A599B61C /* ConnectivityManager.swift */, + AA5C5902EFB7F60563678E46 /* RoutineView.swift */, + C2D78A1BF31D30C5AEC24E7C /* RoutineGuidedView.swift */, + 969DB880395BDEB107C9F2FE /* RoutineStore.swift */, + 8AC9C9B9971F55027D227A06 /* WorkoutManager.swift */, + 3342ACCE085010828CF63565 /* Assets.xcassets */, + ); + path = CoachWatch; + sourceTree = ""; + }; + 7497026ECEFF81CCD11C289D /* iOS */ = { + isa = PBXGroup; + children = ( + D61D7B2F5AFEF834423E07AB /* Foundation.framework */, + ); + name = iOS; + sourceTree = ""; + }; + B91ACF72653FD495148698CF /* Frameworks */ = { + isa = PBXGroup; + children = ( + 3E58B60E9B4F1CA14B5EC667 /* watchOS */, + 7497026ECEFF81CCD11C289D /* iOS */, + 880A76D0302B601000F582D5 /* WidgetKit.framework */, + 880A76D2302B601000F582D5 /* SwiftUI.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 28FB3582F417B2F3C6BFC5D1 /* CoachLiveActivity */ = { + isa = PBXNativeTarget; + buildConfigurationList = C2671D2741138A4A55CE1ED0 /* Build configuration list for PBXNativeTarget "CoachLiveActivity" */; + buildPhases = ( + 2D25180D64B3326AE6F9D91B /* Sources */, + D8B443A150F5A7E1C135ABAA /* Frameworks */, + 411CB19BB5DB127758A86A2D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = CoachLiveActivity; + productName = CoachLiveActivity; + productReference = 9B5664FCDB4DDE62514D3A1E /* CoachLiveActivity.appex */; + productType = "com.apple.product-type.app-extension"; + }; + 504EC3031FED79650016851F /* App */ = { + isa = PBXNativeTarget; + buildConfigurationList = 504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "App" */; + buildPhases = ( + 504EC3001FED79650016851F /* Sources */, + 504EC3011FED79650016851F /* Frameworks */, + 504EC3021FED79650016851F /* Resources */, + F50D9A7DFABB52EE96BB93D6 /* Embed Watch Content */, + C4916F81E61FABAAD62EE4F9 /* Embed App Extensions */, + ); + buildRules = ( + ); + dependencies = ( + EEEAB45810829EE8B3C4976E /* PBXTargetDependency */, + BACE810C3CD85E302BBFEC84 /* PBXTargetDependency */, + ); + name = App; + packageProductDependencies = ( + 4D22ABE82AF431CB00220026 /* CapApp-SPM */, + 88924CCD2FD2A733002F3A80 /* GoogleSignIn */, + ); + productName = App; + productReference = 504EC3041FED79650016851F /* App.app */; + productType = "com.apple.product-type.application"; + }; + 880A76CE302B601000F582D5 /* CoachWatchWidgetsExtension */ = { + isa = PBXNativeTarget; + buildConfigurationList = 880A76E3302B601100F582D5 /* Build configuration list for PBXNativeTarget "CoachWatchWidgetsExtension" */; + buildPhases = ( + 880A76CB302B601000F582D5 /* Sources */, + 880A76CC302B601000F582D5 /* Frameworks */, + 880A76CD302B601000F582D5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 880A76D4302B601000F582D5 /* CoachWatchWidgets */, + ); + name = CoachWatchWidgetsExtension; + packageProductDependencies = ( + ); + productName = CoachWatchWidgetsExtension; + productReference = 880A76CF302B601000F582D5 /* CoachWatchWidgetsExtension.appex */; + productType = "com.apple.product-type.app-extension"; + }; + D5BF41648D334DC24770B9D2 /* CoachWatch */ = { + isa = PBXNativeTarget; + buildConfigurationList = FA2A9602402AA384726BFF97 /* Build configuration list for PBXNativeTarget "CoachWatch" */; + buildPhases = ( + E1B262849E79F8569984E173 /* Sources */, + 85FFFE3727FD44280013FE19 /* Frameworks */, + CFD58983FA62853BAD4DC405 /* Resources */, + 880A76DF302B601100F582D5 /* Embed Foundation Extensions */, + ); + buildRules = ( + ); + dependencies = ( + 880A76DD302B601100F582D5 /* PBXTargetDependency */, + ); + name = CoachWatch; + productName = CoachWatch; + productReference = 2517374227A4072A4D6AFC15 /* CoachWatch.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 504EC2FC1FED79650016851F /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 2660; + LastUpgradeCheck = 2650; + TargetAttributes = { + 504EC3031FED79650016851F = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + }; + 880A76CE302B601000F582D5 = { + CreatedOnToolsVersion = 26.6; + }; + }; + }; + buildConfigurationList = 504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 504EC2FB1FED79650016851F; + packageReferences = ( + D4C12C0A2AAA248700AAC8A2 /* XCLocalSwiftPackageReference "CapApp-SPM" */, + 88924CCC2FD2A663002F3A80 /* XCRemoteSwiftPackageReference "GoogleSignIn-iOS" */, + ); + productRefGroup = 504EC3051FED79650016851F /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 504EC3031FED79650016851F /* App */, + D5BF41648D334DC24770B9D2 /* CoachWatch */, + 28FB3582F417B2F3C6BFC5D1 /* CoachLiveActivity */, + 880A76CE302B601000F582D5 /* CoachWatchWidgetsExtension */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 411CB19BB5DB127758A86A2D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 88D1DD5F302B46B000B9BA42 /* CoachAuth.swift.example in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 504EC3021FED79650016851F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 88D1DD5E302B46B000B9BA42 /* CoachAuth.swift.example in Resources */, + 504EC3121FED79650016851F /* LaunchScreen.storyboard in Resources */, + 50B271D11FEDC1A000F3C39B /* public in Resources */, + 504EC30F1FED79650016851F /* Assets.xcassets in Resources */, + 50379B232058CBB4000EE86E /* capacitor.config.json in Resources */, + 504EC30D1FED79650016851F /* Main.storyboard in Resources */, + 2FAD9763203C412B000D30F8 /* config.xml in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 880A76CD302B601000F582D5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CFD58983FA62853BAD4DC405 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0318E7E610501FC1F958251B /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 2D25180D64B3326AE6F9D91B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 79A94FD334CC9EC24D1FB700 /* CoachWidgets.swift in Sources */, + 19F735674999FD63AB1C566F /* CoachWidgetSnapshot.swift in Sources */, + 1B690F0D16AB76A6854CA1F7 /* CoachLiveActivityAttributes.swift in Sources */, + 694B2F69591CAA85CE5DEC3A /* CoachLiveActivityWidget.swift in Sources */, + 9E88D51C0B0255D24274DACC /* CoachLiveActivityBundle.swift in Sources */, + 88ABE0073024C498002636FD /* CoachQuickLog.swift in Sources */, + 88ABE0093024C51D002636FD /* CoachQuickWidget.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 504EC3001FED79650016851F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B130613187FE0661DDF636C9 /* CoachWidgetSnapshot.swift in Sources */, + 2BAD3233026A4DFEEA02EAE8 /* CoachWidgetBridge.swift in Sources */, + 504EC3081FED79650016851F /* AppDelegate.swift in Sources */, + C0AC4A07811751FB78AA0001 /* CoachAuth.swift in Sources */, + D1BD5B1990CF3F2B9C5D0001 /* CoachWorkoutKit.swift in Sources */, + 88ABE0043024C45A002636FD /* CoachQuickLog.swift in Sources */, + 88ABE0053024C45A002636FD /* CoachQuickSync.swift in Sources */, + F1ABCDEF0123456789AB0001 /* CoachHealthRoute.swift in Sources */, + A99E51A99E51A99E51A90001 /* CoachAppleAuth.swift in Sources */, + 60061E60061E60061E060001 /* CoachGoogleAuth.swift in Sources */, + 88F28EB12FBB330E00E8306E /* CoachWorkoutObserver.swift in Sources */, + E2CE6C2AA1DF4F3CAD6E0001 /* MainViewController.swift in Sources */, + 21B242F8E61FB07C476C477C /* CoachLiveBridge.swift in Sources */, + 2F86A358498667B66E5EFC60 /* CoachRoutineBridge.swift in Sources */, + 97116C31D4CC40F71A6A0FE7 /* LiveStore.swift in Sources */, + 548F8BFA06417B35474BD69E /* CoachLiveView.swift in Sources */, + D1384CFA4960060CDBF05FC3 /* CoachLiveActivityAttributes.swift in Sources */, + E547F675B2F61C3475D2A787 /* LiveActivityManager.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 880A76CB302B601000F582D5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 880A76E6302B62FB00F582D5 /* CoachWidgetSnapshot.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E1B262849E79F8569984E173 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97600B69ADF2F19B56E79621 /* CoachWidgetSnapshot.swift in Sources */, + 543A7005429A43F54C0EC61B /* CoachWatchApp.swift in Sources */, + 290D0F17978B7EF3DDB3A792 /* ContentView.swift in Sources */, + B06AB24B350B221F38D99E17 /* ConnectivityManager.swift in Sources */, + 95D0478A499056FE922211EA /* RoutineView.swift in Sources */, + 6442A95576AFC77377D0DC61 /* RoutineGuidedView.swift in Sources */, + 23F47FD81F646516727B5317 /* RoutineStore.swift in Sources */, + 436442D6BF54833C59D9E668 /* WorkoutManager.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 880A76DD302B601100F582D5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 880A76CE302B601000F582D5 /* CoachWatchWidgetsExtension */; + targetProxy = 880A76DC302B601100F582D5 /* PBXContainerItemProxy */; + }; + BACE810C3CD85E302BBFEC84 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = CoachLiveActivity; + target = 28FB3582F417B2F3C6BFC5D1 /* CoachLiveActivity */; + targetProxy = 9D160400D2AE8723B1112F2F /* PBXContainerItemProxy */; + }; + EEEAB45810829EE8B3C4976E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = CoachWatch; + target = D5BF41648D334DC24770B9D2 /* CoachWatch */; + targetProxy = 3063F4D3E3903D2EB4956B44 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 504EC30B1FED79650016851F /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 504EC30C1FED79650016851F /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 504EC3101FED79650016851F /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 504EC3111FED79650016851F /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 09CEF8C9131E8948450FEC27 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = ""; + CODE_SIGN_ENTITLEMENTS = CoachWatch/CoachWatch.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 22; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = CoachWatch/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.2; + PRODUCT_BUNDLE_IDENTIFIER = ch.hypnotruck.coach.watchkitapp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 11.0; + }; + name = Debug; + }; + 504EC3141FED79650016851F /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 958DCC722DB07C7200EA8C5F /* debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = TZ2PVTRKNY; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 504EC3151FED79650016851F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = TZ2PVTRKNY; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 504EC3171FED79650016851F /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 958DCC722DB07C7200EA8C5F /* debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; + CODE_SIGN_ENTITLEMENTS = App/App.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 22; + INFOPLIST_FILE = App/Info.plist; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.healthcare-fitness"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.2; + OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; + PRODUCT_BUNDLE_IDENTIFIER = ch.hypnotruck.coach; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 504EC3181FED79650016851F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; + CODE_SIGN_ENTITLEMENTS = App/App.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 22; + INFOPLIST_FILE = App/Info.plist; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.healthcare-fitness"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.2; + PRODUCT_BUNDLE_IDENTIFIER = ch.hypnotruck.coach; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ""; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 6BD679ED799FBBFC9D3BE40C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = ""; + CODE_SIGN_ENTITLEMENTS = CoachWatch/CoachWatch.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 22; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = CoachWatch/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.2; + PRODUCT_BUNDLE_IDENTIFIER = ch.hypnotruck.coach.watchkitapp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ""; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + VALIDATE_PRODUCT = YES; + WATCHOS_DEPLOYMENT_TARGET = 11.0; + }; + name = Release; + }; + 880A76E0302B601100F582D5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CODE_SIGN_ENTITLEMENTS = CoachWatchWidgetsExtension.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 22; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = CoachWatchWidgets/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = CoachWatchWidgets; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + "@executable_path/../../../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.2; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = ch.hypnotruck.coach.watchkitapp.CoachWatchWidgets; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 26.5; + }; + name = Debug; + }; + 880A76E1302B601100F582D5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CODE_SIGN_ENTITLEMENTS = CoachWatchWidgetsExtension.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 22; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = CoachWatchWidgets/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = CoachWatchWidgets; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + "@executable_path/../../../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.2; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = ch.hypnotruck.coach.watchkitapp.CoachWatchWidgets; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 26.5; + }; + name = Release; + }; + 90CE3C22F60C6432852DC1B1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = ""; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_ENTITLEMENTS = CoachLiveActivity/CoachLiveActivity.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 22; + DEVELOPMENT_TEAM = TZ2PVTRKNY; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = CoachLiveActivity/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 17.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.2; + PRODUCT_BUNDLE_IDENTIFIER = ch.hypnotruck.coach.LiveActivity; + PRODUCT_NAME = CoachLiveActivity; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + C7A0838F3DA0842EDE320050 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = ""; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_ENTITLEMENTS = CoachLiveActivity/CoachLiveActivity.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 22; + DEVELOPMENT_TEAM = TZ2PVTRKNY; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = CoachLiveActivity/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 17.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.2; + PRODUCT_BUNDLE_IDENTIFIER = ch.hypnotruck.coach.LiveActivity; + PRODUCT_NAME = CoachLiveActivity; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 504EC2FF1FED79650016851F /* Build configuration list for PBXProject "App" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 504EC3141FED79650016851F /* Debug */, + 504EC3151FED79650016851F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 504EC3161FED79650016851F /* Build configuration list for PBXNativeTarget "App" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 504EC3171FED79650016851F /* Debug */, + 504EC3181FED79650016851F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 880A76E3302B601100F582D5 /* Build configuration list for PBXNativeTarget "CoachWatchWidgetsExtension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 880A76E0302B601100F582D5 /* Debug */, + 880A76E1302B601100F582D5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C2671D2741138A4A55CE1ED0 /* Build configuration list for PBXNativeTarget "CoachLiveActivity" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C7A0838F3DA0842EDE320050 /* Release */, + 90CE3C22F60C6432852DC1B1 /* Debug */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FA2A9602402AA384726BFF97 /* Build configuration list for PBXNativeTarget "CoachWatch" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6BD679ED799FBBFC9D3BE40C /* Release */, + 09CEF8C9131E8948450FEC27 /* Debug */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + D4C12C0A2AAA248700AAC8A2 /* XCLocalSwiftPackageReference "CapApp-SPM" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = "CapApp-SPM"; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 88924CCC2FD2A663002F3A80 /* XCRemoteSwiftPackageReference "GoogleSignIn-iOS" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/google/GoogleSignIn-iOS"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 9.1.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 4D22ABE82AF431CB00220026 /* CapApp-SPM */ = { + isa = XCSwiftPackageProductDependency; + package = D4C12C0A2AAA248700AAC8A2 /* XCLocalSwiftPackageReference "CapApp-SPM" */; + productName = "CapApp-SPM"; + }; + 88924CCD2FD2A733002F3A80 /* GoogleSignIn */ = { + isa = XCSwiftPackageProductDependency; + package = 88924CCC2FD2A663002F3A80 /* XCRemoteSwiftPackageReference "GoogleSignIn-iOS" */; + productName = GoogleSignIn; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 504EC2FC1FED79650016851F /* Project object */; +} diff --git a/ios/App/App/CoachLiveBridge.swift b/ios/App/App/CoachLiveBridge.swift index 859f981..6103339 100644 --- a/ios/App/App/CoachLiveBridge.swift +++ b/ios/App/App/CoachLiveBridge.swift @@ -135,6 +135,14 @@ extension CoachLiveBridgePlugin: WCSessionDelegate { ) return true } + // Résultat d'un test de VMA fait au poignet. Même aiguillage que la + // routine : ce plugin est l'unique WCSession.delegate côté iPhone. + if message["vmaTest"] as? Bool == true { + NotificationCenter.default.post( + name: .coachVmaFromWatch, object: nil, userInfo: message + ) + return true + } // Pause / reprise : pilote le libellé du bouton de la Live Activity. if let paused = message["paused"] as? Bool { liveLog.info("état pause reçu de la Watch : \(paused, privacy: .public)") diff --git a/ios/App/App/CoachRoutineBridge.swift b/ios/App/App/CoachRoutineBridge.swift index 4e0363f..5bdc3f2 100644 --- a/ios/App/App/CoachRoutineBridge.swift +++ b/ios/App/App/CoachRoutineBridge.swift @@ -10,6 +10,8 @@ private let routineLog = Logger(subsystem: "ch.hypnotruck.coach", category: "rou /// message et le relaie ici plutôt que de l'émettre comme sample de séance. extension Notification.Name { static let coachRoutineFromWatch = Notification.Name("coachRoutineFromWatch") + /// Résultat d'un test de VMA fait au poignet, relayé par le même aiguillage. + static let coachVmaFromWatch = Notification.Name("coachVmaFromWatch") } /// Pont routine quotidienne iPhone ↔ Apple Watch. @@ -46,6 +48,16 @@ public class CoachRoutineBridgePlugin: CAPPlugin, CAPBridgedPlugin { name: .coachRoutineFromWatch, object: nil ) + // Le test de VMA vit dans ce plugin plutôt que dans un fichier dédié : + // il a déjà l'abonnement NotificationCenter, la base d'API et le cookie + // d'authentification, et un fichier de plus devrait être câblé à la main + // dans le pbxproj (la cible App n'est pas un dossier synchronisé). + NotificationCenter.default.addObserver( + self, + selector: #selector(handleVmaFromWatch(_:)), + name: .coachVmaFromWatch, + object: nil + ) } deinit { @@ -184,6 +196,54 @@ public class CoachRoutineBridgePlugin: CAPPlugin, CAPBridgedPlugin { } } + // MARK: - Test de VMA fait au poignet + + /// La montre n'envoie que des MESURES (paliers tenus, distance, FC max) ; + /// le calcul de la VMA se fait côté serveur, en un seul endroit. Deux + /// implémentations d'une même formule finissent toujours par diverger. + @objc private func handleVmaFromWatch(_ note: Notification) { + guard let info = note.userInfo as? [String: Any] else { return } + var body: [String: Any] = [:] + body["protocol"] = info["protocol"] as? String ?? "stages" + if let hr = (info["maxHr"] as? NSNumber)?.intValue, hr > 0 { body["max_hr"] = hr } + if let d = (info["distanceM"] as? NSNumber)?.doubleValue { body["distance_m"] = d } + if let s = (info["startKmh"] as? NSNumber)?.doubleValue { body["start_kmh"] = s } + if let s = (info["stepKmh"] as? NSNumber)?.doubleValue { body["step_kmh"] = s } + if let c = (info["completed"] as? NSNumber)?.intValue { body["completed"] = c } + if let r = (info["partialRatio"] as? NSNumber)?.doubleValue { body["partial_ratio"] = r } + body["note"] = "Test guidé depuis l'Apple Watch" + + postVma(body) { [weak self] ok, kmh in + routineLog.info("POST /api/vma : \(ok ? "ok" : "echec", privacy: .public)") + DispatchQueue.main.async { + self?.notifyListeners("vmaRecorded", data: ["ok": ok, "vma_kmh": kmh ?? 0]) + } + } + } + + private func postVma(_ body: [String: Any], + completion: @escaping (Bool, Double?) -> Void) { + guard let url = URL(string: "\(Self.apiBase)/api/vma") else { + completion(false, nil) + return + } + var req = URLRequest(url: url) + req.httpMethod = "POST" + req.setValue("application/json", forHTTPHeaderField: "Content-Type") + req.setValue("coach_web_token=\(CoachAuth.kCoachWebToken)", forHTTPHeaderField: "Cookie") + req.httpBody = try? JSONSerialization.data(withJSONObject: body) + req.timeoutInterval = 15 + URLSession.shared.dataTask(with: req) { data, response, _ in + let code = (response as? HTTPURLResponse)?.statusCode ?? -1 + guard (200..<300).contains(code), let data = data, + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { + completion(false, nil) + return + } + completion(true, (json["vma_kmh"] as? NSNumber)?.doubleValue) + }.resume() + } + private static func todayISO() -> String { let fmt = DateFormatter() fmt.dateFormat = "yyyy-MM-dd" diff --git a/ios/App/CoachWatch/ConnectivityManager.swift b/ios/App/CoachWatch/ConnectivityManager.swift index ac9638b..76ff341 100644 --- a/ios/App/CoachWatch/ConnectivityManager.swift +++ b/ios/App/CoachWatch/ConnectivityManager.swift @@ -102,6 +102,27 @@ final class ConnectivityManager: NSObject, ObservableObject { return true } + /// Envoie le résultat brut d'un test de VMA (paliers tenus ou distance). + /// + /// Livraison différée garantie comme la routine : un test se fait dehors, + /// l'iPhone peut être hors de portée, et refaire un test maximal parce que + /// le message s'est perdu n'est pas acceptable. Le calcul de la VMA se fait + /// côté serveur — la montre ne transmet que des mesures. + @discardableResult + func sendVmaResult(_ payload: [String: Any]) -> Bool { + let session = WCSession.default + guard session.activationState == .activated else { return false } + if session.isReachable { + session.sendMessage(payload, replyHandler: nil) { _ in + session.transferUserInfo(payload) + } + } else { + session.transferUserInfo(payload) + } + connLog.info("résultat de test VMA envoyé à l'iPhone") + return true + } + /// Signale à l'iPhone que la séance est en pause / a repris, pour que le /// bouton de la Live Activity affiche le bon état. func sendPaused(_ paused: Bool) { diff --git a/ios/App/CoachWatch/ContentView.swift b/ios/App/CoachWatch/ContentView.swift index 28c47ba..638bc53 100644 --- a/ios/App/CoachWatch/ContentView.swift +++ b/ios/App/CoachWatch/ContentView.swift @@ -25,6 +25,7 @@ struct ContentView: View { struct ActivityPickerView: View { @EnvironmentObject private var workout: WorkoutManager @State private var showRoutine = false + @State private var showVma = false private struct Activity: Identifiable { let id = UUID() @@ -63,6 +64,14 @@ struct ActivityPickerView: View { } .tint(.cyan) + Button { + showVma = true + } label: { + Label("Test VMA", systemImage: "speedometer") + .frame(maxWidth: .infinity, alignment: .leading) + } + .tint(.orange) + Button { workout.startSimulation() } label: { @@ -83,6 +92,9 @@ struct ActivityPickerView: View { .sheet(isPresented: $showRoutine) { RoutineView() } + .sheet(isPresented: $showVma) { + VmaTestView() + } } } diff --git a/ios/App/CoachWatch/VmaTestView.swift b/ios/App/CoachWatch/VmaTestView.swift new file mode 100644 index 0000000..49d080a --- /dev/null +++ b/ios/App/CoachWatch/VmaTestView.swift @@ -0,0 +1,255 @@ +// VmaTestView.swift +// Test de VMA guidé au poignet, cible CoachWatch. +// +// Pourquoi au poignet plutôt que sur le téléphone : pendant un test, le +// téléphone est dans une poche. La montre est le seul écran consultable en +// courant, et c'est elle qui porte déjà la vitesse, la distance et la FC via +// WorkoutManager (HKLiveWorkoutBuilder). +// +// ⚠️ Aucun calcul de VMA ici : la vue mesure (paliers tenus, distance) et +// envoie ces mesures à l'iPhone, qui les poste à /api/vma. Le calcul vit dans +// web/vma.py, en un seul endroit — deux implémentations d'une même formule +// finissent toujours par diverger. +// +// ⚠️ Sous bêtabloquant, la FC ne sert PAS à mesurer : elle est affichée pour +// que l'utilisateur voie son plafond arriver, et transmise pour que le serveur +// signale un test interrompu par le cœur plutôt que par les jambes. +import SwiftUI +import HealthKit +import WatchKit + +struct VmaTestView: View { + enum Protocole: String, CaseIterable { + case stages = "Paliers" + case sixMin = "6 minutes" + } + + @StateObject private var workout = WorkoutManager.shared + @Environment(\.dismiss) private var dismiss + + // Paramètres du protocole à paliers. Départ volontairement bas : la marche + // rapide est à 6 km/h, un départ à 8 laisse une vraie marge de montée. + private let startKmh = 8.0 + private let stepKmh = 0.5 + private let stageSeconds = 60.0 + + @State private var proto: Protocole = .stages + @State private var started = false + @State private var finished = false + @State private var stageIndex = 0 // 0 = premier palier en cours + @State private var maxHr = 0.0 + @State private var sent = false + @State private var sendError: String? + + private let tick = Timer.publish(every: 0.2, on: .main, in: .common).autoconnect() + + private var targetKmh: Double { startKmh + stepKmh * Double(stageIndex) } + private var completedStages: Int { stageIndex } // paliers TERMINÉS + private var sixMinRemaining: Double { max(0, 360 - workout.elapsedSec) } + + /// Avancement dans le palier courant, dérivé de la durée de séance et NON + /// d'un compteur accumulé au fil du Timer. + /// + /// ⚠️ Le Timer de la vue ne tourne pas quand l'écran s'éteint — et il + /// s'éteint dès que le poignet retombe, c'est-à-dire pendant l'essentiel du + /// test. Un décompte accumulé dériverait donc de plusieurs secondes par + /// palier. `elapsedSec` vient de HKLiveWorkoutBuilder, qui continue de + /// courir en arrière-plan : c'est la seule horloge fiable ici. + private var stageElapsed: Double { + workout.elapsedSec.truncatingRemainder(dividingBy: stageSeconds) + } + + var body: some View { + Group { + if finished { resultView } + else if started { runningView } + else { setupView } + } + .onReceive(tick) { _ in onTick() } + .navigationTitle("Test VMA") + } + + // MARK: - Avant le départ + + private var setupView: some View { + ScrollView { + VStack(alignment: .leading, spacing: 10) { + Picker("Protocole", selection: $proto) { + ForEach(Protocole.allCases, id: \.self) { Text($0.rawValue).tag($0) } + } + .labelsHidden() + .frame(height: 60) + + Text(proto == .stages + ? "Paliers d'une minute, de 8 km/h par pas de 0,5. La montre vibre à chaque changement. Arrête-toi quand tu ne tiens plus l'allure." + : "Six minutes à allure maximale régulière, sur terrain plat. La distance parcourue donne la VMA.") + .font(.caption2) + .foregroundStyle(.secondary) + + Button("Démarrer") { start() } + .buttonStyle(.borderedProminent) + .tint(.orange) + } + .padding(.horizontal, 4) + } + } + + // MARK: - Pendant le test + + private var runningView: some View { + VStack(spacing: 6) { + if proto == .stages { + Text("Palier \(stageIndex + 1)") + .font(.caption2).foregroundStyle(.secondary) + Text(String(format: "%.1f", targetKmh)) + .font(.system(size: 44, weight: .semibold, design: .rounded)) + .monospacedDigit() + Text("km/h visés").font(.caption2).foregroundStyle(.secondary) + ProgressView(value: min(1, stageElapsed / stageSeconds)) + .tint(.orange) + // Écart à la cible : c'est la seule information qui aide à + // corriger en courant. La vitesse brute demanderait un calcul + // mental à chaque foulée. + Text(paceHint) + .font(.caption) + .foregroundStyle(paceOnTarget ? .green : .orange) + } else { + Text(timeString(sixMinRemaining)) + .font(.system(size: 44, weight: .semibold, design: .rounded)) + .monospacedDigit() + Text("restant").font(.caption2).foregroundStyle(.secondary) + Text(String(format: "%.0f m", workout.distanceMeters)) + .font(.title3).monospacedDigit() + } + + HStack(spacing: 10) { + Label(String(format: "%.0f", workout.heartRate), systemImage: "heart.fill") + .foregroundStyle(.red) + Label(String(format: "%.1f", workout.speedKmh), systemImage: "speedometer") + } + .font(.caption2) + .monospacedDigit() + + Button("J'arrête") { finish() } + .buttonStyle(.bordered) + .tint(.red) + } + .padding(.horizontal, 4) + } + + private var paceOnTarget: Bool { abs(workout.speedKmh - targetKmh) <= 0.4 } + + private var paceHint: String { + // ⚠️ La vitesse GPS est erratique les premières secondes d'acquisition : + // pas d'indication tant que la montre n'a rien de crédible. + guard workout.speedKmh > 1 else { return "acquisition…" } + let d = workout.speedKmh - targetKmh + if abs(d) <= 0.4 { return "allure tenue" } + return d < 0 ? String(format: "accélère (%.1f)", -d) : String(format: "ralentis (%.1f)", d) + } + + // MARK: - Après + + private var resultView: some View { + ScrollView { + VStack(spacing: 8) { + if proto == .stages { + Text("\(completedStages) paliers") + .font(.title3) + Text(completedStages > 0 + ? String(format: "dernier tenu : %.1f km/h", startKmh + stepKmh * Double(completedStages - 1)) + : "aucun palier terminé") + .font(.caption2).foregroundStyle(.secondary) + } else { + Text(String(format: "%.0f m", workout.distanceMeters)).font(.title3) + Text("en 6 minutes").font(.caption2).foregroundStyle(.secondary) + } + + if maxHr > 0 { + Text(String(format: "FC max %.0f bpm", maxHr)) + .font(.caption2).foregroundStyle(.secondary) + } + + if sent { + Label("Envoyé au téléphone", systemImage: "checkmark.circle.fill") + .font(.caption2).foregroundStyle(.green) + } else if let e = sendError { + // Échec d'envoi ≠ test perdu : les chiffres restent lisibles + // à l'écran, l'utilisateur peut les saisir dans l'app. + Text(e).font(.caption2).foregroundStyle(.orange) + Button("Réessayer") { send() }.buttonStyle(.bordered) + } + + Button("Terminer") { dismiss() }.buttonStyle(.bordered) + } + .padding(.horizontal, 4) + } + } + + // MARK: - Machine à états + + private func start() { + stageIndex = 0 + maxHr = 0 + sent = false + sendError = nil + finished = false + started = true + // startWorkout est async (@MainActor) : même appel que ContentView. + Task { await workout.startWorkout(activityType: .running, locationType: .outdoor) } + WKInterfaceDevice.current().play(.start) + } + + private func onTick() { + guard started, !finished else { return } + if workout.heartRate > maxHr { maxHr = workout.heartRate } + + if proto == .stages { + let reached = Int(workout.elapsedSec / stageSeconds) + if reached > stageIndex { + stageIndex = reached // le palier vient d'être TERMINÉ + WKInterfaceDevice.current().play(.notification) + } + } else if workout.elapsedSec >= 360 { + finish() + } + } + + private func finish() { + guard !finished else { return } + finished = true + started = false + workout.end() + WKInterfaceDevice.current().play(.success) + send() + } + + private func send() { + sendError = nil + var payload: [String: Any] = [ + "vmaTest": true, + "protocol": proto == .stages ? "stages" : "cooper6", + "maxHr": Int(maxHr.rounded()), + ] + if proto == .stages { + payload["startKmh"] = startKmh + payload["stepKmh"] = stepKmh + payload["completed"] = completedStages + // Fraction du palier en cours au moment de l'arrêt : le serveur + // n'en crédite que la moitié, et seulement au-delà de 50 %. + payload["partialRatio"] = min(1.0, stageElapsed / stageSeconds) + } else { + payload["distanceM"] = Int(workout.distanceMeters.rounded()) + } + if ConnectivityManager.shared.sendVmaResult(payload) { + sent = true + } else { + sendError = "iPhone injoignable — note les chiffres." + } + } + + private func timeString(_ s: Double) -> String { + let t = Int(s.rounded()) + return String(format: "%d:%02d", t / 60, t % 60) + } +}