polscm32 aka Marvout 1 год назад
Родитель
Сommit
021f212440
23 измененных файлов с 11 добавлено и 2491 удалено
  1. 2 423
      FreeAPS.xcodeproj/project.pbxproj
  2. 0 1
      FreeAPS/Sources/Application/FreeAPSApp.swift
  3. 0 1
      FreeAPS/Sources/Assemblies/ServiceAssembly.swift
  4. 7 5
      FreeAPS/Sources/Modules/Home/View/HomeRootView.swift
  5. 2 1
      FreeAPS/Sources/Services/Network/Nightscout/NightscoutManager.swift
  6. 0 537
      FreeAPS/Sources/Services/WatchManager/WatchManager.swift
  7. 0 106
      FreeAPSWatch WatchKit Extension/ComplicationController.swift
  8. 0 33
      FreeAPSWatch WatchKit Extension/DataFlow.swift
  9. 0 15
      FreeAPSWatch WatchKit Extension/FreeAPSApp.swift
  10. 0 16
      FreeAPSWatch WatchKit Extension/FreeAPSWatch WatchKit Extension.entitlements
  11. 0 22
      FreeAPSWatch WatchKit Extension/Info.plist
  12. 0 25
      FreeAPSWatch WatchKit Extension/NotificationController.swift
  13. 0 13
      FreeAPSWatch WatchKit Extension/NotificationView.swift
  14. 0 20
      FreeAPSWatch WatchKit Extension/PushNotificationPayload.apns
  15. 0 118
      FreeAPSWatch WatchKit Extension/Views/BolusConfirmationView.swift
  16. 0 100
      FreeAPSWatch WatchKit Extension/Views/BolusView.swift
  17. 0 253
      FreeAPSWatch WatchKit Extension/Views/CarbsView.swift
  18. 0 86
      FreeAPSWatch WatchKit Extension/Views/ConfirmationView.swift
  19. 0 444
      FreeAPSWatch WatchKit Extension/Views/MainView.swift
  20. 0 56
      FreeAPSWatch WatchKit Extension/Views/TempTargetsView.swift
  21. 0 201
      FreeAPSWatch WatchKit Extension/WatchStateModel.swift
  22. 0 10
      FreeAPSWatch/FreeAPSWatch.entitlements
  23. 0 5
      FreeAPSWatch/Info.plist

+ 2 - 423
FreeAPS.xcodeproj/project.pbxproj

@@ -38,9 +38,7 @@
 		1967DFBE29D052C200759F30 /* Icons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1967DFBD29D052C200759F30 /* Icons.swift */; };
 		1967DFC029D053AC00759F30 /* IconSelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1967DFBF29D053AC00759F30 /* IconSelection.swift */; };
 		1967DFC229D053D300759F30 /* IconImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1967DFC129D053D300759F30 /* IconImage.swift */; };
-		19795118275953E50044850D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 198377D4266BFFF6004DE65E /* Localizable.strings */; };
 		198377D2266BFFF6004DE65E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 198377D4266BFFF6004DE65E /* Localizable.strings */; };
-		199561C1275E61A50077B976 /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 199561C0275E61A50077B976 /* HealthKit.framework */; };
 		19A910302A24BF6300C8951B /* StatsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A9102F2A24BF6300C8951B /* StatsView.swift */; };
 		19A910362A24D6D700C8951B /* DateFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A910352A24D6D700C8951B /* DateFilter.swift */; };
 		19A910382A24EF3200C8951B /* ChartsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A910372A24EF3200C8951B /* ChartsView.swift */; };
@@ -51,8 +49,6 @@
 		19D466AA29AA3099004D5F33 /* MealSettingsRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19D466A929AA3099004D5F33 /* MealSettingsRootView.swift */; };
 		19D4E4EB29FC6A9F00351451 /* Charts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19D4E4EA29FC6A9F00351451 /* Charts.swift */; };
 		19DA48E829CD339B00EEA1E7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 19DA487F29CD2B8400EEA1E7 /* Assets.xcassets */; };
-		19DA48E929CD339C00EEA1E7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 19DA487F29CD2B8400EEA1E7 /* Assets.xcassets */; };
-		19DA48EA29CD339C00EEA1E7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 19DA487F29CD2B8400EEA1E7 /* Assets.xcassets */; };
 		19E1F7E829D082D0005C8D20 /* IconConfigDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19E1F7E729D082D0005C8D20 /* IconConfigDataFlow.swift */; };
 		19E1F7EA29D082ED005C8D20 /* IconConfigProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19E1F7E929D082ED005C8D20 /* IconConfigProvider.swift */; };
 		19E1F7EC29D082FE005C8D20 /* IconConfigStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19E1F7EB29D082FE005C8D20 /* IconConfigStateModel.swift */; };
@@ -190,29 +186,6 @@
 		38E87401274F77E400975559 /* CoreNFC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 38E873FD274F761800975559 /* CoreNFC.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
 		38E87403274F78C000975559 /* libswiftCoreNFC.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 38E87402274F78C000975559 /* libswiftCoreNFC.tbd */; settings = {ATTRIBUTES = (Weak, ); }; };
 		38E87408274F9AD000975559 /* UserNotificationsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E87407274F9AD000975559 /* UserNotificationsManager.swift */; };
-		38E8752527554D5700975559 /* FreeAPSWatch WatchKit Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 38E8752427554D5700975559 /* FreeAPSWatch WatchKit Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
-		38E8752A27554D5700975559 /* FreeAPSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E8752927554D5700975559 /* FreeAPSApp.swift */; };
-		38E8752C27554D5700975559 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E8752B27554D5700975559 /* MainView.swift */; };
-		38E8752E27554D5700975559 /* NotificationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E8752D27554D5700975559 /* NotificationController.swift */; };
-		38E8753027554D5700975559 /* NotificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E8752F27554D5700975559 /* NotificationView.swift */; };
-		38E8753227554D5700975559 /* ComplicationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E8753127554D5700975559 /* ComplicationController.swift */; };
-		38E8753427554D5800975559 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 38E8753327554D5800975559 /* Assets.xcassets */; };
-		38E8753727554D5900975559 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 38E8753627554D5800975559 /* Preview Assets.xcassets */; };
-		38E8753C27554D5900975559 /* FreeAPSWatch.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 38E8751C27554D5500975559 /* FreeAPSWatch.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
-		38E8754727554DF100975559 /* Color+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38F37827261260DC009DB701 /* Color+Extensions.swift */; };
-		38E8754A275550BB00975559 /* CarbsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E87549275550BB00975559 /* CarbsView.swift */; };
-		38E8754C2755548F00975559 /* WatchStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E8754B2755548F00975559 /* WatchStateModel.swift */; };
-		38E8754F275556FA00975559 /* WatchManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E8754E275556FA00975559 /* WatchManager.swift */; };
-		38E8755127555D0500975559 /* DataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E8755027555D0500975559 /* DataFlow.swift */; };
-		38E8755427561E9800975559 /* DataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E8755027555D0500975559 /* DataFlow.swift */; };
-		38E8755827567AE400975559 /* SwiftDate in Frameworks */ = {isa = PBXBuildFile; productRef = 38E8755727567AE400975559 /* SwiftDate */; };
-		38E8755927567CA600975559 /* Decimal+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3871F39E25ED895A0013ECB5 /* Decimal+Extensions.swift */; };
-		38E8755B27568A6800975559 /* ConfirmationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E8755A27568A6700975559 /* ConfirmationView.swift */; };
-		38E8757927579D9200975559 /* Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3811DE5525C9D4D500A708ED /* Publisher.swift */; };
-		38E8757B2757B1C300975559 /* TempTargetsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E8757A2757B1C300975559 /* TempTargetsView.swift */; };
-		38E8757D2757C45D00975559 /* BolusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E8757C2757C45D00975559 /* BolusView.swift */; };
-		38E8757E2758C86A00975559 /* ConvenienceExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38192E0C261BAF980094D973 /* ConvenienceExtensions.swift */; };
-		38E8758027595DC600975559 /* BolusConfirmationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E8757F27595DC500975559 /* BolusConfirmationView.swift */; };
 		38E989DD25F5021400C0CED0 /* PumpStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E989DC25F5021400C0CED0 /* PumpStatus.swift */; };
 		38E98A2325F52C9300C0CED0 /* Signpost.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E98A1B25F52C9300C0CED0 /* Signpost.swift */; };
 		38E98A2425F52C9300C0CED0 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E98A1C25F52C9300C0CED0 /* Logger.swift */; };
@@ -373,7 +346,6 @@
 		CE48C86628CA6B48007C0598 /* OmniPodManagerExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE48C86528CA6B48007C0598 /* OmniPodManagerExtensions.swift */; };
 		CE51DD1C2A01970900F163F7 /* ConnectIQ 2.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE51DD1B2A01970800F163F7 /* ConnectIQ 2.xcframework */; };
 		CE51DD1D2A01970900F163F7 /* ConnectIQ 2.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CE51DD1B2A01970800F163F7 /* ConnectIQ 2.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
-		CE6B025728F350FF000C5502 /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE6B025628F350FF000C5502 /* HealthKit.framework */; };
 		CE7950242997D81700FA576E /* CGMSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7950232997D81700FA576E /* CGMSettingsView.swift */; };
 		CE7950262998056D00FA576E /* CGMSetupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7950252998056D00FA576E /* CGMSetupView.swift */; };
 		CE7CA34E2A064973004BE681 /* AppShortcuts.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7CA3432A064973004BE681 /* AppShortcuts.swift */; };
@@ -483,9 +455,9 @@
 		DD9ECB712CA9A0BA00AA7C45 /* RemoteControlConfigProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9ECB6E2CA9A0BA00AA7C45 /* RemoteControlConfigProvider.swift */; };
 		DD9ECB722CA9A0BA00AA7C45 /* RemoteControlConfigDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9ECB6F2CA9A0BA00AA7C45 /* RemoteControlConfigDataFlow.swift */; };
 		DD9ECB742CA9A0C300AA7C45 /* RemoteControlConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9ECB732CA9A0C300AA7C45 /* RemoteControlConfig.swift */; };
+		DDA6E2502D22187500C2988C /* ChartLegendView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA6E24F2D22187500C2988C /* ChartLegendView.swift */; };
 		DDA6E3202D258E0500C2988C /* OverrideHelpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA6E31F2D258E0500C2988C /* OverrideHelpView.swift */; };
 		DDA6E3222D25901100C2988C /* TempTargetHelpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA6E3212D25901100C2988C /* TempTargetHelpView.swift */; };
-		DDA6E2502D22187500C2988C /* ChartLegendView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA6E24F2D22187500C2988C /* ChartLegendView.swift */; };
 		DDB37CC52D05048F00D99BF4 /* ContactImageStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB37CC42D05048F00D99BF4 /* ContactImageStorage.swift */; };
 		DDB37CC72D05127500D99BF4 /* FontExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB37CC62D05127500D99BF4 /* FontExtensions.swift */; };
 		DDCEBF5B2CC1B76400DF4C36 /* LiveActivity+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDCEBF5A2CC1B76400DF4C36 /* LiveActivity+Helper.swift */; };
@@ -567,20 +539,6 @@
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
-		38E8752627554D5700975559 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 388E595025AD948C0019842D /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 38E8752327554D5700975559;
-			remoteInfo = "FreeAPSWatch WatchKit Extension";
-		};
-		38E8753A27554D5900975559 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 388E595025AD948C0019842D /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 38E8751B27554D5500975559;
-			remoteInfo = FreeAPSWatch;
-		};
 		38FCF3F225E9028E0078B0D1 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 388E595025AD948C0019842D /* Project object */;
