diff --git a/Config.xcconfig b/Config.xcconfig index ec5f4a80f..3ff1066f3 100644 --- a/Config.xcconfig +++ b/Config.xcconfig @@ -6,4 +6,4 @@ unique_id = ${DEVELOPMENT_TEAM} //Version (DEFAULT) -LOOP_FOLLOW_MARKETING_VERSION = 6.0.8 +LOOP_FOLLOW_MARKETING_VERSION = 6.1.0 diff --git a/Gemfile b/Gemfile index 2d6cd6e10..1a3b246f6 100644 --- a/Gemfile +++ b/Gemfile @@ -1,2 +1,4 @@ source "https://rubygems.org" -gem "fastlane", "2.232.2" +gem "fastlane", "2.233.1" +gem "json", ">=2.19.2" +gem "addressable", ">=2.9.0" diff --git a/Gemfile.lock b/Gemfile.lock index 54a0a20a8..25ea69c8c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -72,7 +72,7 @@ GEM faraday_middleware (1.2.1) faraday (~> 1.0) fastimage (2.4.0) - fastlane (2.232.2) + fastlane (2.233.1) CFPropertyList (>= 2.3, < 4.0.0) abbrev (~> 0.1.2) addressable (>= 2.8, < 3.0.0) @@ -92,7 +92,7 @@ GEM faraday-cookie_jar (~> 0.0.6) faraday_middleware (~> 1.0) fastimage (>= 2.1.0, < 3.0.0) - fastlane-sirp (>= 1.0.0) + fastlane-sirp (>= 1.1.0) gh_inspector (>= 1.1.2, < 2.0.0) google-apis-androidpublisher_v3 (~> 0.3) google-apis-playcustomapp_v1 (~> 0.1) @@ -122,8 +122,7 @@ GEM xcodeproj (>= 1.13.0, < 2.0.0) xcpretty (~> 0.4.1) xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) - fastlane-sirp (1.0.0) - sysrandom (~> 1.0) + fastlane-sirp (1.1.0) gh_inspector (1.1.3) google-apis-androidpublisher_v3 (0.54.0) google-apis-core (>= 0.11.0, < 2.a) @@ -203,7 +202,6 @@ GEM simctl (1.6.10) CFPropertyList naturally - sysrandom (1.0.5) terminal-notifier (2.0.0) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) @@ -232,7 +230,9 @@ PLATFORMS ruby DEPENDENCIES - fastlane (= 2.232.2) + addressable (>= 2.9.0) + fastlane (= 2.233.1) + json (>= 2.19.2) BUNDLED WITH 4.0.6 diff --git a/LoopFollow.xcodeproj/project.pbxproj b/LoopFollow.xcodeproj/project.pbxproj index 4c2444734..c882ae3d5 100644 --- a/LoopFollow.xcodeproj/project.pbxproj +++ b/LoopFollow.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 2D8068C66833EEAED7B4BEB8 /* FutureCarbsCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EBAB9EECE7095238A558060 /* FutureCarbsCondition.swift */; }; 374A77992F5BD8B200E96858 /* APNSClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374A77982F5BD8AB00E96858 /* APNSClient.swift */; }; + F77D52D003E24351AF2D53AC /* APNsCredentialValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 100F72B12B2E40828D4ED0BD /* APNsCredentialValidator.swift */; }; 374A77A52F5BE17000E96858 /* AppGroupID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374A779F2F5BE17000E96858 /* AppGroupID.swift */; }; 374A77A62F5BE17000E96858 /* GlucoseSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374A77A12F5BE17000E96858 /* GlucoseSnapshot.swift */; }; 374A77A72F5BE17000E96858 /* LAAppGroupSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374A77A32F5BE17000E96858 /* LAAppGroupSettings.swift */; }; @@ -24,6 +25,18 @@ 374A77B92F5BE1AC00E96858 /* PreferredGlucoseUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374A77B22F5BE1AC00E96858 /* PreferredGlucoseUnit.swift */; }; 379BECAA2F6588300069DC62 /* RestartLiveActivityIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 379BECA92F6588300069DC62 /* RestartLiveActivityIntent.swift */; }; 379BECB02F65DA4B0069DC62 /* LiveActivitySettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 379BECAF2F65DA4B0069DC62 /* LiveActivitySettingsView.swift */; }; + 37989DBF2F609B0E0004BD8B /* LoopFollowWatch Watch App.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 37989DB52F609B0C0004BD8B /* LoopFollowWatch Watch App.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 37989DC52F609C550004BD8B /* GlucoseSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374A77A12F5BE17000E96858 /* GlucoseSnapshot.swift */; }; + 37989DC62F609C5E0004BD8B /* GlucoseSnapshotStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374A77AF2F5BE1AC00E96858 /* GlucoseSnapshotStore.swift */; }; + 37989DC72F609C730004BD8B /* AppGroupID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374A779F2F5BE17000E96858 /* AppGroupID.swift */; }; + 37989DC82F609C7A0004BD8B /* LAAppGroupSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374A77A32F5BE17000E96858 /* LAAppGroupSettings.swift */; }; + 37989DCE2F609ED40004BD8B /* WatchComplicationProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37989DCC2F609DAE0004BD8B /* WatchComplicationProvider.swift */; }; + 37989DD02F609F570004BD8B /* ComplicationEntryBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37989DCF2F609F570004BD8B /* ComplicationEntryBuilder.swift */; }; + 37989DDC2F60A2010004BD8B /* WatchFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37989DDB2F60A2000004BD8B /* WatchFormat.swift */; }; + 37989DDD2F60A2020004BD8B /* GlucoseConversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD91E4DC2BDEC3F8002D9E97 /* GlucoseConversion.swift */; }; + 37989DD22F60A0ED0004BD8B /* WatchConnectivity.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37989DD12F60A0ED0004BD8B /* WatchConnectivity.framework */; }; + 37989DD42F60A11E0004BD8B /* WatchConnectivityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37989DD32F60A11E0004BD8B /* WatchConnectivityManager.swift */; }; + 37989DD62F60A15E0004BD8B /* WatchSessionReceiver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37989DD52F60A15E0004BD8B /* WatchSessionReceiver.swift */; }; 37A4BDDB2F5B6B4A00EEB289 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37A4BDDA2F5B6B4A00EEB289 /* WidgetKit.framework */; }; 37A4BDDD2F5B6B4A00EEB289 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37A4BDDC2F5B6B4A00EEB289 /* SwiftUI.framework */; }; 37A4BDE82F5B6B4C00EEB289 /* LoopFollowLAExtensionExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 37A4BDD92F5B6B4A00EEB289 /* LoopFollowLAExtensionExtension.appex */; platformFilter = ios; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; @@ -59,6 +72,8 @@ 6589CC6F2E9E7D1600BB18FE /* AdvancedSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6589CC572E9E7D1600BB18FE /* AdvancedSettingsViewModel.swift */; }; 6589CC712E9E814F00BB18FE /* AlarmSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6589CC702E9E814F00BB18FE /* AlarmSelectionView.swift */; }; 6589CC752E9EAFB700BB18FE /* SettingsMigrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6589CC742E9EAFB700BB18FE /* SettingsMigrationManager.swift */; }; + 65A100012F5AA00000AA1001 /* UnitsSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65A100002F5AA00000AA1001 /* UnitsSettingsView.swift */; }; + 65A100032F5AA00000AA1002 /* UnitsConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65A100022F5AA00000AA1002 /* UnitsConfigurationView.swift */; }; 65E153C32E4BB69100693A4F /* URLTokenValidationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65E153C22E4BB69100693A4F /* URLTokenValidationView.swift */; }; 65E8A2862E44B0300065037B /* VolumeButtonHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65E8A2852E44B0300065037B /* VolumeButtonHandler.swift */; }; 66E3D12E66AA4534A144A54B /* BackgroundRefreshManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8CA8BE0B3D247408FE088B4 /* BackgroundRefreshManager.swift */; }; @@ -248,6 +263,7 @@ DDD10F0B2C54192A00D76A8E /* TemporaryTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDD10F0A2C54192A00D76A8E /* TemporaryTarget.swift */; }; DDDB86F12DF7223C00AADDAC /* DeleteAlarmSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDB86F02DF7223C00AADDAC /* DeleteAlarmSection.swift */; }; DDDC01DD2E244B3100D9975C /* JWTManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDC01DC2E244B3100D9975C /* JWTManager.swift */; }; + A1A1A10002000000A0CFEED1 /* LogRedactor.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1A1A10002000000A0CFEED2 /* LogRedactor.swift */; }; DDDC31CC2E13A7DF009EA0F3 /* AddAlarmSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDC31CB2E13A7DF009EA0F3 /* AddAlarmSheet.swift */; }; DDDC31CE2E13A811009EA0F3 /* AlarmTile.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDC31CD2E13A811009EA0F3 /* AlarmTile.swift */; }; DDDF6F492D479AF000884336 /* NoRemoteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDF6F482D479AEF00884336 /* NoRemoteView.swift */; }; @@ -260,6 +276,7 @@ DDEF503A2D31615000999A5D /* LogManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDEF50392D31614200999A5D /* LogManager.swift */; }; DDEF503C2D31BE2D00999A5D /* TaskScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDEF503B2D31BE2A00999A5D /* TaskScheduler.swift */; }; DDEF503F2D32754F00999A5D /* ProfileTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDEF503E2D32754A00999A5D /* ProfileTask.swift */; }; + AA001002000000000000ABCD /* WatchCommandDispatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA001001000000000000ABCD /* WatchCommandDispatcher.swift */; }; DDEF50402D479B8A00884336 /* LoopAPNSService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDEF503F2D479B8A00884336 /* LoopAPNSService.swift */; }; DDEF50422D479BAA00884336 /* LoopAPNSCarbsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDEF50412D479BAA00884336 /* LoopAPNSCarbsView.swift */; }; DDEF50432D479BBA00884336 /* LoopAPNSBolusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDEF50422D479BBA00884336 /* LoopAPNSBolusView.swift */; }; @@ -288,6 +305,7 @@ FC1BDD3224A2585C001B652C /* DataStructs.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC1BDD2E24A232A3001B652C /* DataStructs.swift */; }; FC3AE7B5249E8E0E00AAE1E0 /* LoopFollow.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = FC3AE7B3249E8E0E00AAE1E0 /* LoopFollow.xcdatamodeld */; }; FC3CAB022493B6220068A152 /* BackgroundTaskAudio.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCC688592489554800A0279D /* BackgroundTaskAudio.swift */; }; + A1A1A10001000000A0CFEED1 /* APNsCredentialValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1A1A10001000000A0CFEED2 /* APNsCredentialValidator.swift */; }; FC5A5C3D2497B229009C550E /* Config.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = FC5A5C3C2497B229009C550E /* Config.xcconfig */; }; FC7CE518248ABE37001F83B8 /* Siri_Alert_Calibration_Needed.caf in Resources */ = {isa = PBXBuildFile; fileRef = FC7CE4A9248ABE2B001F83B8 /* Siri_Alert_Calibration_Needed.caf */; }; FC7CE519248ABE37001F83B8 /* Rise_And_Shine.caf in Resources */ = {isa = PBXBuildFile; fileRef = FC7CE4AA248ABE2B001F83B8 /* Rise_And_Shine.caf */; }; @@ -420,6 +438,7 @@ FCC6886B24898FD800A0279D /* ObservationToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCC6886A24898FD800A0279D /* ObservationToken.swift */; }; FCC6886D2489909D00A0279D /* AnyConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCC6886C2489909D00A0279D /* AnyConvertible.swift */; }; FCC6886F2489A53800A0279D /* AppConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCC6886E2489A53800A0279D /* AppConstants.swift */; }; + 9C7FB98C98BE4FF98F4815EE /* Telemetry.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDFBE69CEF18416D84959974 /* Telemetry.swift */; }; FCD2A27D24C9D044009F7B7B /* Globals.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCD2A27C24C9D044009F7B7B /* Globals.swift */; }; FCE537BC249A4D7D00F80BF8 /* carbBolusArrays.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCE537BB249A4D7D00F80BF8 /* carbBolusArrays.swift */; }; FCEF87AC24A141A700AE6FA0 /* Localizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCEF87AA24A1417900AE6FA0 /* Localizer.swift */; }; @@ -429,6 +448,13 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 37989DBD2F609B0E0004BD8B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FC97880C2485969B00A7906C /* Project object */; + proxyType = 1; + remoteGlobalIDString = 37989DB42F609B0C0004BD8B; + remoteInfo = "LoopFollowWatch Watch App"; + }; 37A4BDE62F5B6B4C00EEB289 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = FC97880C2485969B00A7906C /* Project object */; @@ -446,6 +472,17 @@ /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + 37989DC32F609B0E0004BD8B /* Embed Watch Content */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(CONTENTS_FOLDER_PATH)/Watch"; + dstSubfolderSpec = 16; + files = ( + 37989DBF2F609B0E0004BD8B /* LoopFollowWatch Watch App.app in Embed Watch Content */, + ); + name = "Embed Watch Content"; + runOnlyForDeploymentPostprocessing = 0; + }; 37A4BDED2F5B6B4C00EEB289 /* Embed Foundation Extensions */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -464,6 +501,7 @@ 2B9BEC26E4E48EF9B811A372 /* PendingFutureCarb.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PendingFutureCarb.swift; sourceTree = ""; }; 2EBAB9EECE7095238A558060 /* FutureCarbsCondition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FutureCarbsCondition.swift; sourceTree = ""; }; 374A77982F5BD8AB00E96858 /* APNSClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APNSClient.swift; sourceTree = ""; }; + 100F72B12B2E40828D4ED0BD /* APNsCredentialValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APNsCredentialValidator.swift; sourceTree = ""; }; 374A779F2F5BE17000E96858 /* AppGroupID.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppGroupID.swift; sourceTree = ""; }; 374A77A02F5BE17000E96858 /* GlucoseLiveActivityAttributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseLiveActivityAttributes.swift; sourceTree = ""; }; 374A77A12F5BE17000E96858 /* GlucoseSnapshot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseSnapshot.swift; sourceTree = ""; }; @@ -476,6 +514,13 @@ 374DAACA2F5B924B00BB663B /* LoopFollowLAExtensionExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LoopFollowLAExtensionExtension.entitlements; sourceTree = ""; }; 379BECA92F6588300069DC62 /* RestartLiveActivityIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestartLiveActivityIntent.swift; sourceTree = ""; }; 379BECAF2F65DA4B0069DC62 /* LiveActivitySettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveActivitySettingsView.swift; sourceTree = ""; }; + 37989DB52F609B0C0004BD8B /* LoopFollowWatch Watch App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "LoopFollowWatch Watch App.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 37989DCC2F609DAE0004BD8B /* WatchComplicationProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchComplicationProvider.swift; sourceTree = ""; }; + 37989DCF2F609F570004BD8B /* ComplicationEntryBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComplicationEntryBuilder.swift; sourceTree = ""; }; + 37989DDB2F60A2000004BD8B /* WatchFormat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchFormat.swift; sourceTree = ""; }; + 37989DD12F60A0ED0004BD8B /* WatchConnectivity.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WatchConnectivity.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.2.sdk/System/iOSSupport/System/Library/Frameworks/WatchConnectivity.framework; sourceTree = DEVELOPER_DIR; }; + 37989DD32F60A11E0004BD8B /* WatchConnectivityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchConnectivityManager.swift; sourceTree = ""; }; + 37989DD52F60A15E0004BD8B /* WatchSessionReceiver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchSessionReceiver.swift; sourceTree = ""; }; 37A4BDD92F5B6B4A00EEB289 /* LoopFollowLAExtensionExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = LoopFollowLAExtensionExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 37A4BDDA2F5B6B4A00EEB289 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = /System/Library/Frameworks/WidgetKit.framework; sourceTree = ""; }; 37A4BDDC2F5B6B4A00EEB289 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = /System/Library/Frameworks/SwiftUI.framework; sourceTree = ""; }; @@ -508,6 +553,8 @@ 6589CC602E9E7D1600BB18FE /* TabCustomizationModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabCustomizationModal.swift; sourceTree = ""; }; 6589CC702E9E814F00BB18FE /* AlarmSelectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmSelectionView.swift; sourceTree = ""; }; 6589CC742E9EAFB700BB18FE /* SettingsMigrationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsMigrationManager.swift; sourceTree = ""; }; + 65A100002F5AA00000AA1001 /* UnitsSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitsSettingsView.swift; sourceTree = ""; }; + 65A100022F5AA00000AA1002 /* UnitsConfigurationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitsConfigurationView.swift; sourceTree = ""; }; 65E153C22E4BB69100693A4F /* URLTokenValidationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLTokenValidationView.swift; sourceTree = ""; }; 65E8A2852E44B0300065037B /* VolumeButtonHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VolumeButtonHandler.swift; sourceTree = ""; }; A7D55B42A22051DAD69E89D0 /* Pods_LoopFollow.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LoopFollow.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -700,6 +747,7 @@ DDD10F0A2C54192A00D76A8E /* TemporaryTarget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemporaryTarget.swift; sourceTree = ""; }; DDDB86F02DF7223C00AADDAC /* DeleteAlarmSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteAlarmSection.swift; sourceTree = ""; }; DDDC01DC2E244B3100D9975C /* JWTManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWTManager.swift; sourceTree = ""; }; + A1A1A10002000000A0CFEED2 /* LogRedactor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogRedactor.swift; sourceTree = ""; }; DDDC31CB2E13A7DF009EA0F3 /* AddAlarmSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAlarmSheet.swift; sourceTree = ""; }; DDDC31CD2E13A811009EA0F3 /* AlarmTile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmTile.swift; sourceTree = ""; }; DDDF6F482D479AEF00884336 /* NoRemoteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoRemoteView.swift; sourceTree = ""; }; @@ -712,6 +760,7 @@ DDEF50392D31614200999A5D /* LogManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogManager.swift; sourceTree = ""; }; DDEF503B2D31BE2A00999A5D /* TaskScheduler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskScheduler.swift; sourceTree = ""; }; DDEF503E2D32754A00999A5D /* ProfileTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileTask.swift; sourceTree = ""; }; + AA001001000000000000ABCD /* WatchCommandDispatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchCommandDispatcher.swift; sourceTree = ""; }; DDEF503F2D479B8A00884336 /* LoopAPNSService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopAPNSService.swift; sourceTree = ""; }; DDEF50412D479BAA00884336 /* LoopAPNSCarbsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopAPNSCarbsView.swift; sourceTree = ""; }; DDEF50422D479BBA00884336 /* LoopAPNSBolusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopAPNSBolusView.swift; sourceTree = ""; }; @@ -868,6 +917,7 @@ FCA2DDE52501095000254A8C /* Timers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Timers.swift; sourceTree = ""; }; FCC0FAC124922A22003E610E /* DictionaryKeyPath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DictionaryKeyPath.swift; sourceTree = ""; }; FCC688592489554800A0279D /* BackgroundTaskAudio.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BackgroundTaskAudio.swift; sourceTree = ""; }; + A1A1A10001000000A0CFEED2 /* APNsCredentialValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APNsCredentialValidator.swift; sourceTree = ""; }; FCC6885B2489559400A0279D /* blank.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = blank.wav; sourceTree = ""; }; FCC6885D24896A6C00A0279D /* silence.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = silence.mp3; sourceTree = ""; }; FCC6886624898F8000A0279D /* UserDefaultsValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsValue.swift; sourceTree = ""; }; @@ -875,6 +925,7 @@ FCC6886A24898FD800A0279D /* ObservationToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObservationToken.swift; sourceTree = ""; }; FCC6886C2489909D00A0279D /* AnyConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnyConvertible.swift; sourceTree = ""; }; FCC6886E2489A53800A0279D /* AppConstants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppConstants.swift; sourceTree = ""; }; + BDFBE69CEF18416D84959974 /* Telemetry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Telemetry.swift; sourceTree = ""; }; FCC688702489A57C00A0279D /* Loop Follow.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Loop Follow.entitlements"; sourceTree = ""; }; FCD2A27C24C9D044009F7B7B /* Globals.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Globals.swift; sourceTree = ""; }; FCE537BB249A4D7D00F80BF8 /* carbBolusArrays.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = carbBolusArrays.swift; sourceTree = ""; }; @@ -886,6 +937,7 @@ /* End PBXFileReference section */ /* Begin PBXFileSystemSynchronizedRootGroup section */ + 37989DB62F609B0C0004BD8B /* LoopFollowWatch Watch App */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = "LoopFollowWatch Watch App"; sourceTree = ""; }; 37A4BDDE2F5B6B4A00EEB289 /* LoopFollowLAExtension */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = LoopFollowLAExtension; sourceTree = ""; }; 65AC25F52ECFD5E800421360 /* Stats */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Stats; sourceTree = ""; }; 65AC26702ED245DF00421360 /* Treatments */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Treatments; sourceTree = ""; }; @@ -893,6 +945,13 @@ /* End PBXFileSystemSynchronizedRootGroup section */ /* Begin PBXFrameworksBuildPhase section */ + 37989DB22F609B0C0004BD8B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 37A4BDD62F5B6B4A00EEB289 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -915,6 +974,8 @@ files = ( FCFEEC9E2486E68E00402A7F /* WebKit.framework in Frameworks */, 3F1335F351590E573D8E6962 /* Pods_LoopFollow.framework in Frameworks */, + DD48781C2C7DAF140048F05C /* SwiftJWT in Frameworks */, + 37989DD22F60A0ED0004BD8B /* WatchConnectivity.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -936,10 +997,22 @@ 374A77A12F5BE17000E96858 /* GlucoseSnapshot.swift */, 374A77A32F5BE17000E96858 /* LAAppGroupSettings.swift */, 374A77982F5BD8AB00E96858 /* APNSClient.swift */, + 100F72B12B2E40828D4ED0BD /* APNsCredentialValidator.swift */, ); path = LiveActivity; sourceTree = ""; }; + 37989DCB2F609D9C0004BD8B /* WatchComplication */ = { + isa = PBXGroup; + children = ( + 37989DD52F60A15E0004BD8B /* WatchSessionReceiver.swift */, + 37989DCF2F609F570004BD8B /* ComplicationEntryBuilder.swift */, + 37989DCC2F609DAE0004BD8B /* WatchComplicationProvider.swift */, + 37989DDB2F60A2000004BD8B /* WatchFormat.swift */, + ); + path = WatchComplication; + sourceTree = ""; + }; 6589CC552E9E7D1600BB18FE /* ImportExport */ = { isa = PBXGroup; children = ( @@ -968,6 +1041,8 @@ 6589CC5E2E9E7D1600BB18FE /* GraphSettingsView.swift */, 657F98172F043D8100F732BD /* HomeContentView.swift */, 6589CC5F2E9E7D1600BB18FE /* SettingsMenuView.swift */, + 65A100002F5AA00000AA1001 /* UnitsSettingsView.swift */, + 65A100022F5AA00000AA1002 /* UnitsConfigurationView.swift */, 6589CC602E9E7D1600BB18FE /* TabCustomizationModal.swift */, ); path = Settings; @@ -976,6 +1051,7 @@ 6A5880E0B811AF443B05AB02 /* Frameworks */ = { isa = PBXGroup; children = ( + 37989DD12F60A0ED0004BD8B /* WatchConnectivity.framework */, DDCC3ABF2DDE10B0006F1C10 /* Testing.framework */, FCFEEC9D2486E68E00402A7F /* WebKit.framework */, A7D55B42A22051DAD69E89D0 /* Pods_LoopFollow.framework */, @@ -1036,12 +1112,21 @@ path = Metric; sourceTree = ""; }; + AA001003000000000000ABCD /* Watch */ = { + isa = PBXGroup; + children = ( + AA001001000000000000ABCD /* WatchCommandDispatcher.swift */, + ); + path = Watch; + sourceTree = ""; + }; DD0C0C6E2C4AFFB800DBADDF /* Remote */ = { isa = PBXGroup; children = ( DDDF6F4A2D479B6A00884336 /* Nightscout */, DDDF6F482D479AEF00884336 /* NoRemoteView.swift */, DDEF503E2D479B8A00884336 /* LoopAPNS */, + AA001003000000000000ABCD /* Watch */, DD4878112C7B74F90048F05C /* TRC */, DD4878062C7B2E9E0048F05C /* Settings */, DDF699972C5AA2E50058A8D9 /* TempTargetPreset */, @@ -1590,6 +1675,7 @@ isa = PBXGroup; children = ( 379BECAF2F65DA4B0069DC62 /* LiveActivitySettingsView.swift */, + 37989DCB2F609D9C0004BD8B /* WatchComplication */, 376310762F5CD65100656488 /* LiveActivity */, 6589CC612E9E7D1600BB18FE /* Settings */, 65AC26702ED245DF00421360 /* Treatments */, @@ -1622,6 +1708,7 @@ isa = PBXGroup; children = ( 379BECA92F6588300069DC62 /* RestartLiveActivityIntent.swift */, + 37989DD32F60A11E0004BD8B /* WatchConnectivityManager.swift */, 374DAACA2F5B924B00BB663B /* LoopFollowLAExtensionExtension.entitlements */, DDF2C0132BEFD468007A20E6 /* blacklisted-versions.json */, DDB0AF542BB1B24A00AFA48B /* BuildDetails.plist */, @@ -1632,6 +1719,7 @@ FC8DEEE32485D1680075863F /* LoopFollow */, DDCC3AD72DDE1790006F1C10 /* Tests */, 37A4BDDE2F5B6B4A00EEB289 /* LoopFollowLAExtension */, + 37989DB62F609B0C0004BD8B /* LoopFollowWatch Watch App */, FC9788152485969B00A7906C /* Products */, 8E32230C453C93FDCE59C2B9 /* Pods */, 6A5880E0B811AF443B05AB02 /* Frameworks */, @@ -1644,6 +1732,7 @@ FC9788142485969B00A7906C /* Loop Follow.app */, DDCC3AD62DDE1790006F1C10 /* Tests.xctest */, 37A4BDD92F5B6B4A00EEB289 /* LoopFollowLAExtensionExtension.appex */, + 37989DB52F609B0C0004BD8B /* LoopFollowWatch Watch App.app */, ); name = Products; sourceTree = ""; @@ -1676,9 +1765,11 @@ DD7B0D432D730A320063DCB6 /* CycleHelper.swift */, DDF6999C2C5AAA4C0058A8D9 /* Views */, FCC6886E2489A53800A0279D /* AppConstants.swift */, + BDFBE69CEF18416D84959974 /* Telemetry.swift */, FCC6886A24898FD800A0279D /* ObservationToken.swift */, FCC6886C2489909D00A0279D /* AnyConvertible.swift */, FCC688592489554800A0279D /* BackgroundTaskAudio.swift */, + A1A1A10001000000A0CFEED2 /* APNsCredentialValidator.swift */, A8CA8BE0B3D247408FE088B4 /* BackgroundRefreshManager.swift */, FCFEEC9F2488157B00402A7F /* Chart.swift */, FCC0FAC124922A22003E610E /* DictionaryKeyPath.swift */, @@ -1697,6 +1788,7 @@ DDF699952C5582290058A8D9 /* TextFieldWithToolBar.swift */, DDC7E5372DBD887400EB1127 /* isOnPhoneCall.swift */, DDDC01DC2E244B3100D9975C /* JWTManager.swift */, + A1A1A10002000000A0CFEED2 /* LogRedactor.swift */, 6541341B2E1DC28000BDBE08 /* DateExtensions.swift */, ); path = Helpers; @@ -1717,6 +1809,28 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + 37989DB42F609B0C0004BD8B /* LoopFollowWatch Watch App */ = { + isa = PBXNativeTarget; + buildConfigurationList = 37989DC02F609B0E0004BD8B /* Build configuration list for PBXNativeTarget "LoopFollowWatch Watch App" */; + buildPhases = ( + 37989DB12F609B0C0004BD8B /* Sources */, + 37989DB22F609B0C0004BD8B /* Frameworks */, + 37989DB32F609B0C0004BD8B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 37989DB62F609B0C0004BD8B /* LoopFollowWatch Watch App */, + ); + name = "LoopFollowWatch Watch App"; + packageProductDependencies = ( + ); + productName = "LoopFollowWatch Watch App"; + productReference = 37989DB52F609B0C0004BD8B /* LoopFollowWatch Watch App.app */; + productType = "com.apple.product-type.application"; + }; 37A4BDD82F5B6B4A00EEB289 /* LoopFollowLAExtensionExtension */ = { isa = PBXNativeTarget; buildConfigurationList = 37A4BDEA2F5B6B4C00EEB289 /* Build configuration list for PBXNativeTarget "LoopFollowLAExtensionExtension" */; @@ -1774,11 +1888,13 @@ 04DA71CCA0280FA5FA2DF7A6 /* [CP] Embed Pods Frameworks */, DDB0AF532BB1AA0900AFA48B /* Capture Build Details */, 37A4BDED2F5B6B4C00EEB289 /* Embed Foundation Extensions */, + 37989DC32F609B0E0004BD8B /* Embed Watch Content */, ); buildRules = ( ); dependencies = ( 37A4BDE72F5B6B4C00EEB289 /* PBXTargetDependency */, + 37989DBE2F609B0E0004BD8B /* PBXTargetDependency */, ); fileSystemSynchronizedGroups = ( 65AC25F52ECFD5E800421360 /* Stats */, @@ -1797,10 +1913,13 @@ FC97880C2485969B00A7906C /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 2620; + LastSwiftUpdateCheck = 2630; LastUpgradeCheck = 1140; ORGANIZATIONNAME = "Jon Fawcett"; TargetAttributes = { + 37989DB42F609B0C0004BD8B = { + CreatedOnToolsVersion = 26.3; + }; 37A4BDD82F5B6B4A00EEB289 = { CreatedOnToolsVersion = 26.2; }; @@ -1831,11 +1950,19 @@ FC9788132485969B00A7906C /* LoopFollow */, DDCC3AD52DDE1790006F1C10 /* Tests */, 37A4BDD82F5B6B4A00EEB289 /* LoopFollowLAExtensionExtension */, + 37989DB42F609B0C0004BD8B /* LoopFollowWatch Watch App */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 37989DB32F609B0C0004BD8B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 37A4BDD72F5B6B4A00EEB289 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -2066,6 +2193,22 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 37989DB12F609B0C0004BD8B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 37989DC62F609C5E0004BD8B /* GlucoseSnapshotStore.swift in Sources */, + 37989DD02F609F570004BD8B /* ComplicationEntryBuilder.swift in Sources */, + 37989DC52F609C550004BD8B /* GlucoseSnapshot.swift in Sources */, + 37989DC72F609C730004BD8B /* AppGroupID.swift in Sources */, + 37989DD62F60A15E0004BD8B /* WatchSessionReceiver.swift in Sources */, + 37989DC82F609C7A0004BD8B /* LAAppGroupSettings.swift in Sources */, + 37989DCE2F609ED40004BD8B /* WatchComplicationProvider.swift in Sources */, + 37989DDC2F60A2010004BD8B /* WatchFormat.swift in Sources */, + 37989DDD2F60A2020004BD8B /* GlucoseConversion.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 37A4BDD52F5B6B4A00EEB289 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -2106,6 +2249,7 @@ 374A77B42F5BE1AC00E96858 /* StorageCurrentGlucoseStateProvider.swift in Sources */, 374A77B52F5BE1AC00E96858 /* GlucoseSnapshotBuilder.swift in Sources */, 374A77B72F5BE1AC00E96858 /* LiveActivityManager.swift in Sources */, + F77D52D003E24351AF2D53AC /* APNsCredentialValidator.swift in Sources */, 374A77B82F5BE1AC00E96858 /* GlucoseSnapshotStore.swift in Sources */, 374A77B92F5BE1AC00E96858 /* PreferredGlucoseUnit.swift in Sources */, DDE75D232DE5E505007C1FC1 /* Glyph.swift in Sources */, @@ -2143,6 +2287,7 @@ DD0650ED2DCE9371004D3B41 /* HighBgAlarmEditor.swift in Sources */, DD7F4C172DD63FA700D449E9 /* RecBolusCondition.swift in Sources */, FCC6886F2489A53800A0279D /* AppConstants.swift in Sources */, + 9C7FB98C98BE4FF98F4815EE /* Telemetry.swift in Sources */, DDE75D2D2DE71401007C1FC1 /* TogglableSecureInput.swift in Sources */, DD7E19842ACDA50C00DBD158 /* Overrides.swift in Sources */, DD0B9D562DE1EC8A0090C337 /* AlarmType+Snooze.swift in Sources */, @@ -2232,6 +2377,7 @@ FC8589BF252B54F500C8FC73 /* Mobileprovision.swift in Sources */, DD4878052C7B2C970048F05C /* Storage.swift in Sources */, DD493AE12ACF22FE009A6922 /* Profile.swift in Sources */, + 37989DD42F60A11E0004BD8B /* WatchConnectivityManager.swift in Sources */, 6589CC622E9E7D1600BB18FE /* ImportExportSettingsView.swift in Sources */, 6589CC632E9E7D1600BB18FE /* GeneralSettingsView.swift in Sources */, 5544D8C363FB5D3B9BF8CE4A /* APNSettingsView.swift in Sources */, @@ -2247,6 +2393,8 @@ 6589CC6C2E9E7D1600BB18FE /* GraphSettingsView.swift in Sources */, 6589CC6D2E9E7D1600BB18FE /* CalendarSettingsView.swift in Sources */, 6589CC6E2E9E7D1600BB18FE /* SettingsMenuView.swift in Sources */, + 65A100012F5AA00000AA1001 /* UnitsSettingsView.swift in Sources */, + 65A100032F5AA00000AA1002 /* UnitsConfigurationView.swift in Sources */, 657F98182F043D8100F732BD /* HomeContentView.swift in Sources */, 6589CC6F2E9E7D1600BB18FE /* AdvancedSettingsViewModel.swift in Sources */, DD493ADF2ACF22BB009A6922 /* SAge.swift in Sources */, @@ -2284,6 +2432,7 @@ DD4A407E2E6AFEE6007B318B /* AuthService.swift in Sources */, 654134182E1DC09700BDBE08 /* OverridePresetsView.swift in Sources */, DDDC01DD2E244B3100D9975C /* JWTManager.swift in Sources */, + A1A1A10002000000A0CFEED1 /* LogRedactor.swift in Sources */, DDD10F072C529DE800D76A8E /* Observable.swift in Sources */, DDFF3D852D14279B00BF9D9E /* BackgroundRefreshSettingsView.swift in Sources */, DDCF9A882D85FD33004DF4DD /* AlarmData.swift in Sources */, @@ -2369,18 +2518,25 @@ DD493ADD2ACF21E0009A6922 /* Basals.swift in Sources */, FC16A98124996C07003D6245 /* DateTime.swift in Sources */, FC3CAB022493B6220068A152 /* BackgroundTaskAudio.swift in Sources */, + A1A1A10001000000A0CFEED1 /* APNsCredentialValidator.swift in Sources */, DDCC3A582DDC9655006F1C10 /* MissedBolusAlarmEditor.swift in Sources */, DDEF50402D479B8A00884336 /* LoopAPNSService.swift in Sources */, DD485F142E454B2600CE8CBF /* SecureMessenger.swift in Sources */, DDEF50422D479BAA00884336 /* LoopAPNSCarbsView.swift in Sources */, DDEF50432D479BBA00884336 /* LoopAPNSBolusView.swift in Sources */, DDEF50452D479BDA00884336 /* LoopAPNSRemoteView.swift in Sources */, + AA001002000000000000ABCD /* WatchCommandDispatcher.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 37989DBE2F609B0E0004BD8B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 37989DB42F609B0C0004BD8B /* LoopFollowWatch Watch App */; + targetProxy = 37989DBD2F609B0E0004BD8B /* PBXContainerItemProxy */; + }; 37A4BDE72F5B6B4C00EEB289 /* PBXTargetDependency */ = { isa = PBXTargetDependency; platformFilter = ios; @@ -2414,6 +2570,91 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ + 37989DC12F609B0E0004BD8B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_COMPLICATION_NAME = LoopFollow; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CODE_SIGN_ENTITLEMENTS = "LoopFollowWatch Watch App/LoopFollowWatch Watch App.entitlements"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = "$(LF_DEVELOPMENT_TEAM)"; + ENABLE_PREVIEWS = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_CFBundleDisplayName = LoopFollowWatch; + INFOPLIST_KEY_CLKComplicationPrincipalClass = "$(PRODUCT_MODULE_NAME).WatchComplicationProvider"; + INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; + INFOPLIST_KEY_WKCompanionAppBundleIdentifier = "com.$(unique_id).LoopFollow$(app_suffix)"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.$(unique_id).LoopFollow$(app_suffix).watchkitapp"; + 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_DEFAULT_ACTOR_ISOLATION = MainActor; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 9.6; + }; + name = Debug; + }; + 37989DC22F609B0E0004BD8B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_COMPLICATION_NAME = LoopFollow; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CODE_SIGN_ENTITLEMENTS = "LoopFollowWatch Watch App/LoopFollowWatch Watch App.entitlements"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = "$(LF_DEVELOPMENT_TEAM)"; + ENABLE_PREVIEWS = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_CFBundleDisplayName = LoopFollowWatch; + INFOPLIST_KEY_CLKComplicationPrincipalClass = "$(PRODUCT_MODULE_NAME).WatchComplicationProvider"; + INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; + INFOPLIST_KEY_WKCompanionAppBundleIdentifier = "com.$(unique_id).LoopFollow$(app_suffix)"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.$(unique_id).LoopFollow$(app_suffix).watchkitapp"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 9.6; + }; + name = Release; + }; 37A4BDEB2F5B6B4C00EEB289 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -2755,6 +2996,15 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 37989DC02F609B0E0004BD8B /* Build configuration list for PBXNativeTarget "LoopFollowWatch Watch App" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 37989DC12F609B0E0004BD8B /* Debug */, + 37989DC22F609B0E0004BD8B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 37A4BDEA2F5B6B4C00EEB289 /* Build configuration list for PBXNativeTarget "LoopFollowLAExtensionExtension" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/LoopFollow/Application/AppDelegate.swift b/LoopFollow/Application/AppDelegate.swift index a6fd9f2b9..70b5a9dae 100644 --- a/LoopFollow/Application/AppDelegate.swift +++ b/LoopFollow/Application/AppDelegate.swift @@ -40,6 +40,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { _ = BLEManager.shared // Ensure VolumeButtonHandler is initialized so it can receive alarm notifications _ = VolumeButtonHandler.shared + + WatchConnectivityManager.shared.activate() // Register for remote notifications DispatchQueue.main.async { @@ -48,6 +50,21 @@ class AppDelegate: UIResponder, UIApplicationDelegate { BackgroundRefreshManager.shared.register() + // Telemetry: record this cold launch (used by the rolling + // coldLaunches7d signal). If the running build's SHA differs from + // the one we last sent for, fire an immediate ping — the scheduler + // alone can't notice an app update. Otherwise let the 24h scheduler + // handle cadence: its first run is lastSentAt + 24h, so a relaunch + // a few hours after the previous send simply waits out the + // remainder. See Helpers/Telemetry.swift. + TelemetryClient.shared.recordColdLaunch() + Task.detached { + if TelemetryClient.shared.buildShaChangedSinceLastSend() { + await TelemetryClient.shared.maybeSend() + } + TelemetryClient.shared.scheduleRecurring() + } + // Detect Before-First-Unlock launch. If protected data is unavailable here, // StorageValues were cached from encrypted UserDefaults and need a reload // on the first foreground after the user unlocks. @@ -72,7 +89,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { Observable.shared.loopFollowDeviceToken.value = tokenString - LogManager.shared.log(category: .apns, message: "Successfully registered for remote notifications with token: \(tokenString)") + LogManager.shared.log(category: .apns, message: "Successfully registered for remote notifications with token: \(LogRedactor.tail(tokenString))") } /// Called when failed to register for remote notifications @@ -82,7 +99,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { /// Called when a remote notification is received func application(_: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { - LogManager.shared.log(category: .apns, message: "Received remote notification: \(userInfo)") + let userInfoKeys = userInfo.keys.compactMap { $0 as? String }.sorted() + LogManager.shared.log(category: .apns, message: "Received remote notification: keys=\(userInfoKeys)") // Check if this is a response notification from Loop or Trio if let aps = userInfo["aps"] as? [String: Any] { @@ -107,6 +125,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } } + // Forward Loop command return notifications to the Watch + WatchConnectivityManager.shared.forwardCommandReturnToWatch(userInfo: userInfo) + // Call completion handler completionHandler(.newData) } @@ -217,7 +238,8 @@ extension AppDelegate: UNUserNotificationCenterDelegate { { // Log the notification let userInfo = notification.request.content.userInfo - LogManager.shared.log(category: .general, message: "Will present notification: \(userInfo)") + let userInfoKeys = userInfo.keys.compactMap { $0 as? String }.sorted() + LogManager.shared.log(category: .general, message: "Will present notification: keys=\(userInfoKeys)") // Show the notification even when app is in foreground completionHandler([.banner, .sound, .badge]) diff --git a/LoopFollow/Application/Base.lproj/Main.storyboard b/LoopFollow/Application/Base.lproj/Main.storyboard index 11e4b1a72..6441edc6c 100644 --- a/LoopFollow/Application/Base.lproj/Main.storyboard +++ b/LoopFollow/Application/Base.lproj/Main.storyboard @@ -223,7 +223,7 @@ -