@@ -621,22 +579,10 @@
 			dstPath = "$(CONTENTS_FOLDER_PATH)/Watch";
 			dstSubfolderSpec = 16;
 			files = (
-				38E8753C27554D5900975559 /* FreeAPSWatch.app in Embed Watch Content */,
 			);
 			name = "Embed Watch Content";
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		38E8754027554D5900975559 /* Embed App Extensions */ = {
-			isa = PBXCopyFilesBuildPhase;
-			buildActionMask = 2147483647;
-			dstPath = "";
-			dstSubfolderSpec = 13;
-			files = (
-				38E8752527554D5700975559 /* FreeAPSWatch WatchKit Extension.appex in Embed App Extensions */,
-			);
-			name = "Embed App Extensions";
-			runOnlyForDeploymentPostprocessing = 0;
-		};
 		6B1A8D122B14D88E00E76752 /* Embed Foundation Extensions */ = {
 			isa = PBXCopyFilesBuildPhase;
 			buildActionMask = 2147483647;
@@ -701,7 +647,6 @@
 		1967DFBD29D052C200759F30 /* Icons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Icons.swift; sourceTree = "<group>"; };
 		1967DFBF29D053AC00759F30 /* IconSelection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconSelection.swift; sourceTree = "<group>"; };
 		1967DFC129D053D300759F30 /* IconImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconImage.swift; sourceTree = "<group>"; };
-		1980131D29CC9839002FF024 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
 		198377D3266BFFF6004DE65E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
 		198377D5266C0A05004DE65E /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Localizable.strings; sourceTree = "<group>"; };
 		198377D6266C0A0A004DE65E /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/Localizable.strings; sourceTree = "<group>"; };
@@ -886,28 +831,6 @@
 		38E873FD274F761800975559 /* CoreNFC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreNFC.framework; path = System/Library/Frameworks/CoreNFC.framework; sourceTree = SDKROOT; };
 		38E87402274F78C000975559 /* libswiftCoreNFC.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libswiftCoreNFC.tbd; path = usr/lib/swift/libswiftCoreNFC.tbd; sourceTree = SDKROOT; };
 		38E87407274F9AD000975559 /* UserNotificationsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationsManager.swift; sourceTree = "<group>"; };
-		38E8751C27554D5500975559 /* FreeAPSWatch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FreeAPSWatch.app; sourceTree = BUILT_PRODUCTS_DIR; };
-		38E8751E27554D5700975559 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
-		38E8752427554D5700975559 /* FreeAPSWatch WatchKit Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "FreeAPSWatch WatchKit Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
-		38E8752927554D5700975559 /* FreeAPSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FreeAPSApp.swift; sourceTree = "<group>"; };
-		38E8752B27554D5700975559 /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
-		38E8752D27554D5700975559 /* NotificationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationController.swift; sourceTree = "<group>"; };
-		38E8752F27554D5700975559 /* NotificationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationView.swift; sourceTree = "<group>"; };
-		38E8753127554D5700975559 /* ComplicationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComplicationController.swift; sourceTree = "<group>"; };
-		38E8753327554D5800975559 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
-		38E8753627554D5800975559 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
-		38E8753827554D5900975559 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
-		38E8753927554D5900975559 /* PushNotificationPayload.apns */ = {isa = PBXFileReference; lastKnownFileType = text; path = PushNotificationPayload.apns; sourceTree = "<group>"; };
-		38E87549275550BB00975559 /* CarbsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarbsView.swift; sourceTree = "<group>"; };
-		38E8754B2755548F00975559 /* WatchStateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchStateModel.swift; sourceTree = "<group>"; };
-		38E8754E275556FA00975559 /* WatchManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchManager.swift; sourceTree = "<group>"; };
-		38E8755027555D0500975559 /* DataFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataFlow.swift; sourceTree = "<group>"; };
-		38E8755527564B5000975559 /* FreeAPSWatch WatchKit Extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "FreeAPSWatch WatchKit Extension.entitlements"; sourceTree = "<group>"; };
-		38E8755627564B6100975559 /* FreeAPSWatch.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = FreeAPSWatch.entitlements; sourceTree = "<group>"; };
-		38E8755A27568A6700975559 /* ConfirmationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmationView.swift; sourceTree = "<group>"; };
-		38E8757A2757B1C300975559 /* TempTargetsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TempTargetsView.swift; sourceTree = "<group>"; };
-		38E8757C2757C45D00975559 /* BolusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BolusView.swift; sourceTree = "<group>"; };
-		38E8757F27595DC500975559 /* BolusConfirmationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BolusConfirmationView.swift; sourceTree = "<group>"; };
 		38E989DC25F5021400C0CED0 /* PumpStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PumpStatus.swift; sourceTree = "<group>"; };
 		38E98A1B25F52C9300C0CED0 /* Signpost.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Signpost.swift; sourceTree = "<group>"; };
 		38E98A1C25F52C9300C0CED0 /* Logger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
@@ -1188,9 +1111,9 @@
 		DD9ECB6E2CA9A0BA00AA7C45 /* RemoteControlConfigProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RemoteControlConfigProvider.swift; sourceTree = "<group>"; };
 		DD9ECB6F2CA9A0BA00AA7C45 /* RemoteControlConfigDataFlow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RemoteControlConfigDataFlow.swift; sourceTree = "<group>"; };
 		DD9ECB732CA9A0C300AA7C45 /* RemoteControlConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RemoteControlConfig.swift; sourceTree = "<group>"; };
+		DDA6E24F2D22187500C2988C /* ChartLegendView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartLegendView.swift; sourceTree = "<group>"; };
 		DDA6E31F2D258E0500C2988C /* OverrideHelpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverrideHelpView.swift; sourceTree = "<group>"; };
 		DDA6E3212D25901100C2988C /* TempTargetHelpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TempTargetHelpView.swift; sourceTree = "<group>"; };
-		DDA6E24F2D22187500C2988C /* ChartLegendView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartLegendView.swift; sourceTree = "<group>"; };
 		DDB37CC22D05044D00D99BF4 /* ContactTrickEntryStored+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ContactTrickEntryStored+CoreDataClass.swift"; sourceTree = "<group>"; };
 		DDB37CC32D05044D00D99BF4 /* ContactTrickEntryStored+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ContactTrickEntryStored+CoreDataProperties.swift"; sourceTree = "<group>"; };
 		DDB37CC42D05048F00D99BF4 /* ContactImageStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactImageStorage.swift; sourceTree = "<group>"; };
@@ -1296,16 +1219,6 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		38E8752127554D5700975559 /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				CE6B025728F350FF000C5502 /* HealthKit.framework in Frameworks */,
-				38E8755827567AE400975559 /* SwiftDate in Frameworks */,
-				199561C1275E61A50077B976 /* HealthKit.framework in Frameworks */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
 		38FCF3EA25E9028E0078B0D1 /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
@@ -1952,8 +1865,6 @@
 				388E595A25AD948C0019842D /* FreeAPS */,
 				38FCF3EE25E9028E0078B0D1 /* FreeAPSTests */,
 				3818AA44274C229000843DB3 /* Packages */,
-				38E8751D27554D5500975559 /* FreeAPSWatch */,
-				38E8752827554D5700975559 /* FreeAPSWatch WatchKit Extension */,
 				6B1A8D1C2B14D91600E76752 /* LiveActivity */,
 				388E595925AD948C0019842D /* Products */,
 				3818AA48274C267000843DB3 /* Frameworks */,
@@ -1966,8 +1877,6 @@
 			children = (
 				388E595825AD948C0019842D /* FreeAPS.app */,
 				38FCF3ED25E9028E0078B0D1 /* FreeAPSTests.xctest */,
-				38E8751C27554D5500975559 /* FreeAPSWatch.app */,
-				38E8752427554D5700975559 /* FreeAPSWatch WatchKit Extension.appex */,
 				6B1A8D172B14D91600E76752 /* LiveActivityExtension.appex */,
 			);
 			name = Products;
@@ -2180,60 +2089,9 @@
 			path = UserNotifications;
 			sourceTree = "<group>";
 		};
-		38E8751D27554D5500975559 /* FreeAPSWatch */ = {
-			isa = PBXGroup;
-			children = (
-				1980131D29CC9839002FF024 /* Info.plist */,
-				38E8755627564B6100975559 /* FreeAPSWatch.entitlements */,
-				38E8751E27554D5700975559 /* Assets.xcassets */,
-			);
-			path = FreeAPSWatch;
-			sourceTree = "<group>";
-		};
-		38E8752827554D5700975559 /* FreeAPSWatch WatchKit Extension */ = {
-			isa = PBXGroup;
-			children = (
-				38E8755527564B5000975559 /* FreeAPSWatch WatchKit Extension.entitlements */,
-				38E8755027555D0500975559 /* DataFlow.swift */,
-				38E8754B2755548F00975559 /* WatchStateModel.swift */,
-				38E875482755505800975559 /* Views */,
-				38E8752927554D5700975559 /* FreeAPSApp.swift */,
-				38E8752D27554D5700975559 /* NotificationController.swift */,
-				38E8752F27554D5700975559 /* NotificationView.swift */,
-				38E8753127554D5700975559 /* ComplicationController.swift */,
-				38E8753327554D5800975559 /* Assets.xcassets */,
-				38E8753827554D5900975559 /* Info.plist */,
-				38E8753927554D5900975559 /* PushNotificationPayload.apns */,
-				38E8753527554D5800975559 /* Preview Content */,
-			);
-			path = "FreeAPSWatch WatchKit Extension";
-			sourceTree = "<group>";
-		};
-		38E8753527554D5800975559 /* Preview Content */ = {
-			isa = PBXGroup;
-			children = (
-				38E8753627554D5800975559 /* Preview Assets.xcassets */,
-			);
-			path = "Preview Content";
-			sourceTree = "<group>";
-		};
-		38E875482755505800975559 /* Views */ = {
-			isa = PBXGroup;
-			children = (
-				38E8752B27554D5700975559 /* MainView.swift */,
-				38E87549275550BB00975559 /* CarbsView.swift */,
-				38E8755A27568A6700975559 /* ConfirmationView.swift */,
-				38E8757A2757B1C300975559 /* TempTargetsView.swift */,
-				38E8757C2757C45D00975559 /* BolusView.swift */,
-				38E8757F27595DC500975559 /* BolusConfirmationView.swift */,
-			);
-			path = Views;
-			sourceTree = "<group>";
-		};
 		38E8754D275556E100975559 /* WatchManager */ = {
 			isa = PBXGroup;
 			children = (
-				38E8754E275556FA00975559 /* WatchManager.swift */,
 				CE94597D29E9E1EE0047C9C6 /* GarminManager.swift */,
 			);
 			path = WatchManager;
@@ -3117,7 +2975,6 @@
 			buildRules = (
 			);
 			dependencies = (
-				38E8753B27554D5900975559 /* PBXTargetDependency */,
 				6B1A8D272B14D91700E76752 /* PBXTargetDependency */,
 			);
 			name = FreeAPS;
@@ -3133,43 +2990,6 @@
 			productReference = 388E595825AD948C0019842D /* FreeAPS.app */;
 			productType = "com.apple.product-type.application";
 		};
-		38E8751B27554D5500975559 /* FreeAPSWatch */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 38E8754427554D5900975559 /* Build configuration list for PBXNativeTarget "FreeAPSWatch" */;
-			buildPhases = (
-				38E8751A27554D5500975559 /* Resources */,
-				38E8754027554D5900975559 /* Embed App Extensions */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-				38E8752727554D5700975559 /* PBXTargetDependency */,
-			);
-			name = FreeAPSWatch;
-			productName = FreeAPSWatch;
-			productReference = 38E8751C27554D5500975559 /* FreeAPSWatch.app */;
-			productType = "com.apple.product-type.application.watchapp2";
-		};
-		38E8752327554D5700975559 /* FreeAPSWatch WatchKit Extension */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 38E8754327554D5900975559 /* Build configuration list for PBXNativeTarget "FreeAPSWatch WatchKit Extension" */;
-			buildPhases = (
-				38E8752027554D5700975559 /* Sources */,
-				38E8752127554D5700975559 /* Frameworks */,
-				38E8752227554D5700975559 /* Resources */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-			);
-			name = "FreeAPSWatch WatchKit Extension";
-			packageProductDependencies = (
-				38E8755727567AE400975559 /* SwiftDate */,
-			);
-			productName = "FreeAPSWatch WatchKit Extension";
-			productReference = 38E8752427554D5700975559 /* FreeAPSWatch WatchKit Extension.appex */;
-			productType = "com.apple.product-type.watchkit2-extension";
-		};
 		38FCF3EC25E9028E0078B0D1 /* FreeAPSTests */ = {
 			isa = PBXNativeTarget;
 			buildConfigurationList = 38FCF3F425E9028E0078B0D1 /* Build configuration list for PBXNativeTarget "FreeAPSTests" */;
@@ -3219,13 +3039,6 @@
 					388E595725AD948C0019842D = {
 						CreatedOnToolsVersion = 12.3;
 					};
-					38E8751B27554D5500975559 = {
-						CreatedOnToolsVersion = 13.1;
-						LastSwiftMigration = 1530;
-					};
-					38E8752327554D5700975559 = {
-						CreatedOnToolsVersion = 13.1;
-					};
 					38FCF3EC25E9028E0078B0D1 = {
 						CreatedOnToolsVersion = 12.4;
 						TestTargetID = 388E595725AD948C0019842D;
@@ -3277,8 +3090,6 @@
 			targets = (
 				388E595725AD948C0019842D /* FreeAPS */,
 				38FCF3EC25E9028E0078B0D1 /* FreeAPSTests */,
-				38E8751B27554D5500975559 /* FreeAPSWatch */,
-				38E8752327554D5700975559 /* FreeAPSWatch WatchKit Extension */,
 				6B1A8D162B14D91500E76752 /* LiveActivityExtension */,
 			);
 		};
@@ -3301,25 +3112,6 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		38E8751A27554D5500975559 /* Resources */ = {
-			isa = PBXResourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				19DA48E929CD339C00EEA1E7 /* Assets.xcassets in Resources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		38E8752227554D5700975559 /* Resources */ = {
-			isa = PBXResourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				38E8753727554D5900975559 /* Preview Assets.xcassets in Resources */,
-				19795118275953E50044850D /* Localizable.strings in Resources */,
-				19DA48EA29CD339C00EEA1E7 /* Assets.xcassets in Resources */,
-				38E8753427554D5800975559 /* Assets.xcassets in Resources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
 		38FCF3EB25E9028E0078B0D1 /* Resources */ = {
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -3778,7 +3570,6 @@
 				E13B7DAB2A435F57066AF02E /* TargetsEditorStateModel.swift in Sources */,
 				9702FF92A09C53942F20D7EA /* TargetsEditorRootView.swift in Sources */,
 				1967DFBE29D052C200759F30 /* Icons.swift in Sources */,
-				38E8754F275556FA00975559 /* WatchManager.swift in Sources */,
 				DDD163182C4C694000CD525A /* AdjustmentsRootView.swift in Sources */,
 				389ECE052601144100D86C4F /* ConcurrentMap.swift in Sources */,
 				110AEDEC2C51A0AE00615CC9 /* ShortcutsConfigDataFlow.swift in Sources */,
@@ -3786,7 +3577,6 @@
 				19E1F7EA29D082ED005C8D20 /* IconConfigProvider.swift in Sources */,
 				DD09D4822C5986F6003FEA5D /* CalendarEventSettingsRootView.swift in Sources */,
 				CE48C86428CA69D5007C0598 /* OmniBLEPumpManagerExtensions.swift in Sources */,
-				38E8755427561E9800975559 /* DataFlow.swift in Sources */,
 				DD5DC9F92CF3DAA900AB8703 /* RadioButton.swift in Sources */,
 				38E44522274E3DDC00EC9A94 /* NetworkReachabilityManager.swift in Sources */,
 				CE7CA34F2A064973004BE681 /* BaseIntentsRequest.swift in Sources */,
@@ -3912,29 +3702,6 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-		38E8752027554D5700975559 /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				38E8757927579D9200975559 /* Publisher.swift in Sources */,
-				38E8755B27568A6800975559 /* ConfirmationView.swift in Sources */,
-				38E8757D2757C45D00975559 /* BolusView.swift in Sources */,
-				38E8752E27554D5700975559 /* NotificationController.swift in Sources */,
-				38E8754C2755548F00975559 /* WatchStateModel.swift in Sources */,
-				38E8754A275550BB00975559 /* CarbsView.swift in Sources */,
-				38E8752C27554D5700975559 /* MainView.swift in Sources */,
-				38E8755127555D0500975559 /* DataFlow.swift in Sources */,
-				38E8753227554D5700975559 /* ComplicationController.swift in Sources */,
-				38E8752A27554D5700975559 /* FreeAPSApp.swift in Sources */,
-				38E8757B2757B1C300975559 /* TempTargetsView.swift in Sources */,
-				38E8753027554D5700975559 /* NotificationView.swift in Sources */,
-				38E8757E2758C86A00975559 /* ConvenienceExtensions.swift in Sources */,
-				38E8754727554DF100975559 /* Color+Extensions.swift in Sources */,
-				38E8755927567CA600975559 /* Decimal+Extensions.swift in Sources */,
-				38E8758027595DC600975559 /* BolusConfirmationView.swift in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
 		38FCF3E925E9028E0078B0D1 /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -3960,16 +3727,6 @@
 /* End PBXSourcesBuildPhase section */
 
 /* Begin PBXTargetDependency section */
-		38E8752727554D5700975559 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 38E8752327554D5700975559 /* FreeAPSWatch WatchKit Extension */;
-			targetProxy = 38E8752627554D5700975559 /* PBXContainerItemProxy */;
-		};
-		38E8753B27554D5900975559 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 38E8751B27554D5500975559 /* FreeAPSWatch */;
-			targetProxy = 38E8753A27554D5900975559 /* PBXContainerItemProxy */;
-		};
 		38FCF3F325E9028E0078B0D1 /* PBXTargetDependency */ = {
 			isa = PBXTargetDependency;
 			target = 388E595725AD948C0019842D /* FreeAPS */;
@@ -4254,161 +4011,6 @@
 			};
 			name = Release;
 		};
-		38E8753E27554D5900975559 /* Debug */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
-				APP_DISPLAY_NAME = "$(APP_DISPLAY_NAME)";
-				ASSETCATALOG_COMPILER_APPICON_NAME = "$(APP_ICON)";
-				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
-				ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
-				ASSETCATALOG_COMPILER_INCLUDE_STICKER_CONTENT = YES;
-				ASSETCATALOG_COMPILER_STANDALONE_ICON_BEHAVIOR = all;
-				ASSETCATALOG_COMPILER_TARGET_STICKERS_ICON_ROLE = "host-app";
-				BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER)";
-				CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
-				CLANG_ENABLE_MODULES = YES;
-				CODE_SIGN_ENTITLEMENTS = FreeAPSWatch/FreeAPSWatch.entitlements;
-				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = $APP_BUILD_NUMBER;
-				DEVELOPMENT_TEAM = "$(DEVELOPER_TEAM)";
-				GENERATE_INFOPLIST_FILE = YES;
-				IBSC_MODULE = FreeAPSWatch_WatchKit_Extension;
-				INFOPLIST_FILE = FreeAPSWatch/Info.plist;
-				INFOPLIST_KEY_CFBundleDisplayName = "$(APP_DISPLAY_NAME)";
-				INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
-				INFOPLIST_KEY_WKCompanionAppBundleIdentifier = "$(BUNDLE_IDENTIFIER)";
-				MARKETING_VERSION = "$(APP_VERSION)";
-				PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER).watchkitapp";
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				SDKROOT = watchos;
-				SKIP_INSTALL = YES;
-				SWIFT_EMIT_LOC_STRINGS = YES;
-				SWIFT_OBJC_BRIDGING_HEADER = "Model/Classes+Properties/FreeAPSWatch-Bridging-Header.h";
-				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
-				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = 4;
-				WATCHOS_DEPLOYMENT_TARGET = 10;
-			};
-			name = Debug;
-		};
-		38E8753F27554D5900975559 /* Release */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
-				APP_DISPLAY_NAME = "$(APP_DISPLAY_NAME)";
-				ASSETCATALOG_COMPILER_APPICON_NAME = "$(APP_ICON)";
-				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
-				ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
-				ASSETCATALOG_COMPILER_INCLUDE_STICKER_CONTENT = YES;
-				ASSETCATALOG_COMPILER_STANDALONE_ICON_BEHAVIOR = all;
-				ASSETCATALOG_COMPILER_TARGET_STICKERS_ICON_ROLE = "host-app";
-				BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER)";
-				CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
-				CLANG_ENABLE_MODULES = YES;
-				CODE_SIGN_ENTITLEMENTS = FreeAPSWatch/FreeAPSWatch.entitlements;
-				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = $APP_BUILD_NUMBER;
-				DEVELOPMENT_TEAM = "$(DEVELOPER_TEAM)";
-				GENERATE_INFOPLIST_FILE = YES;
-				IBSC_MODULE = FreeAPSWatch_WatchKit_Extension;
-				INFOPLIST_FILE = FreeAPSWatch/Info.plist;
-				INFOPLIST_KEY_CFBundleDisplayName = "$(APP_DISPLAY_NAME)";
-				INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
-				INFOPLIST_KEY_WKCompanionAppBundleIdentifier = "$(BUNDLE_IDENTIFIER)";
-				MARKETING_VERSION = "$(APP_VERSION)";
-				PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER).watchkitapp";
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				SDKROOT = watchos;
-				SKIP_INSTALL = YES;
-				SWIFT_EMIT_LOC_STRINGS = YES;
-				SWIFT_OBJC_BRIDGING_HEADER = "Model/Classes+Properties/FreeAPSWatch-Bridging-Header.h";
-				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = 4;
-				WATCHOS_DEPLOYMENT_TARGET = 10;
-			};
-			name = Release;
-		};
-		38E8754127554D5900975559 /* Debug */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				APP_DISPLAY_NAME = "$(APP_DISPLAY_NAME)";
-				ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication;
-				BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER)";
-				CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
-				CODE_SIGN_ENTITLEMENTS = "FreeAPSWatch WatchKit Extension/FreeAPSWatch WatchKit Extension.entitlements";
-				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = $APP_BUILD_NUMBER;
-				DEVELOPMENT_ASSET_PATHS = "\"FreeAPSWatch WatchKit Extension/Preview Content\"";
-				DEVELOPMENT_TEAM = "$(DEVELOPER_TEAM)";
-				ENABLE_PREVIEWS = YES;
-				GENERATE_INFOPLIST_FILE = YES;
-				INFOPLIST_FILE = "FreeAPSWatch WatchKit Extension/Info.plist";
-				INFOPLIST_KEY_CFBundleDisplayName = "$(APP_DISPLAY_NAME) WatchKit Extension";
-				INFOPLIST_KEY_CLKComplicationPrincipalClass = FreeAPSWatch_WatchKit_Extension.ComplicationController;
-				INFOPLIST_KEY_NSHealthClinicalHealthRecordsShareUsageDescription = "Bla bla Record Health";
-				INFOPLIST_KEY_NSHealthShareUsageDescription = "Bla bla Share Health";
-				INFOPLIST_KEY_NSHealthUpdateUsageDescription = "Bla bla Update Health";
-				INFOPLIST_KEY_NSHumanReadableCopyright = "";
-				INFOPLIST_KEY_WKRunsIndependentlyOfCompanionApp = NO;
-				LD_RUNPATH_SEARCH_PATHS = (
-					"$(inherited)",
-					"@executable_path/Frameworks",
-					"@executable_path/../../Frameworks",
-				);
-				MARKETING_VERSION = "$(APP_VERSION)";
-				PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER).watchkitapp.watchkitextension";
-				PRODUCT_NAME = "${TARGET_NAME}";
-				SDKROOT = watchos;
-				SKIP_INSTALL = YES;
-				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG RUN_STATISTICS";
-				SWIFT_EMIT_LOC_STRINGS = YES;
-				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = 4;
-				WATCHOS_DEPLOYMENT_TARGET = 10;
-			};
-			name = Debug;
-		};
-		38E8754227554D5900975559 /* Release */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				APP_DISPLAY_NAME = "$(APP_DISPLAY_NAME)";
-				ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication;
-				BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER)";
-				CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
-				CODE_SIGN_ENTITLEMENTS = "FreeAPSWatch WatchKit Extension/FreeAPSWatch WatchKit Extension.entitlements";
-				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = $APP_BUILD_NUMBER;
-				DEVELOPMENT_ASSET_PATHS = "\"FreeAPSWatch WatchKit Extension/Preview Content\"";
-				DEVELOPMENT_TEAM = "$(DEVELOPER_TEAM)";
-				ENABLE_PREVIEWS = YES;
-				GENERATE_INFOPLIST_FILE = YES;
-				INFOPLIST_FILE = "FreeAPSWatch WatchKit Extension/Info.plist";
-				INFOPLIST_KEY_CFBundleDisplayName = "$(APP_DISPLAY_NAME) WatchKit Extension";
-				INFOPLIST_KEY_CLKComplicationPrincipalClass = FreeAPSWatch_WatchKit_Extension.ComplicationController;
-				INFOPLIST_KEY_NSHealthClinicalHealthRecordsShareUsageDescription = "Bla bla Record Health";
-				INFOPLIST_KEY_NSHealthShareUsageDescription = "Bla bla Share Health";
-				INFOPLIST_KEY_NSHealthUpdateUsageDescription = "Bla bla Update Health";
-				INFOPLIST_KEY_NSHumanReadableCopyright = "";
-				INFOPLIST_KEY_WKRunsIndependentlyOfCompanionApp = NO;
-				LD_RUNPATH_SEARCH_PATHS = (
-					"$(inherited)",
-					"@executable_path/Frameworks",
-					"@executable_path/../../Frameworks",
-				);
-				MARKETING_VERSION = "$(APP_VERSION)";
-				PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_IDENTIFIER).watchkitapp.watchkitextension";
-				PRODUCT_NAME = "${TARGET_NAME}";
-				SDKROOT = watchos;
-				SKIP_INSTALL = YES;
-				SWIFT_ACTIVE_COMPILATION_CONDITIONS = RUN_STATISTICS;
-				SWIFT_EMIT_LOC_STRINGS = YES;
-				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = 4;
-				WATCHOS_DEPLOYMENT_TARGET = 10;
-			};
-			name = Release;
-		};
 		38FCF3F525E9028E0078B0D1 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
@@ -4539,24 +4141,6 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Debug;
 		};
-		38E8754327554D5900975559 /* Build configuration list for PBXNativeTarget "FreeAPSWatch WatchKit Extension" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				38E8754127554D5900975559 /* Debug */,
-				38E8754227554D5900975559 /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Debug;
-		};
-		38E8754427554D5900975559 /* Build configuration list for PBXNativeTarget "FreeAPSWatch" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				38E8753E27554D5900975559 /* Debug */,
-				38E8753F27554D5900975559 /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Debug;
-		};
 		38FCF3F425E9028E0078B0D1 /* Build configuration list for PBXNativeTarget "FreeAPSTests" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
@@ -4649,11 +4233,6 @@
 			package = 38DF1787276FC8C300B3528F /* XCRemoteSwiftPackageReference "SwiftMessages" */;
 			productName = SwiftMessages;
 		};
-		38E8755727567AE400975559 /* SwiftDate */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = 38B17B6425DD90E0005CAE3D /* XCRemoteSwiftPackageReference "SwiftDate" */;
-			productName = SwiftDate;
-		};
 		B958F1B62BA0711600484851 /* MKRingProgressView */ = {
 			isa = XCSwiftPackageProductDependency;
 			package = B958F1B52BA0711600484851 /* XCRemoteSwiftPackageReference "MKRingProgressView" */;

+ 0 - 1
FreeAPS/Sources/Application/FreeAPSApp.swift

@@ -48,7 +48,6 @@ import Swinject
         _ = resolver.resolve(FetchTreatmentsManager.self)!
         _ = resolver.resolve(CalendarManager.self)!
         _ = resolver.resolve(UserNotificationsManager.self)!
-        _ = resolver.resolve(WatchManager.self)!
         _ = resolver.resolve(HealthKitManager.self)!
         _ = resolver.resolve(BluetoothStateManager.self)!
         _ = resolver.resolve(PluginManager.self)!

+ 0 - 1
FreeAPS/Sources/Assemblies/ServiceAssembly.swift

@@ -18,7 +18,6 @@ final class ServiceAssembly: Assembly {
         container.register(HKHealthStore.self) { _ in HKHealthStore() }
         container.register(HealthKitManager.self) { r in BaseHealthKitManager(resolver: r) }
         container.register(UserNotificationsManager.self) { r in BaseUserNotificationsManager(resolver: r) }
-        container.register(WatchManager.self) { r in BaseWatchManager(resolver: r) }
         container.register(GarminManager.self) { r in BaseGarminManager(resolver: r) }
         container.register(ContactImageManager.self) { r in BaseContactImageManager(resolver: r) }
         container.register(AlertPermissionsChecker.self) { r in AlertPermissionsChecker(resolver: r) }

+ 7 - 5
FreeAPS/Sources/Modules/Home/View/HomeRootView.swift

@@ -980,7 +980,7 @@ extension Home {
             let patterns = [
                 "minGuardBG\\s*-?\\d+\\.?\\d*<-?\\d+\\.?\\d*", // minGuardBG x<y
                 "Eventual BG\\s*-?\\d+\\.?\\d*\\s*>=\\s*-?\\d+\\.?\\d*", // Eventual BG x >= target
-                "Eventual BG\\s*-?\\d+\\.?\\d*\\s*<\\s*-?\\d+\\.?\\d*",  // Eventual BG x < target
+                "Eventual BG\\s*-?\\d+\\.?\\d*\\s*<\\s*-?\\d+\\.?\\d*", // Eventual BG x < target
                 "(\\S+)\\s+(-?\\d+\\.?\\d*)\\s*>\\s*(\\d+)%\\s+of\\s+BG\\s+(-?\\d+\\.?\\d*)" // maxDelta x > y% of BG z
             ]
             let pattern = patterns.joined(separator: "|")
@@ -1005,18 +1005,19 @@ extension Home {
                 let matchedString = String(reasonConclusion[range])
 
                 if isMmolL {
-                    if matchedString.contains("<") && matchedString.contains("Eventual BG") && !matchedString.contains("=") {
+                    if matchedString.contains("<"), matchedString.contains("Eventual BG"), !matchedString.contains("=") {
                         // Handle "Eventual BG x < target" pattern
                         let parts = matchedString.components(separatedBy: "<")
                         if parts.count == 2 {
-                            let bgPart = parts[0].replacingOccurrences(of: "Eventual BG", with: "").trimmingCharacters(in: .whitespaces)
+                            let bgPart = parts[0].replacingOccurrences(of: "Eventual BG", with: "")
+                                .trimmingCharacters(in: .whitespaces)
                             let targetValue = parts[1].trimmingCharacters(in: .whitespaces)
                             let formattedBGPart = convertToMmolL(bgPart)
                             let formattedTargetValue = convertToMmolL(targetValue)
                             let formattedString = "Eventual BG \(formattedBGPart)<\(formattedTargetValue)"
                             updatedConclusion.replaceSubrange(range, with: formattedString)
                         }
-                    } else if matchedString.contains("<") && matchedString.contains("minGuardBG") {
+                    } else if matchedString.contains("<"), matchedString.contains("minGuardBG") {
                         // Handle "minGuardBG x<y" pattern
                         let parts = matchedString.components(separatedBy: "<")
                         if parts.count == 2 {
@@ -1031,7 +1032,8 @@ extension Home {
                         // Handle "Eventual BG x >= target" pattern
                         let parts = matchedString.components(separatedBy: " >= ")
                         if parts.count == 2 {
-                            let firstValue = parts[0].replacingOccurrences(of: "Eventual BG", with: "").trimmingCharacters(in: .whitespaces)
+                            let firstValue = parts[0].replacingOccurrences(of: "Eventual BG", with: "")
+                                .trimmingCharacters(in: .whitespaces)
                             let secondValue = parts[1].trimmingCharacters(in: .whitespaces)
                             let formattedFirstValue = convertToMmolL(firstValue)
                             let formattedSecondValue = convertToMmolL(secondValue)

+ 2 - 1
FreeAPS/Sources/Services/Network/Nightscout/NightscoutManager.swift

@@ -1205,7 +1205,8 @@ extension BaseNightscoutManager {
                 // Handle "Eventual BG X >= Y"
                 let parts = glucoseValueString.components(separatedBy: " >= ")
                 if parts.count == 2 {
-                    let firstValue = parts[0].replacingOccurrences(of: "Eventual BG", with: "").trimmingCharacters(in: .whitespaces)
+                    let firstValue = parts[0].replacingOccurrences(of: "Eventual BG", with: "")
+                        .trimmingCharacters(in: .whitespaces)
                     let secondValue = parts[1].trimmingCharacters(in: .whitespaces)
                     let formattedFirstValue = convertToMmolL(firstValue)
                     let formattedSecondValue = convertToMmolL(secondValue)

+ 0 - 537
FreeAPS/Sources/Services/WatchManager/WatchManager.swift

@@ -1,537 +0,0 @@
-import Combine
-import CoreData
-import Foundation
-import Swinject
-import WatchConnectivity
-
-protocol WatchManager {}
-
-final class BaseWatchManager: NSObject, WatchManager, Injectable {
-    private let session: WCSession
-    private var state = WatchState()
-    private let processQueue = DispatchQueue(label: "BaseWatchManager.processQueue")
-
-    @Injected() private var broadcaster: Broadcaster!
-    @Injected() private var settingsManager: SettingsManager!
-    @Injected() private var apsManager: APSManager!
-    @Injected() private var storage: FileStorage!
-    @Injected() private var carbsStorage: CarbsStorage!
-    @Injected() private var tempTargetsStorage: TempTargetsStorage!
-    @Injected() private var garmin: GarminManager!
-    @Injected() private var glucoseStorage: GlucoseStorage!
-
-    private var glucoseFormatter: NumberFormatter {
-        let formatter = NumberFormatter()
-        formatter.numberStyle = .decimal
-        formatter.maximumFractionDigits = 0
-        if settingsManager.settings.units == .mmolL {
-            formatter.minimumFractionDigits = 1
-            formatter.maximumFractionDigits = 1
-        }
-        formatter.roundingMode = .halfUp
-        return formatter
-    }
-
-    private var eventualFormatter: NumberFormatter {
-        let formatter = NumberFormatter()
-        formatter.numberStyle = .decimal
-        formatter.maximumFractionDigits = 1
-        return formatter
-    }
-
-    private var deltaFormatter: NumberFormatter {
-        let formatter = NumberFormatter()
-        formatter.numberStyle = .decimal
-        formatter.maximumFractionDigits = settingsManager.settings.units == .mmolL ? 1 : 0
-        formatter.positivePrefix = "+"
-        formatter.negativePrefix = "-"
-        return formatter
-    }
-
-    private var targetFormatter: NumberFormatter {
-        let formatter = NumberFormatter()
-        formatter.numberStyle = .decimal
-        formatter.maximumFractionDigits = 1
-        return formatter
-    }
-
-    let context = CoreDataStack.shared.newTaskContext()
-    let viewContext = CoreDataStack.shared.persistentContainer.viewContext
-
-    private var coreDataPublisher: AnyPublisher<Set<NSManagedObject>, Never>?
-    private var subscriptions = Set<AnyCancellable>()
-
-    private var lifetime = Lifetime()
-
-    init(resolver: Resolver, session: WCSession = .default) {
-        self.session = session
-        super.init()
-        injectServices(resolver)
-        registerHandlers()
-        registerSubscribers()
-
-        coreDataPublisher =
-            changedObjectsOnManagedObjectContextDidSavePublisher()
-                .receive(on: DispatchQueue.global(qos: .background))
-                .share()
-                .eraseToAnyPublisher()
-
-        Task {
-            await configureState()
-        }
-
-        if WCSession.isSupported() {
-            session.delegate = self
-            session.activate()
-        }
-
-        broadcaster.register(SettingsObserver.self, observer: self)
-        broadcaster.register(PumpHistoryObserver.self, observer: self)
-        broadcaster.register(PumpSettingsObserver.self, observer: self)
-        broadcaster.register(BasalProfileObserver.self, observer: self)
-        broadcaster.register(TempTargetsObserver.self, observer: self)
-        broadcaster.register(CarbsObserver.self, observer: self)
-        broadcaster.register(PumpBatteryObserver.self, observer: self)
-        broadcaster.register(PumpReservoirObserver.self, observer: self)
-        garmin.stateRequet = { [weak self] () -> Data in
-            guard let self = self, let data = try? JSONEncoder().encode(self.state) else {
-                warning(.service, "Cannot encode watch state")
-                return Data()
-            }
-            return data
-        }
-    }
-
-    private func registerSubscribers() {
-        glucoseStorage.updatePublisher
-            .receive(on: DispatchQueue.global(qos: .background))
-            .sink { [weak self] _ in
-                guard let self = self else { return }
-                Task {
-                    await self.configureState()
-                }
-            }
-            .store(in: &subscriptions)
-    }
-
-    private func registerHandlers() {
-        coreDataPublisher?.filterByEntityName("OrefDetermination").sink { [weak self] _ in
-            guard let self = self else { return }
-            Task {
-                await self.configureState()
-            }
-        }.store(in: &subscriptions)
-
-        coreDataPublisher?.filterByEntityName("OverrideStored").sink { [weak self] _ in
-            guard let self = self else { return }
-            Task {
-                await self.configureState()
-            }
-        }.store(in: &subscriptions)
-
-        // Observes Deletion of Glucose Objects
-        coreDataPublisher?.filterByEntityName("GlucoseStored").sink { [weak self] _ in
-            guard let self = self else { return }
-            Task {
-                await self.configureState()
-            }
-        }.store(in: &subscriptions)
-    }
-
-    private func fetchlastDetermination() async -> [NSManagedObjectID] {
-        let results = await CoreDataStack.shared.fetchEntitiesAsync(
-            ofType: OrefDetermination.self,
-            onContext: context,
-            predicate: NSPredicate.enactedDetermination,
-            key: "timestamp",
-            ascending: false,
-            fetchLimit: 1
-        )
-
-        return await context.perform {
-            guard let fetchedResults = results as? [OrefDetermination] else { return [] }
-
-            return fetchedResults.map(\.objectID)
-        }
-    }
-
-    private func fetchLatestOverride() async -> NSManagedObjectID? {
-        let results = await CoreDataStack.shared.fetchEntitiesAsync(
-            ofType: OverrideStored.self,
-            onContext: context,
-            predicate: NSPredicate.predicateForOneDayAgo,
-            key: "date",
-            ascending: false,
-            fetchLimit: 1,
-            propertiesToFetch: ["enabled", "percentage", "objectID"]
-        )
-
-        return await context.perform {
-            guard let fetchedResults = results as? [[String: Any]] else { return nil }
-
-            return fetchedResults.compactMap { $0["objectID"] as? NSManagedObjectID }.first
-        }
-    }
-
-    private func fetchGlucose() async -> [NSManagedObjectID] {
-        let results = await CoreDataStack.shared.fetchEntitiesAsync(
-            ofType: GlucoseStored.self,
-            onContext: context,
-            predicate: NSPredicate.predicateFor120MinAgo,
-            key: "date",
-            ascending: false,
-            fetchLimit: 24,
-            batchSize: 12
-        )
-
-        return await context.perform {
-            guard let glucoseResults = results as? [GlucoseStored] else {
-                return []
-            }
-
-            return glucoseResults.map(\.objectID)
-        }
-    }
-
-    @MainActor private func configureState() async {
-        let glucoseValuesIds = await fetchGlucose()
-        async let getLatestDeterminationIds = fetchlastDetermination()
-        async let getlatestOverrideId = fetchLatestOverride()
-
-        let latestOverrideId = await getlatestOverrideId
-
-        guard let lastDeterminationId = await getLatestDeterminationIds.first else {
-            debugPrint("\(DebuggingIdentifiers.failed) \(#file) \(#function) Failed to get last Determination")
-            return
-        }
-
-        do {
-            let glucoseValues: [GlucoseStored] = await CoreDataStack.shared
-                .getNSManagedObject(with: glucoseValuesIds, context: viewContext)
-            let lastDetermination = try viewContext.existingObject(with: lastDeterminationId) as? OrefDetermination
-            let recommendedInsulin = await newBolusCalc(
-                glucoseIds: glucoseValuesIds,
-                determinationId: lastDeterminationId
-            )
-
-            var latestOverride: OverrideStored?
-            if let id = latestOverrideId {
-                latestOverride = try viewContext.existingObject(with: id) as? OverrideStored
-            }
-
-            await MainActor.run { [weak self] in
-                guard let self = self else { return }
-
-                if let firstGlucoseValue = glucoseValues.first {
-                    let value = self.settingsManager.settings.units == .mgdL
-                        ? Decimal(firstGlucoseValue.glucose)
-                        : Decimal(firstGlucoseValue.glucose).asMmolL
-
-                    self.state.glucose = self.glucoseFormatter.string(from: value as NSNumber)
-                    self.state.trend = firstGlucoseValue.directionEnum?.symbol
-
-                    let delta = glucoseValues.count >= 2
-                        ? Decimal(firstGlucoseValue.glucose) - Decimal(glucoseValues.dropFirst().first?.glucose ?? 0)
-                        : 0
-                    let deltaConverted = self.settingsManager.settings.units == .mgdL ? delta : delta.asMmolL
-                    self.state.delta = self.deltaFormatter.string(from: deltaConverted as NSNumber)
-                    self.state.trendRaw = firstGlucoseValue.direction
-                    self.state.glucoseDate = firstGlucoseValue.date
-                }
-
-                self.state.lastLoopDate = lastDetermination?.timestamp
-                self.state.lastLoopDateInterval = self.state.lastLoopDate.map {
-                    guard $0.timeIntervalSince1970 > 0 else { return 0 }
-                    return UInt64($0.timeIntervalSince1970)
-                }
-                self.state.bolusIncrement = self.settingsManager.preferences.bolusIncrement
-                self.state.maxCOB = self.settingsManager.preferences.maxCOB
-                self.state.maxBolus = self.settingsManager.pumpSettings.maxBolus
-                self.state.carbsRequired = lastDetermination?.carbsRequired as? Decimal
-                self.state.bolusRecommended = self.apsManager
-                    .roundBolus(amount: max(recommendedInsulin, 0))
-                self.state.displayOnWatch = self.settingsManager.settings.displayOnWatch
-                self.state.displayFatAndProteinOnWatch = self.settingsManager.settings.displayFatAndProteinOnWatch
-                self.state.confirmBolusFaster = self.settingsManager.settings.confirmBolusFaster
-
-                self.state.iob = lastDetermination?.iob as? Decimal
-                if let cobValue = lastDetermination?.cob {
-                    self.state.cob = Decimal(cobValue)
-                } else {
-                    self.state.cob = 0
-                }
-                self.state.tempTargets = self.tempTargetsStorage.presets()
-                    .map { target -> TempTargetWatchPreset in
-                        let untilDate = self.tempTargetsStorage.current().flatMap { currentTarget -> Date? in
-                            guard currentTarget.id == target.id else { return nil }
-                            let date = currentTarget.createdAt.addingTimeInterval(TimeInterval(currentTarget.duration * 60))
-                            return date > Date() ? date : nil
-                        }
-                        return TempTargetWatchPreset(
-                            name: target.displayName,
-                            id: target.id,
-                            description: self.descriptionForTarget(target),
-                            until: untilDate
-                        )
-                    }
-                self.state.displayOnWatch = self.settingsManager.settings.displayOnWatch
-                self.state.displayFatAndProteinOnWatch = self.settingsManager.settings.displayFatAndProteinOnWatch
-                self.state.confirmBolusFaster = self.settingsManager.settings.confirmBolusFaster
-
-                if let eventualBG = self.settingsManager.settings.units == .mgdL ? lastDetermination?
-                    .eventualBG : lastDetermination?
-                    .eventualBG?.decimalValue.asMmolL as NSDecimalNumber?
-                {
-                    let eventualBGAsString = self.eventualFormatter.string(from: eventualBG)
-                    self.state.eventualBG = eventualBGAsString.map { "⇢ " + $0 }
-                    self.state.eventualBGRaw = eventualBGAsString
-                }
-
-                self.state.isf = lastDetermination?.insulinSensitivity as? Decimal
-
-                if let latestOverride = latestOverride {
-                    if latestOverride.enabled {
-                        let percentString = "\(latestOverride.percentage.formatted(.number)) %"
-                        self.state.override = percentString
-                    } else {
-                        self.state.override = "100 %"
-                    }
-                }
-
-                self.sendState()
-            }
-
-        } catch let error as NSError {
-            debugPrint("\(DebuggingIdentifiers.failed) \(#file) \(#function) Failed to configure state with error: \(error)")
-        }
-    }
-
-    private func sendState() {
-        guard let data = try? JSONEncoder().encode(state) else {
-            warning(.service, "Cannot encode watch state")
-            return
-        }
-
-        garmin.sendState(data)
-
-        guard session.isReachable else { return }
-        session.sendMessageData(data, replyHandler: nil) { error in
-            warning(.service, "Cannot send message to watch", error: error)
-        }
-    }
-
-    private func descriptionForTarget(_ target: TempTarget) -> String {
-        let units = settingsManager.settings.units
-
-        var low = target.targetBottom
-        var high = target.targetTop
-        if units == .mmolL {
-            low = low?.asMmolL
-            high = high?.asMmolL
-        }
-
-        let description =
-            "\(targetFormatter.string(from: (low ?? 0) as NSNumber)!) - \(targetFormatter.string(from: (high ?? 0) as NSNumber)!)" +
-            " for \(targetFormatter.string(from: target.duration as NSNumber)!) min"
-
-        return description
-    }
-
-    private func newBolusCalc(glucoseIds: [NSManagedObjectID], determinationId: NSManagedObjectID) async -> Decimal {
-        await context.perform {
-            let glucoseObjects = glucoseIds.compactMap { self.context.object(with: $0) as? GlucoseStored }
-            guard let determination = self.context.object(with: determinationId) as? OrefDetermination else {
-                print("Failed to fetch determination")
-                return 0
-            }
-
-            guard let firstGlucose = glucoseObjects.first else {
-                return 0 // If there's no glucose data, exit the block
-            }
-            let bg = firstGlucose.glucose // Make sure to provide a fallback value for glucose
-
-            // Calculations related to glucose data
-            var bgDelta: Int = 0
-            if glucoseObjects.count >= 3 {
-                bgDelta = Int(firstGlucose.glucose) - Int(glucoseObjects[2].glucose)
-            }
-
-            let conversion: Decimal = self.settingsManager.settings.units == .mmolL ? 0.0555 : 1
-            let isf = self.state.isf ?? 0
-            let target = determination.currentTarget as? Decimal ?? 100
-            let carbratio = determination.carbRatio as? Decimal ?? 10
-            let cob = self.state.cob ?? 0
-            let iob = self.state.iob ?? 0
-            let fattyMealFactor = self.settingsManager.settings.fattyMealFactor
-
-            // Complete bolus calculation logic
-            let targetDifference = Decimal(bg) - target
-            let targetDifferenceInsulin = targetDifference * conversion / isf
-            let fifteenMinInsulin = Decimal(bgDelta) * conversion / isf
-            let wholeCobInsulin = cob / carbratio
-            let iobInsulinReduction = -iob
-            let wholeCalc = targetDifferenceInsulin + iobInsulinReduction + wholeCobInsulin + fifteenMinInsulin
-
-            let result = wholeCalc * self.settingsManager.settings.overrideFactor
-            var insulinCalculated: Decimal
-            if self.settingsManager.settings.fattyMeals {
-                insulinCalculated = result * fattyMealFactor
-            } else {
-                insulinCalculated = result
-            }
-
-            // Ensure the calculated insulin amount does not exceed the maximum bolus and is not below zero
-            insulinCalculated = max(min(insulinCalculated, self.settingsManager.pumpSettings.maxBolus), 0)
-            return insulinCalculated // Return the calculated insulin outside of the performAndWait block
-        }
-    }
-}
-
-extension BaseWatchManager: WCSessionDelegate {
-    func sessionDidBecomeInactive(_: WCSession) {}
-
-    func sessionDidDeactivate(_: WCSession) {}
-
-    func session(_: WCSession, activationDidCompleteWith state: WCSessionActivationState, error _: Error?) {
-        debug(.service, "WCSession is activated: \(state == .activated)")
-    }
-
-    func session(_: WCSession, didReceiveMessage message: [String: Any]) {
-        debug(.service, "WCSession got message: \(message)")
-
-        if let stateRequest = message["stateRequest"] as? Bool, stateRequest {
-            processQueue.async {
-                self.sendState()
-            }
-        }
-    }
-
-    func session(_: WCSession, didReceiveMessage message: [String: Any], replyHandler: @escaping ([String: Any]) -> Void) {
-        debug(.service, "WCSession got message with reply handler: \(message)")
-
-        if let carbs = message["carbs"] as? Double,
-           let fat = message["fat"] as? Double,
-           let protein = message["protein"] as? Double,
-           carbs > 0 || fat > 0 || protein > 0
-        {
-            Task {
-                await carbsStorage.storeCarbs(
-                    [CarbsEntry(
-                        id: UUID().uuidString,
-                        createdAt: Date(),
-                        actualDate: nil,
-                        carbs: Decimal(carbs),
-                        fat: Decimal(fat),
-                        protein: Decimal(protein),
-                        note: message["note"] as? String,
-                        enteredBy: CarbsEntry.local,
-                        isFPU: false,
-                        fpuID: nil
-                    )],
-                    areFetchedFromRemote: false
-                )
-
-                _ = await apsManager.determineBasal()
-                replyHandler(["confirmation": true])
-            }
-            return
-        }
-
-        if let tempTargetID = message["tempTarget"] as? String {
-            Task {
-                if var preset = tempTargetsStorage.presets().first(where: { $0.id == tempTargetID }) {
-                    preset.createdAt = Date()
-                    await tempTargetsStorage.storeTempTarget(tempTarget: preset)
-                    replyHandler(["confirmation": true])
-                } else if tempTargetID == "cancel" {
-                    let entry = TempTarget(
-                        name: TempTarget.cancel,
-                        createdAt: Date(),
-                        targetTop: 0,
-                        targetBottom: 0,
-                        duration: 0,
-                        enteredBy: TempTarget.local,
-                        reason: TempTarget.cancel,
-                        isPreset: false,
-                        enabled: false,
-                        halfBasalTarget: 160
-                    )
-                    await tempTargetsStorage.storeTempTarget(tempTarget: entry)
-                    replyHandler(["confirmation": true])
-                } else {
-                    replyHandler(["confirmation": false])
-                }
-            }
-            return
-        }
-
-        if let bolus = message["bolus"] as? Double, bolus > 0 {
-            Task {
-                await apsManager.enactBolus(amount: bolus, isSMB: false)
-                replyHandler(["confirmation": true])
-            }
-            return
-        }
-
-        replyHandler(["confirmation": false])
-    }
-
-    func session(_: WCSession, didReceiveMessageData _: Data) {}
-
-    func sessionReachabilityDidChange(_ session: WCSession) {
-        if session.isReachable {
-            processQueue.async {
-                self.sendState()
-            }
-        }
-    }
-}
-
-extension BaseWatchManager:
-    SettingsObserver,
-    PumpHistoryObserver,
-    PumpSettingsObserver,
-    BasalProfileObserver,
-    TempTargetsObserver,
-    CarbsObserver,
-    PumpBatteryObserver,
-    PumpReservoirObserver
-{
-    func settingsDidChange(_: FreeAPSSettings) {
-        Task {
-            await configureState()
-        }
-    }
-
-    func pumpHistoryDidUpdate(_: [PumpHistoryEvent]) {
-        // TODO:
-    }
-
-    func pumpSettingsDidChange(_: PumpSettings) {
-        Task {
-            await configureState()
-        }
-    }
-
-    func basalProfileDidChange(_: [BasalProfileEntry]) {
-        // TODO:
-    }
-
-    func tempTargetsDidUpdate(_: [TempTarget]) {
-        Task {
-            await configureState()
-        }
-    }
-
-    func carbsDidUpdate(_: [CarbsEntry]) {
-        // TODO:
-    }
-
-    func pumpBatteryDidChange(_: Battery) {
-        // TODO:
-    }
-
-    func pumpReservoirDidChange(_: Decimal) {
-        // TODO:
-    }
-}

+ 0 - 106
FreeAPSWatch WatchKit Extension/ComplicationController.swift

@@ -1,106 +0,0 @@
-import ClockKit
-import SwiftUI
-
-class ComplicationController: NSObject, CLKComplicationDataSource {
-    // MARK: - Complication Configuration
-
-    func getComplicationDescriptors(handler: @escaping ([CLKComplicationDescriptor]) -> Void) {
-        let descriptors = [
-            CLKComplicationDescriptor(
-                identifier: "complication",
-                displayName: "Trio",
-                supportedFamilies: [
-                    .graphicCorner,
-                    .graphicCircular,
-                    .modularSmall,
-                    .utilitarianSmall,
-                    .circularSmall
-                ]
-            )
-        ]
-
-        // Call the handler with the currently supported complication descriptors
-        handler(descriptors)
-    }
-
-    func handleSharedComplicationDescriptors(_: [CLKComplicationDescriptor]) {
-        // Do any necessary work to support these newly shared complication descriptors
-    }
-
-    // MARK: - Timeline Configuration
-
-    func getTimelineEndDate(for _: CLKComplication, withHandler handler: @escaping (Date?) -> Void) {
-        // Call the handler with the last entry date you can currently provide or nil if you can't support future timelines
-        handler(nil)
-    }
-
-    func getPrivacyBehavior(for _: CLKComplication, withHandler handler: @escaping (CLKComplicationPrivacyBehavior) -> Void) {
-        // Call the handler with your desired behavior when the device is locked
-        handler(.showOnLockScreen)
-    }
-
-    // MARK: - Timeline Population
-
-    func getCurrentTimelineEntry(
-        for complication: CLKComplication,
-        withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void
-    ) {
-        switch complication.family {
-        case .graphicCorner:
-            guard let image = UIImage(named: "Complication/Graphic Corner") else {
-                handler(nil)
-                return
-            }
-            let template = CLKComplicationTemplateGraphicCornerTextImage(
-                textProvider: CLKTextProvider(format: "%@", "Trio"),
-                imageProvider: CLKFullColorImageProvider(fullColorImage: image)
-            )
-            let timelineEntry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template)
-            handler(timelineEntry)
-        case .modularSmall:
-            let template = CLKComplicationTemplateModularSmallRingText(
-                textProvider: CLKTextProvider(format: "%@", "Trio"),
-                fillFraction: 1,
-                ringStyle: .closed
-            )
-
-            let timelineEntry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template)
-            handler(timelineEntry)
-        case .utilitarianSmall:
-            guard let image = UIImage(named: "Complication/Utilitarian") else {
-                handler(nil)
-                return
-            }
-            let template = CLKComplicationTemplateUtilitarianSmallSquare(
-                imageProvider: CLKImageProvider(onePieceImage: image)
-            )
-            let timelineEntry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template)
-            handler(timelineEntry)
-        case .circularSmall:
-            let template =
-                CLKComplicationTemplateCircularSmallSimpleText(textProvider: CLKTextProvider(format: "%@", "Trio"))
-            let timelineEntry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template)
-            handler(timelineEntry)
-        default:
-            handler(nil)
-        }
-    }
-
-    func getTimelineEntries(
-        for _: CLKComplication,
-        after _: Date,
-        limit _: Int,
-        withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void
-    ) {
-        handler(nil)
-    }
-
-    // MARK: - Sample Templates
-
-    func getLocalizableSampleTemplate(
-        for _: CLKComplication,
-        withHandler handler: @escaping (CLKComplicationTemplate?) -> Void
-    ) {
-        handler(nil)
-    }
-}

+ 0 - 33
FreeAPSWatch WatchKit Extension/DataFlow.swift

@@ -1,33 +0,0 @@
-import Foundation
-
-struct WatchState: Codable {
-    var glucose: String?
-    var trend: String?
-    var trendRaw: String?
-    var delta: String?
-    var glucoseDate: Date?
-    var lastLoopDate: Date?
-    var lastLoopDateInterval: UInt64?
-    var bolusIncrement: Decimal?
-    var maxCOB: Decimal?
-    var maxBolus: Decimal?
-    var carbsRequired: Decimal?
-    var bolusRecommended: Decimal?
-    var iob: Decimal?
-    var cob: Decimal?
-    var tempTargets: [TempTargetWatchPreset] = []
-    var eventualBG: String?
-    var eventualBGRaw: String?
-    var displayOnWatch: AwConfig?
-    var displayFatAndProteinOnWatch: Bool?
-    var confirmBolusFaster: Bool?
-    var isf: Decimal?
-    var override: String?
-}
-
-struct TempTargetWatchPreset: Codable, Identifiable {
-    let name: String
-    let id: String
-    let description: String
-    let until: Date?
-}

+ 0 - 15
FreeAPSWatch WatchKit Extension/FreeAPSApp.swift

@@ -1,15 +0,0 @@
-import SwiftUI
-
-@main struct FreeAPSApp: App {
-    @StateObject var state = WatchStateModel()
-
-    @SceneBuilder var body: some Scene {
-        WindowGroup {
-            NavigationView {
-                MainView()
-            }.environmentObject(state)
-        }
-
-//        WKNotificationScene(controller: NotificationController.self, category: "FreeAPSCategory")
-    }
-}

+ 0 - 16
FreeAPSWatch WatchKit Extension/FreeAPSWatch WatchKit Extension.entitlements

@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>com.apple.developer.healthkit</key>
-	<true/>
-	<key>com.apple.developer.healthkit.access</key>
-	<array/>
-	<key>com.apple.developer.healthkit.background-delivery</key>
-	<true/>
-	<key>com.apple.security.application-groups</key>
-	<array>
-		<string>$(APP_GROUP_ID)</string>
-	</array>
-</dict>
-</plist>

+ 0 - 22
FreeAPSWatch WatchKit Extension/Info.plist

@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>NSHealthClinicalHealthRecordsShareUsageDescription</key>
-	<string>Bla bla Record Health</string>
-	<key>NSHealthShareUsageDescription</key>
-	<string>Bla bla Share Health</string>
-	<key>NSHealthUpdateUsageDescription</key>
-	<string>Bla bla Update Health</string>
-	<key>NSExtension</key>
-	<dict>
-		<key>NSExtensionAttributes</key>
-		<dict>
-			<key>WKAppBundleIdentifier</key>
-			<string>$(BUNDLE_IDENTIFIER).watchkitapp</string>
-		</dict>
-		<key>NSExtensionPointIdentifier</key>
-		<string>com.apple.watchkit</string>
-	</dict>
-</dict>
-</plist>

+ 0 - 25
FreeAPSWatch WatchKit Extension/NotificationController.swift

@@ -1,25 +0,0 @@
-import SwiftUI
-import UserNotifications
-import WatchKit
-
-class NotificationController: WKUserNotificationHostingController<NotificationView> {
-    override var body: NotificationView {
-        NotificationView()
-    }
-
-    override func willActivate() {
-        // This method is called when watch view controller is about to be visible to user
-        super.willActivate()
-    }
-
-    override func didDeactivate() {
-        // This method is called when watch view controller is no longer visible
-        super.didDeactivate()
-    }
-
-    override func didReceive(_: UNNotification) {
-        // This method is called when a notification needs to be presented.
-        // Implement it if you use a dynamic notification interface.
-        // Populate your dynamic notification interface as quickly as possible.
-    }
-}

+ 0 - 13
FreeAPSWatch WatchKit Extension/NotificationView.swift

@@ -1,13 +0,0 @@
-import SwiftUI
-
-struct NotificationView: View {
-    var body: some View {
-        Text("Hello, World!")
-    }
-}
-
-struct NotificationView_Previews: PreviewProvider {
-    static var previews: some View {
-        NotificationView()
-    }
-}

+ 0 - 20
FreeAPSWatch WatchKit Extension/PushNotificationPayload.apns

@@ -1,20 +0,0 @@
-{
-    "aps": {
-        "alert": {
-            "body": "Test message",
-            "title": "Optional title",
-            "subtitle": "Optional subtitle"
-        },
-        "category": "myCategory",
-        "thread-id": "5280"
-    },
-    
-    "WatchKit Simulator Actions": [
-        {
-            "title": "First Button",
-            "identifier": "firstButtonAction"
-        }
-    ],
-    
-    "customKey": "Use this file to define a testing payload for your notifications. The aps dictionary specifies the category, alert text and title. The WatchKit Simulator Actions array can provide info for one or more action buttons in addition to the standard Dismiss button. Any other top level keys are custom payload. If you have multiple such JSON files in your project, you'll be able to select them when choosing to debug the notification interface of your Watch App."
-}

+ 0 - 118
FreeAPSWatch WatchKit Extension/Views/BolusConfirmationView.swift

@@ -1,118 +0,0 @@
-import Combine
-import SwiftUI
-
-struct BolusConfirmationView: View {
-    @EnvironmentObject var state: WatchStateModel
-
-    @State var isCrownLeftOriented = WKInterfaceDevice.current().crownOrientation == .left
-    @State var crownProgress: CGFloat = 100.0
-    @State var progress: CGFloat = 0
-
-    private let elementSize: CGFloat = 30
-
-    @State var progressReturn: AnyCancellable?
-
-    @State var done = false
-
-    var body: some View {
-        VStack {
-            GeometryReader { geo in
-                HStack(alignment: .top) {
-                    Spacer().frame(width: elementSize / 2)
-                    ZStack(alignment: .top) {
-                        RoundedRectangle(cornerRadius: elementSize / 2, style: .circular)
-                            .fill(.secondary)
-                            .frame(width: elementSize, height: geo.size.height)
-                            .opacity(0.2)
-
-                        RoundedRectangle(cornerRadius: elementSize / 2, style: .circular)
-                            .fill(Color.insulin)
-                            .frame(width: elementSize, height: elementSize + (geo.size.height - elementSize) * progress / 100)
-                            .opacity(0.2)
-
-                        Image(systemName: done == true ? "checkmark.circle.fill" : "arrow.down.circle.fill")
-                            .resizable()
-                            .foregroundColor(done == true ? .loopGreen : .insulin)
-                            .frame(width: elementSize, height: elementSize)
-                            .offset(y: (geo.size.height - elementSize) * progress / 100)
-
-                    }.frame(maxWidth: .infinity, alignment: .center)
-                    if isCrownLeftOriented {
-                        Spacer().frame(width: elementSize / 2)
-                    } else {
-                        Image(systemName: "digitalcrown.arrow.counterclockwise.fill")
-                            .resizable()
-                            .frame(width: elementSize / 2, height: elementSize / 2)
-                            .foregroundColor(.primary)
-                            .transition(.opacity)
-                    }
-                }.frame(maxWidth: .infinity, maxHeight: .infinity)
-            }
-            .padding()
-            HStack(spacing: 16) {
-                if isCrownLeftOriented {
-                    Image(systemName: "digitalcrown.arrow.counterclockwise.fill")
-                        .resizable()
-                        .frame(width: elementSize / 2, height: elementSize / 2)
-                        .foregroundColor(.primary)
-                        .transition(.opacity)
-                }
-                Button {
-                    WKInterfaceDevice.current().play(.click)
-                    state.pendingBolus = nil
-                    state.isConfirmationBolusViewActive = false
-                }
-                label: {
-                    Text("Cancel")
-                }
-                if isCrownLeftOriented {
-                    Spacer().frame(width: elementSize / 2)
-                }
-            }
-        }
-        .focusable(true)
-        .digitalCrownRotation(
-            $crownProgress,
-            from: 0.0,
-            through: 100.0,
-            by: state.confirmBolusFaster ? 5 : 0.5,
-            sensitivity: .high,
-            isContinuous: false,
-            isHapticFeedbackEnabled: true
-        )
-        .onChange(of: crownProgress) { _ in
-            guard !done else { return }
-
-            progressReturn?.cancel()
-            progress = min(max(0, 100 - crownProgress), 100)
-            if progress >= 100 {
-                success()
-            } else {
-                progressReturn = Just(())
-                    .delay(for: 0.1, scheduler: RunLoop.main)
-                    .sink { _ in
-                        crownProgress = 100
-                        withAnimation {
-                            progress = 0
-                        }
-                    }
-            }
-        }
-    }
-
-    private func success() {
-        WKInterfaceDevice.current().play(.success)
-        withAnimation {
-            done = true
-        }
-        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
-            state.enactBolus()
-        }
-    }
-}
-
-struct BolusConfirmationView_Previews: PreviewProvider {
-    static var previews: some View {
-        BolusConfirmationView(progress: 50, done: false).environmentObject(WatchStateModel())
-    }
-}

+ 0 - 100
FreeAPSWatch WatchKit Extension/Views/BolusView.swift

@@ -1,100 +0,0 @@
-import SwiftUI
-
-struct BolusView: View {
-    @EnvironmentObject var state: WatchStateModel
-
-    @State var steps = 0.0
-
-    var numberFormatter: NumberFormatter {
-        let formatter = NumberFormatter()
-        formatter.numberStyle = .decimal
-        formatter.minimum = 0
-        formatter.maximum = Double((state.maxBolus ?? 5) / (state.bolusIncrement ?? 0.1)) as NSNumber
-        formatter.maximumFractionDigits = (state.bolusIncrement ?? 0.1) > 0.05 ? 1 : 2
-        formatter.minimumFractionDigits = (state.bolusIncrement ?? 0.1) > 0.05 ? 1 : 2
-        formatter.allowsFloats = true
-        formatter.roundingIncrement = Double(state.bolusIncrement ?? 0.1) as NSNumber
-        return formatter
-    }
-
-    var body: some View {
-        GeometryReader { geo in
-            VStack(spacing: 16) {
-                HStack {
-                    Button {
-                        WKInterfaceDevice.current().play(.click)
-                        let newValue = steps - 1
-                        steps = max(newValue, 0)
-                    } label: { Image(systemName: "minus") }
-                        .frame(width: geo.size.width / 4)
-                    Spacer()
-                    Text(numberFormatter.string(from: (steps * Double(state.bolusIncrement ?? 0.1)) as NSNumber)! + " U")
-                        .font(.headline)
-                        .focusable(true)
-                        .digitalCrownRotation(
-                            $steps,
-                            from: 0,
-                            through: Double((state.maxBolus ?? 5) / (state.bolusIncrement ?? 0.1)),
-                            by: 1,
-                            sensitivity: .medium,
-                            isContinuous: false,
-                            isHapticFeedbackEnabled: true
-                        )
-                    Spacer()
-                    Button {
-                        WKInterfaceDevice.current().play(.click)
-                        let newValue = steps + 1
-                        steps = min(newValue, Double((state.maxBolus ?? 5) / (state.bolusIncrement ?? 0.1)))
-                    } label: { Image(systemName: "plus") }
-                        .frame(width: geo.size.width / 4)
-                }
-
-                HStack {
-                    Button {
-                        WKInterfaceDevice.current().play(.click)
-                        state.isBolusViewActive = false
-                    }
-                    label: {
-                        Image(systemName: "xmark.circle.fill")
-                            .resizable()
-                            .foregroundColor(.loopRed)
-                            .frame(width: 30, height: 30)
-                    }
-                    Button {
-                        WKInterfaceDevice.current().play(.click)
-                        enactBolus()
-                    }
-                    label: {
-                        Image(systemName: "checkmark.circle.fill")
-                            .resizable()
-                            .foregroundColor(.loopGreen)
-                            .frame(width: 30, height: 30)
-                    }
-                    .disabled(steps <= 0)
-                }
-            }.frame(maxHeight: .infinity)
-        }
-        .navigationTitle("Enact Bolus")
-        .onAppear {
-            steps = Double((state.bolusRecommended ?? 0) / (state.bolusIncrement ?? 0.1))
-        }
-    }
-
-    private func enactBolus() {
-        let amount = steps * Double(state.bolusIncrement ?? 0.1)
-        state.addBolus(amount: amount)
-    }
-}
-
-struct BolusView_Previews: PreviewProvider {
-    static var previews: some View {
-        let state = WatchStateModel()
-        state.bolusRecommended = 10.3
-        state.bolusIncrement = 0.05
-        return Group {
-            BolusView()
-            BolusView().previewDevice("Apple Watch Series 5 - 40mm")
-            BolusView().previewDevice("Apple Watch Series 3 - 38mm")
-        }.environmentObject(state)
-    }
-}

+ 0 - 253
FreeAPSWatch WatchKit Extension/Views/CarbsView.swift

@@ -1,253 +0,0 @@
-import SwiftUI
-
-struct CarbsView: View {
-    @EnvironmentObject var state: WatchStateModel
-
-    // Selected nutrient
-    enum Selection: String {
-        case carbs
-        case protein
-        case fat
-    }
-
-    @State var selection: Selection = .carbs
-    @State var carbAmount = 0.0
-    @State var fatAmount = 0.0
-    @State var proteinAmount = 0.0
-    @State var colorOfselection: Color = .darkGray
-    // @State var displayPresets: Bool = false
-
-    var numberFormatter: NumberFormatter {
-        let formatter = NumberFormatter()
-        formatter.numberStyle = .decimal
-        formatter.minimum = 0
-        formatter.maximum = (state.maxCOB ?? 120) as NSNumber
-        formatter.maximumFractionDigits = 0
-        formatter.allowsFloats = false
-        return formatter
-    }
-
-    var body: some View {
-        VStack {
-            // nutrient
-            carbs
-            if state.displayFatAndProteinOnWatch {
-                Spacer()
-                fat
-                Spacer()
-                protein
-            }
-            buttonStack
-        }
-        .onAppear { carbAmount = Double(state.carbsRequired ?? 0) }
-    }
-
-    var nutrient: some View {
-        HStack {
-            switch selection {
-            case .protein:
-                Text("Protein")
-            case .fat:
-                Text("Fat")
-            default:
-                Text("Carbs")
-            }
-        }.font(.footnote).frame(maxWidth: .infinity, alignment: .center)
-    }
-
-    var carbs: some View {
-        HStack {
-            if selection == .carbs {
-                Button {
-                    WKInterfaceDevice.current().play(.click)
-                    let newValue = carbAmount - 5
-                    carbAmount = max(newValue, 0)
-                }
-                label: {
-                    HStack {
-                        Image(systemName: "minus")
-                        Text("") // Ugly fix to increase active tapping (button) area.
-                    }
-                }
-                .buttonStyle(.borderless).padding(.leading, 5)
-                .tint(selection == .carbs ? .blue : .none)
-            }
-            Spacer()
-            Text("🥨")
-            Spacer()
-            Text(numberFormatter.string(from: carbAmount as NSNumber)! + " g")
-                .font(selection == .carbs ? .title : .title3)
-                .focusable(selection == .carbs)
-                .digitalCrownRotation(
-                    $carbAmount,
-                    from: 0,
-                    through: Double(state.maxCOB ?? 120),
-                    by: 1,
-                    sensitivity: .medium,
-                    isContinuous: false,
-                    isHapticFeedbackEnabled: true
-                )
-            Spacer()
-            if selection == .carbs {
-                Button {
-                    WKInterfaceDevice.current().play(.click)
-                    let newValue = carbAmount + 5
-                    carbAmount = min(newValue, Double(state.maxCOB ?? 120))
-                } label: { Image(systemName: "plus") }
-                    .buttonStyle(.borderless).padding(.trailing, 5)
-                    .tint(selection == .carbs ? .blue : .none)
-            }
-        }
-        .minimumScaleFactor(0.7)
-        .onTapGesture {
-            select(entry: .carbs)
-        }
-        .background(selection == .carbs && state.displayFatAndProteinOnWatch ? colorOfselection : .black)
-        .padding(.top)
-    }
-
-    var protein: some View {
-        HStack {
-            if selection == .protein {
-                Button {
-                    WKInterfaceDevice.current().play(.click)
-                    let newValue = proteinAmount - 5
-                    proteinAmount = max(newValue, 0)
-                } label: {
-                    HStack {
-                        Image(systemName: "minus")
-                        Text("") // Ugly fix to increase active tapping (button) area.
-                    }
-                }
-                .buttonStyle(.borderless).padding(.leading, 5)
-                .tint(selection == .protein ? .blue : .none)
-            }
-            Spacer()
-            Text("🍗")
-            Spacer()
-            Text(numberFormatter.string(from: proteinAmount as NSNumber)! + " g")
-                .font(selection == .protein ? .title : .title3)
-                .foregroundStyle(.red)
-                .focusable(selection == .protein)
-                .digitalCrownRotation(
-                    $proteinAmount,
-                    from: 0,
-                    through: Double(240),
-                    by: 1,
-                    sensitivity: .medium,
-                    isContinuous: false,
-                    isHapticFeedbackEnabled: true
-                )
-            Spacer()
-            if selection == .protein {
-                Button {
-                    WKInterfaceDevice.current().play(.click)
-                    let newValue = proteinAmount + 5
-                    proteinAmount = min(newValue, Double(240))
-                } label: { Image(systemName: "plus") }.buttonStyle(.borderless).padding(.trailing, 5)
-                    .tint(selection == .protein ? .blue : .none)
-            }
-        }
-        .minimumScaleFactor(0.7)
-        .onTapGesture {
-            select(entry: .protein)
-        }
-        .background(selection == .protein ? colorOfselection : .black)
-    }
-
-    var fat: some View {
-        HStack {
-            if selection == .fat {
-                Button {
-                    WKInterfaceDevice.current().play(.click)
-                    let newValue = fatAmount - 5
-                    fatAmount = max(newValue, 0)
-                } label: {
-                    HStack {
-                        Image(systemName: "minus")
-                        Text("") // Ugly fix to increase active tapping (button) area.
-                    }
-                }
-                .buttonStyle(.borderless).padding(.leading, 5)
-                .tint(selection == .fat ? .blue : .none)
-            }
-            Spacer()
-            Text("🧀")
-            Spacer()
-            Text(numberFormatter.string(from: fatAmount as NSNumber)! + " g")
-                .font(selection == .fat ? .title : .title3)
-                .foregroundColor(.loopYellow)
-                .focusable(selection == .fat)
-                .digitalCrownRotation(
-                    $fatAmount,
-                    from: 0,
-                    through: Double(240),
-                    by: 1,
-                    sensitivity: .medium,
-                    isContinuous: false,
-                    isHapticFeedbackEnabled: true
-                )
-            Spacer()
-            if selection == .fat {
-                Button {
-                    WKInterfaceDevice.current().play(.click)
-                    let newValue = fatAmount + 5
-                    fatAmount = min(newValue, Double(240))
-                } label: { Image(systemName: "plus") }
-                    .buttonStyle(.borderless).padding(.trailing, 5)
-                    .tint(selection == .fat ? .blue : .none)
-            }
-        }
-        .minimumScaleFactor(0.7)
-        .onTapGesture {
-            select(entry: .fat)
-        }
-        .background(selection == .fat ? colorOfselection : .black)
-    }
-
-    var buttonStack: some View {
-        HStack(spacing: 25) {
-            /* To do: display the actual meal presets
-             Button {
-                 displayPresets.toggle()
-             }
-             label: { Image(systemName: "menucard.fill") }
-                 .buttonStyle(.borderless)
-             */
-            Button {
-                WKInterfaceDevice.current().play(.click)
-                // Get amount from displayed string
-                let amountCarbs = Int(numberFormatter.string(from: carbAmount as NSNumber)!) ?? Int(carbAmount.rounded())
-                let amountFat = Int(numberFormatter.string(from: fatAmount as NSNumber)!) ?? Int(fatAmount.rounded())
-                let amountProtein = Int(numberFormatter.string(from: proteinAmount as NSNumber)!) ??
-                    Int(proteinAmount.rounded())
-                let note = "Via Watch" // Hard-coded note for entries from watch
-                state.addMeal(amountCarbs, fat: amountFat, protein: amountProtein, note: note)
-            }
-            label: { Text("Save") }
-                .buttonStyle(.borderless)
-                .font(.callout)
-                .foregroundColor(carbAmount > 0 || fatAmount > 0 || proteinAmount > 0 ? .blue : .secondary)
-                .disabled(carbAmount <= 0 && fatAmount <= 0 && proteinAmount <= 0)
-        }
-        .frame(maxHeight: .infinity, alignment: .bottom)
-        .padding(.top)
-    }
-
-    private func select(entry: Selection) {
-        selection = entry
-    }
-}
-
-struct CarbsView_Previews: PreviewProvider {
-    static var previews: some View {
-        let state = WatchStateModel()
-        state.carbsRequired = 120
-        return Group {
-            CarbsView()
-            CarbsView().previewDevice("Apple Watch Series 5 - 40mm")
-            CarbsView().previewDevice("Apple Watch Series 3 - 38mm")
-        }
-        .environmentObject(state)
-    }
-}

+ 0 - 86
FreeAPSWatch WatchKit Extension/Views/ConfirmationView.swift

@@ -1,86 +0,0 @@
-import SwiftUI
-
-struct ConfirmationView: View {
-    @Binding var success: Bool?
-
-    var body: some View {
-        ZStack {
-            Group {
-                Image(systemName: "checkmark.circle.fill")
-                    .resizable()
-                    .foregroundColor(.loopGreen)
-                    .opacity(success == true ? 1.0 : 0.0)
-                    .scaleEffect(success == true ? 1.0 : 0.0)
-
-                Image(systemName: "xmark.circle.fill")
-                    .resizable()
-                    .foregroundColor(.loopRed)
-                    .opacity(success == false ? 1.0 : 0.0)
-                    .scaleEffect(success == false ? 1.0 : 0.0)
-
-                BlinkingView(count: 10, size: 10)
-                    .opacity(success == nil ? 1.0 : 0.0)
-                    .scaleEffect(success == nil ? 1.0 : 0.0)
-            }
-            .frame(width: 50, height: 50)
-        }
-        .frame(maxWidth: .infinity, maxHeight: .infinity)
-    }
-}
-
-struct ConfirmationView_Previews: PreviewProvider {
-    struct Container: View {
-        @State var success: Bool?
-
-        var body: some View {
-            ConfirmationView(success: $success)
-        }
-    }
-
-    static var previews: some View {
-        Container()
-    }
-}
-
-struct BlinkingView: View {
-    let count: UInt
-    let size: CGFloat
-
-    var body: some View {
-        GeometryReader { geometry in
-            ForEach(0 ..< Int(count)) { index in
-                item(forIndex: index, in: geometry.size)
-                    .frame(width: geometry.size.width, height: geometry.size.height)
-            }
-        }
-        .animation(.none, value: false)
-        .aspectRatio(contentMode: .fit)
-        .onAppear {
-            scale = 1
-            opacity = 1
-        }
-    }
-
-    @State var scale = 0.5
-    @State var opacity = 0.25
-
-    func animation(index: Int) -> Animation {
-        Animation
-            .default
-            .repeatCount(.max, autoreverses: true)
-            .delay(Double(index) / Double(count) / 2)
-    }
-
-    private func item(forIndex index: Int, in geometrySize: CGSize) -> some View {
-        let angle = 2 * CGFloat.pi / CGFloat(count) * CGFloat(index)
-        let x = (geometrySize.width / 2 - size / 2) * cos(angle)
-        let y = (geometrySize.height / 2 - size / 2) * sin(angle)
-        return Circle()
-            .frame(width: size, height: size)
-            .scaleEffect(scale)
-            .opacity(opacity)
-            .animation(animation(index: index), value: scale)
-            .animation(animation(index: index), value: opacity)
-            .offset(x: x, y: y)
-    }
-}

+ 0 - 444
FreeAPSWatch WatchKit Extension/Views/MainView.swift

@@ -1,444 +0,0 @@
-import HealthKit
-import SwiftDate
-import SwiftUI
-
-struct MainView: View {
-    private enum Config {
-        static let lag: TimeInterval = 30
-    }
-
-    @EnvironmentObject var state: WatchStateModel
-
-    @State var isCarbsActive = false
-    @State var isTargetsActive = false
-    @State var isBolusActive = false
-    @State private var pulse = 0
-    @State private var steps = 0
-
-    @GestureState var isDetectingLongPress = false
-    @State var completedLongPress = false
-
-    @State var completedLongPressOfBG = false
-    @GestureState var isDetectingLongPressOfBG = false
-
-    private var healthStore = HKHealthStore()
-    let heartRateQuantity = HKUnit(from: "count/min")
-
-    var body: some View {
-        ZStack(alignment: .topLeading) {
-            if !completedLongPressOfBG {
-                if state.timerDate.timeIntervalSince(state.lastUpdate) > 10 {
-                    HStack {
-                        withAnimation {
-                            BlinkingView(count: 5, size: 3)
-                                .frame(width: 14, height: 14)
-                                .padding(2)
-                        }
-                        Text("Updating...").font(.caption2).foregroundColor(.secondary)
-                    }
-                }
-            }
-            VStack {
-                if !completedLongPressOfBG {
-                    header
-                    Spacer()
-                    buttons
-                } else {
-                    bigHeader
-                }
-            }
-
-            if state.isConfirmationViewActive {
-                ConfirmationView(success: $state.confirmationSuccess)
-                    .background(Rectangle().fill(.black))
-            }
-
-            if state.isConfirmationBolusViewActive {
-                BolusConfirmationView()
-                    .environmentObject(state)
-                    .background(Rectangle().fill(.black))
-            }
-        }
-        .frame(maxHeight: .infinity)
-        .padding()
-        .onReceive(state.timer) { date in
-            state.timerDate = date
-            state.requestState()
-        }
-        .onAppear {
-            state.requestState()
-        }
-    }
-
-    var header: some View {
-        VStack {
-            HStack(alignment: .top) {
-                VStack(alignment: .leading) {
-                    HStack {
-                        Text(state.glucose).font(.title)
-                        Text(state.trend)
-                            .scaledToFill()
-                            .minimumScaleFactor(0.5)
-                    }
-                    /* IF YOU WANT TO DISPLAY MINUTES AGO, UNCOMMENT the gray code below
-                     let minutesAgo: TimeInterval = -1 * (state.glucoseDate ?? .distantPast).timeIntervalSinceNow / 60
-                     let minuteString = minutesAgo.formatted(.number.grouping(.never).rounded().precision(.fractionLength(0)))
-                     */
-                    HStack {
-                        /* if minutesAgo > 0 {
-                             Text(minuteString)
-                             Text("min")
-                         } */
-                        Text(state.delta)
-                    }
-                    .font(.caption2).foregroundColor(.gray)
-                }
-                Spacer()
-
-                VStack(spacing: 0) {
-                    HStack {
-                        Circle().stroke(color, lineWidth: 5).frame(width: 26, height: 26).padding(10)
-                    }
-
-                    if state.lastLoopDate != nil {
-                        Text(timeString).font(.caption2).foregroundColor(.gray)
-                    } else {
-                        Text("--").font(.caption2).foregroundColor(.gray)
-                    }
-                }
-            }
-            Spacer()
-            HStack(alignment: .firstTextBaseline) {
-                Text(iobFormatter.string(from: (state.cob ?? 0) as NSNumber)!)
-                    .font(.caption2)
-                    .scaledToFill()
-                    .foregroundColor(Color.white)
-                    .minimumScaleFactor(0.5)
-                Text("g").foregroundColor(.loopYellow)
-                    .font(.caption2)
-                    .scaledToFill()
-                    .minimumScaleFactor(0.5)
-                Spacer()
-                Text(iobFormatter.string(from: (state.iob ?? 0) as NSNumber)!)
-                    .font(.caption2)
-                    .scaledToFill()
-                    .foregroundColor(Color.white)
-                    .minimumScaleFactor(0.5)
-
-                Text("U").foregroundColor(.insulin)
-                    .font(.caption2)
-                    .scaledToFill()
-                    .minimumScaleFactor(0.5)
-
-                switch state.displayOnWatch {
-                case .HR:
-                    Spacer()
-                    HStack {
-                        if completedLongPress {
-                            HStack {
-                                Text("❤️" + " \(pulse)")
-                                    .fontWeight(.regular)
-                                    .font(.custom("activated", size: 20))
-                                    .scaledToFill()
-                                    .foregroundColor(.white)
-                                    .minimumScaleFactor(0.5)
-                            }
-                            .scaleEffect(isDetectingLongPress ? 3 : 1)
-                            .gesture(longPress)
-
-                        } else {
-                            HStack {
-                                Text("❤️" + " \(pulse)")
-                                    .fontWeight(.regular)
-                                    .font(.caption2)
-                                    .scaledToFill()
-                                    .foregroundColor(.white)
-                                    .minimumScaleFactor(0.5)
-                            }
-                            .scaleEffect(isDetectingLongPress ? 3 : 1)
-                            .gesture(longPress)
-                        }
-                    }
-                case .BGTarget:
-                    if let eventualBG = state.eventualBG.nonEmpty {
-                        Spacer()
-                        HStack {
-                            Text(eventualBG)
-                                .font(.caption2)
-                                .scaledToFill()
-                                .foregroundColor(.secondary)
-                                .minimumScaleFactor(0.5)
-                        }
-                    }
-                case .steps:
-                    Spacer()
-                    HStack {
-                        Text("🦶" + " \(steps)")
-                            .fontWeight(.regular)
-                            .font(.caption2)
-                            .scaledToFill()
-                            .foregroundColor(.white)
-                            .minimumScaleFactor(0.5)
-                    }
-                case .isf:
-                    Spacer()
-                    let isf: String = state.isf != nil ? "\(state.isf ?? 0)" : "-"
-                    HStack {
-                        Image(systemName: "arrow.up.arrow.down")
-                            .renderingMode(.template)
-                            .resizable()
-                            .frame(width: 12, height: 12)
-                            .foregroundColor(.loopGreen)
-                        Text("\(isf)")
-                            .fontWeight(.regular)
-                            .font(.caption2)
-                            .scaledToFill()
-                            .foregroundColor(.white)
-                            .minimumScaleFactor(0.5)
-                    }
-                case .override:
-                    Spacer()
-                    let override: String = state.override != nil ? state.override! : "-"
-                    HStack {
-                        Text("👤 \(override)")
-                            .fontWeight(.regular)
-                            .font(.caption2)
-                            .scaledToFill()
-                            .foregroundColor(.white)
-                            .minimumScaleFactor(0.5)
-                    }
-                }
-            }
-            Spacer()
-                .onAppear(perform: start)
-        }
-        .padding()
-        // .scaleEffect(isDetectingLongPressOfBG ? 3 : 1)
-        .gesture(longPresBGs)
-    }
-
-    var bigHeader: some View {
-        VStack(alignment: .center) {
-            HStack {
-                Text(state.glucose).font(.custom("Big BG", size: 55))
-                Text(state.trend != "→" ? state.trend : "")
-                    .scaledToFill()
-                    .minimumScaleFactor(0.5)
-            }.padding(.bottom, 35)
-
-            HStack {
-                Circle().stroke(color, lineWidth: 5).frame(width: 20, height: 20).padding(10)
-            }
-        }
-        .gesture(longPresBGs)
-    }
-
-    var longPress: some Gesture {
-        LongPressGesture(minimumDuration: 1)
-            .updating($isDetectingLongPress) { currentState, gestureState,
-                _ in
-                gestureState = currentState
-            }
-            .onEnded { _ in
-                if completedLongPress {
-                    completedLongPress = false
-                } else { completedLongPress = true }
-            }
-    }
-
-    var longPresBGs: some Gesture {
-        LongPressGesture(minimumDuration: 1)
-            .updating($isDetectingLongPressOfBG) { currentState, gestureState,
-                _ in
-                gestureState = currentState
-            }
-            .onEnded { _ in
-                if completedLongPressOfBG {
-                    completedLongPressOfBG = false
-                } else { completedLongPressOfBG = true }
-            }
-    }
-
-    var buttons: some View {
-        HStack(alignment: .center) {
-            NavigationLink(isActive: $state.isCarbsViewActive) {
-                CarbsView()
-                    .environmentObject(state)
-            } label: {
-                Image("carbs", bundle: nil)
-                    .renderingMode(.template)
-                    .resizable()
-                    .frame(width: 24, height: 24)
-                    .foregroundColor(.loopYellow)
-            }
-
-            NavigationLink(isActive: $state.isTempTargetViewActive) {
-                TempTargetsView()
-                    .environmentObject(state)
-            } label: {
-                VStack {
-                    Image("target", bundle: nil)
-                        .renderingMode(.template)
-                        .resizable()
-                        .frame(width: 24, height: 24)
-                        .foregroundColor(.loopGreen)
-                    if let until = state.tempTargets.compactMap(\.until).first, until > Date() {
-                        Text(until, style: .timer)
-                            .scaledToFill()
-                            .font(.system(size: 8))
-                    }
-                }
-            }
-
-            NavigationLink(isActive: $state.isBolusViewActive) {
-                BolusView()
-                    .environmentObject(state)
-            } label: {
-                Image("bolus", bundle: nil)
-                    .renderingMode(.template)
-                    .resizable()
-                    .frame(width: 24, height: 24)
-                    .foregroundColor(.insulin)
-            }
-        }
-    }
-
-    func start() {
-        autorizeHealthKit()
-        startHeartRateQuery(quantityTypeIdentifier: .heartRate)
-        startStepsQuery(quantityTypeIdentifier: .stepCount)
-    }
-
-    func autorizeHealthKit() {
-        let healthKitTypes: Set = [
-            HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!,
-            HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate)!
-        ]
-        healthStore.requestAuthorization(toShare: healthKitTypes, read: healthKitTypes) { _, _ in }
-    }
-
-    private func startStepsQuery(quantityTypeIdentifier _: HKQuantityTypeIdentifier) {
-        let type = HKQuantityType.quantityType(forIdentifier: .stepCount)!
-        let now = Date()
-        let startOfDay = Calendar.current.startOfDay(for: now)
-        var interval = DateComponents()
-        interval.day = 1
-        let query = HKStatisticsCollectionQuery(
-            quantityType: type,
-            quantitySamplePredicate: nil,
-            options: [.cumulativeSum],
-            anchorDate: startOfDay,
-            intervalComponents: interval
-        )
-
-        query.initialResultsHandler = { _, result, _ in
-            var resultCount = 0.0
-            guard let result = result else {
-                self.steps = 0
-                return
-            }
-            result.enumerateStatistics(from: startOfDay, to: now) { statistics, _ in
-
-                if let sum = statistics.sumQuantity() {
-                    // Get steps (they are of double type)
-                    resultCount = sum.doubleValue(for: HKUnit.count())
-                } // end if
-                // Return
-                self.steps = Int(resultCount)
-            }
-        }
-
-        query.statisticsUpdateHandler = {
-            _, statistics, _, _ in
-
-            // If new statistics are available
-            if let sum = statistics?.sumQuantity() {
-                let resultCount = sum.doubleValue(for: HKUnit.count())
-                // Return
-                self.steps = Int(resultCount)
-            } // end if
-        }
-        healthStore.execute(query)
-    }
-
-    private func startHeartRateQuery(quantityTypeIdentifier: HKQuantityTypeIdentifier) {
-        let devicePredicate = HKQuery.predicateForObjects(from: [HKDevice.local()])
-        let updateHandler: (HKAnchoredObjectQuery, [HKSample]?, [HKDeletedObject]?, HKQueryAnchor?, Error?) -> Void = {
-            _, samples, _, _, _ in
-            guard let samples = samples as? [HKQuantitySample] else {
-                return
-            }
-            self.process(samples, type: quantityTypeIdentifier)
-        }
-        let query = HKAnchoredObjectQuery(
-            type: HKObjectType.quantityType(forIdentifier: quantityTypeIdentifier)!,
-            predicate: devicePredicate,
-            anchor: nil,
-            limit: HKObjectQueryNoLimit,
-            resultsHandler: updateHandler
-        )
-        query.updateHandler = updateHandler
-        healthStore.execute(query)
-    }
-
-    private func process(_ samples: [HKQuantitySample], type: HKQuantityTypeIdentifier) {
-        var lastHeartRate = 0.0
-        for sample in samples {
-            if type == .heartRate {
-                lastHeartRate = sample.quantity.doubleValue(for: heartRateQuantity)
-            }
-            pulse = Int(lastHeartRate)
-        }
-    }
-
-    private var iobFormatter: NumberFormatter {
-        let formatter = NumberFormatter()
-        formatter.maximumFractionDigits = 2
-        formatter.numberStyle = .decimal
-        return formatter
-    }
-
-    private var timeString: String {
-        let minAgo = Int((Date().timeIntervalSince(state.lastLoopDate ?? .distantPast) - Config.lag) / 60) + 1
-        if minAgo > 1440 {
-            return "--"
-        }
-        return "\(minAgo) " + NSLocalizedString("min", comment: "Minutes ago since last loop")
-    }
-
-    private var color: Color {
-        guard let lastLoopDate = state.lastLoopDate else {
-            return .loopGray
-        }
-        let delta = Date().timeIntervalSince(lastLoopDate) - Config.lag
-
-        if delta <= 5.minutes.timeInterval {
-            return .loopGreen
-        } else if delta <= 10.minutes.timeInterval {
-            return .loopYellow
-        } else {
-            return .loopRed
-        }
-    }
-}
-
-struct ContentView_Previews: PreviewProvider {
-    static var previews: some View {
-        let state = WatchStateModel()
-
-        state.glucose = "15,8"
-        state.delta = "+888"
-        state.iob = 100.38
-        state.cob = 112.123
-        state.lastLoopDate = Date().addingTimeInterval(-200)
-        state
-            .tempTargets =
-            [TempTargetWatchPreset(name: "Test", id: "test", description: "", until: Date().addingTimeInterval(3600 * 3))]
-
-        return Group {
-            MainView()
-            MainView().previewDevice("Apple Watch Series 5 - 40mm")
-            MainView().previewDevice("Apple Watch Series 3 - 38mm")
-        }.environmentObject(state)
-    }
-}

+ 0 - 56
FreeAPSWatch WatchKit Extension/Views/TempTargetsView.swift

@@ -1,56 +0,0 @@
-import SwiftUI
-
-struct TempTargetsView: View {
-    @EnvironmentObject var state: WatchStateModel
-
-    var body: some View {
-        List {
-            if state.tempTargets.isEmpty {
-                Text("Set temp targets presets on iPhone first").padding()
-            } else {
-                ForEach(state.tempTargets) { target in
-                    Button {
-                        WKInterfaceDevice.current().play(.click)
-                        state.enactTempTarget(id: target.id)
-                    } label: {
-                        VStack(alignment: .leading) {
-                            HStack {
-                                Text(target.name)
-                                if let until = target.until, until > Date() {
-                                    Spacer()
-                                    Text(until, style: .timer).foregroundColor(.loopGreen)
-                                }
-                            }
-                            Text(target.description).font(.caption2).foregroundColor(.secondary)
-                        }
-                    }
-                }
-            }
-
-            Button {
-                WKInterfaceDevice.current().play(.click)
-                state.enactTempTarget(id: "cancel")
-            } label: {
-                Text("Cancel Temp Target")
-            }
-        }
-        .navigationTitle("Temp Targets")
-    }
-}
-
-struct TempTargetsView_Previews: PreviewProvider {
-    static var previews: some View {
-        let model = WatchStateModel()
-        model.tempTargets = [
-            TempTargetWatchPreset(
-                name: "Target 0",
-                id: UUID().uuidString,
-                description: "blablabla",
-                until: Date().addingTimeInterval(60 * 60)
-            ),
-            TempTargetWatchPreset(name: "target1", id: UUID().uuidString, description: "blablabla", until: nil),
-            TempTargetWatchPreset(name: "🤖 Target 2", id: UUID().uuidString, description: "blablabla", until: nil)
-        ]
-        return TempTargetsView().environmentObject(model)
-    }
-}

+ 0 - 201
FreeAPSWatch WatchKit Extension/WatchStateModel.swift

@@ -1,201 +0,0 @@
-import Combine
-import Foundation
-import SwiftUI
-import WatchConnectivity
-
-enum AwConfig: String, CaseIterable, Identifiable, Codable {
-    var id: String { rawValue }
-    case HR
-    case BGTarget
-    case steps
-    case isf
-    case override
-}
-
-class WatchStateModel: NSObject, ObservableObject {
-    var session: WCSession
-
-    @Published var glucose = "00"
-    @Published var trend = "→"
-    @Published var delta = "+00"
-    @Published var lastLoopDate: Date?
-    @Published var glucoseDate: Date?
-    @Published var bolusIncrement: Decimal?
-    @Published var maxCOB: Decimal?
-    @Published var maxBolus: Decimal?
-    @Published var bolusRecommended: Decimal?
-    @Published var carbsRequired: Decimal?
-    @Published var iob: Decimal?
-    @Published var cob: Decimal?
-    @Published var tempTargets: [TempTargetWatchPreset] = []
-    @Published var isCarbsViewActive = false
-    @Published var isTempTargetViewActive = false
-    @Published var isBolusViewActive = false
-    @Published var displayOnWatch: AwConfig = .BGTarget
-    @Published var displayFatAndProteinOnWatch = false
-    @Published var confirmBolusFaster = false
-    @Published var eventualBG = ""
-    @Published var isConfirmationViewActive = false {
-        didSet {
-            confirmationTimeout = nil
-            if isConfirmationViewActive {
-                confirmationTimeout = Just(())
-                    .delay(for: 30, scheduler: DispatchQueue.main)
-                    .sink {
-                        WKInterfaceDevice.current().play(.retry)
-                        self.isConfirmationViewActive = false
-                    }
-            }
-        }
-    }
-
-    @Published var isConfirmationBolusViewActive = false
-    @Published var confirmationSuccess: Bool?
-    @Published var lastUpdate: Date = .distantPast
-    @Published var timerDate = Date()
-    @Published var pendingBolus: Double?
-    @Published var isf: Decimal?
-    @Published var override: String?
-
-    private var lifetime = Set<AnyCancellable>()
-    private var confirmationTimeout: AnyCancellable?
-    let timer = Timer.publish(every: 10, on: .main, in: .common).autoconnect()
-
-    init(session: WCSession = .default) {
-        self.session = session
-        super.init()
-
-        session.delegate = self
-        session.activate()
-    }
-
-    func addMeal(_ carbs: Int, fat: Int, protein: Int, note: String) {
-        confirmationSuccess = nil
-        isConfirmationViewActive = true
-        isCarbsViewActive = false
-        session.sendMessage(["carbs": carbs, "fat": fat, "protein": protein, "note": note], replyHandler: { reply in
-            self.completionHandler(reply)
-            if let ok = reply["confirmation"] as? Bool, ok {
-                DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
-                    self.isBolusViewActive = true
-                }
-            }
-        }) { error in
-            print(error.localizedDescription)
-            DispatchQueue.main.async {
-                self.confirmation(false)
-            }
-        }
-    }
-
-    func enactTempTarget(id: String) {
-        confirmationSuccess = nil
-        isConfirmationViewActive = true
-        isTempTargetViewActive = false
-        session.sendMessage(["tempTarget": id], replyHandler: completionHandler) { error in
-            print(error.localizedDescription)
-            DispatchQueue.main.async {
-                self.confirmation(false)
-            }
-        }
-    }
-
-    func addBolus(amount: Double) {
-        isBolusViewActive = false
-        pendingBolus = amount
-        isConfirmationBolusViewActive = true
-    }
-
-    func enactBolus() {
-        isConfirmationBolusViewActive = false
-        guard let amount = pendingBolus else { return }
-
-        confirmationSuccess = nil
-        isConfirmationViewActive = true
-        session.sendMessage(["bolus": amount], replyHandler: completionHandler) { error in
-            print(error.localizedDescription)
-            DispatchQueue.main.async {
-                self.confirmation(false)
-            }
-        }
-    }
-
-    func requestState() {
-        guard session.activationState == .activated else {
-            session.activate()
-            return
-        }
-        session.sendMessage(["stateRequest": true], replyHandler: nil) { error in
-            print("WatchStateModel error: " + error.localizedDescription)
-        }
-    }
-
-    private func completionHandler(_ reply: [String: Any]) {
-        if let ok = reply["confirmation"] as? Bool {
-            DispatchQueue.main.async {
-                self.confirmation(ok)
-            }
-        } else {
-            DispatchQueue.main.async {
-                self.confirmation(false)
-            }
-        }
-    }
-
-    private func confirmation(_ ok: Bool) {
-        WKInterfaceDevice.current().play(ok ? .success : .failure)
-        withAnimation {
-            confirmationSuccess = ok
-        }
-
-        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
-            withAnimation {
-                self.isConfirmationViewActive = false
-            }
-        }
-    }
-
-    private func processState(_ state: WatchState) {
-        glucose = state.glucose ?? "?"
-        trend = state.trend ?? "?"
-        delta = state.delta ?? "?"
-        glucoseDate = state.glucoseDate
-        lastLoopDate = state.lastLoopDate
-        bolusIncrement = state.bolusIncrement
-        maxCOB = state.maxCOB
-        maxBolus = state.maxBolus
-        bolusRecommended = state.bolusRecommended
-        carbsRequired = state.carbsRequired
-        iob = state.iob
-        cob = state.cob
-        tempTargets = state.tempTargets
-        lastUpdate = Date()
-        eventualBG = state.eventualBG ?? ""
-        displayOnWatch = state.displayOnWatch ?? .BGTarget
-        displayFatAndProteinOnWatch = state.displayFatAndProteinOnWatch ?? false
-        confirmBolusFaster = state.confirmBolusFaster ?? false
-        isf = state.isf
-        override = state.override
-    }
-}
-
-extension WatchStateModel: WCSessionDelegate {
-    func session(_: WCSession, activationDidCompleteWith state: WCSessionActivationState, error _: Error?) {
-        print("WCSession activated: \(state == .activated)")
-        requestState()
-    }
-
-    func session(_: WCSession, didReceiveMessage _: [String: Any]) {}
-
-    func sessionReachabilityDidChange(_ session: WCSession) {
-        print("WCSession Reachability: \(session.isReachable)")
-    }
-
-    func session(_: WCSession, didReceiveMessageData messageData: Data) {
-        if let state = try? JSONDecoder().decode(WatchState.self, from: messageData) {
-            DispatchQueue.main.async {
-                self.processState(state)
-            }
-        }
-    }
-}

+ 0 - 10
FreeAPSWatch/FreeAPSWatch.entitlements

@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>com.apple.security.application-groups</key>
-	<array>
-		<string>$(APP_GROUP_ID)</string>
-	</array>
-</dict>
-</plist>

+ 0 - 5
FreeAPSWatch/Info.plist

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