Jelajahi Sumber

Move CGM logic to HomeStateModel+CGM

Sam King 1 tahun lalu
induk
melakukan
0dedd6b415

+ 4 - 0
Trio.xcodeproj/project.pbxproj

@@ -204,6 +204,7 @@
 		38FEF413273B317A00574A46 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38FEF412273B317A00574A46 /* HKUnit.swift */; };
 		3B2F77862D7E52ED005ED9FA /* TDD.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B2F77852D7E52ED005ED9FA /* TDD.swift */; };
 		3B2F77882D7E5387005ED9FA /* CurrentTDDSetup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B2F77872D7E5387005ED9FA /* CurrentTDDSetup.swift */; };
+		3B4196E02D8C4BC00091DFF7 /* HomStateModel+CGM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B4196DF2D8C4BBB0091DFF7 /* HomStateModel+CGM.swift */; };
 		3BAD36B22D7CDC1A00CC298D /* MainLoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BAD36B12D7CDC1400CC298D /* MainLoadingView.swift */; };
 		3BAD36CC2D7D420E00CC298D /* CoreDataInitializationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BAD36CB2D7D420500CC298D /* CoreDataInitializationCoordinator.swift */; };
 		45252C95D220E796FDB3B022 /* ConfigEditorDataFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F8A87AA037BD079BA3528BA /* ConfigEditorDataFlow.swift */; };
@@ -925,6 +926,7 @@
 		38FEF412273B317A00574A46 /* HKUnit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = "<group>"; };
 		3B2F77852D7E52ED005ED9FA /* TDD.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TDD.swift; sourceTree = "<group>"; };
 		3B2F77872D7E5387005ED9FA /* CurrentTDDSetup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentTDDSetup.swift; sourceTree = "<group>"; };
+		3B4196DF2D8C4BBB0091DFF7 /* HomStateModel+CGM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomStateModel+CGM.swift"; sourceTree = "<group>"; };
 		3BAD36B12D7CDC1400CC298D /* MainLoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainLoadingView.swift; sourceTree = "<group>"; };
 		3BAD36CB2D7D420500CC298D /* CoreDataInitializationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataInitializationCoordinator.swift; sourceTree = "<group>"; };
 		3BDEA2DC60EDE0A3CA54DC73 /* TargetsEditorProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TargetsEditorProvider.swift; sourceTree = "<group>"; };
@@ -1755,6 +1757,7 @@
 				3811DE2A25C9D49500A708ED /* HomeDataFlow.swift */,
 				3811DE2925C9D49500A708ED /* HomeProvider.swift */,
 				3811DE2825C9D49500A708ED /* HomeStateModel.swift */,
+				3B4196DF2D8C4BBB0091DFF7 /* HomStateModel+CGM.swift */,
 				58645B972CA2D16A008AFCE7 /* HomeStateModel+Setup */,
 				3811DE2C25C9D49500A708ED /* View */,
 			);
@@ -3880,6 +3883,7 @@
 				CE7950242997D81700FA576E /* CGMSettingsView.swift in Sources */,
 				58237D9E2BCF0A6B00A47A79 /* PopupView.swift in Sources */,
 				BD793CB02CE7C61500D669AC /* OverrideRunStored+helper.swift in Sources */,
+				3B4196E02D8C4BC00091DFF7 /* HomStateModel+CGM.swift in Sources */,
 				38D0B3D925EC07C400CB6E88 /* CarbsEntry.swift in Sources */,
 				DD32CF9C2CC82499003686D6 /* TrioRemoteControl+TempTarget.swift in Sources */,
 				BD249D882D42FC0000412DEB /* BolusStatsView.swift in Sources */,

+ 1 - 1
Trio/Sources/Modules/CGMSettings/CGMSettingsStateModel.swift

@@ -5,7 +5,7 @@ import LoopKitUI
 import SwiftUI
 
 /// For a full description of the events that can happen for the CGM lifecycle, see comment at the top
-/// of HomeStateModel since these are the same events
+/// of HomeStateModel+CGM since these are the same events
 
 struct CGMModel: Identifiable, Hashable {
     var id: String

+ 77 - 0
Trio/Sources/Modules/Home/HomStateModel+CGM.swift

@@ -0,0 +1,77 @@
+import LoopKitUI
+
+/// Notes on the CGM lifecycle:
+/// There are two classes of CGM devices: plugins and non-plugins. Plugins are implemented using
+/// LoopKit APIs and include most hardware CGMs like Dexcom G6, G7, Libre, and so on. Non-plugins
+/// drivers are implemented directly in Trio, and include the CGM Simulator and Nightscout CGM. For
+/// these different CGMs, there are a few different events, handled in different places, that happen to
+/// signify a change in the CGM lifecycle.
+///
+/// Both:
+/// - addCGM function invocation: Called by the UI in response to a user clicking the "add CGM" button
+///
+/// Non-plugins only:
+/// - deleteCGM function invocation: Called by the CGM View in response to a user clicking the "delete CGM" button
+///
+/// Plugins only:
+/// - completionNotifyingDidComplete: Called by the CGM driver to signify that Trio should close its UIViewController
+/// - cgmManagerOnboarding didCreateCGMManager: Called by the CGM driver after adding a new CGM
+/// - cgmManagerWantsDeletion: Called by the CGM driver when the user asks to delete a CGM
+/// There are no ordering constraints between completionNotifyingDidComplete and the other two
+/// Plugin events (it's up to the implementation of each individual driver). For example, the G7 driver invokes
+/// cgmManagerWantsDeletion on the delegate's queue while calling completionNotifyingDidComplete in parallel
+/// on the main queue.
+///
+/// In additinon to having different events for different types of CGMs, the handling of these events is spread out
+/// across various state managers, like HomeStateModel, CGMSettingsStateModel, and PluginSource.
+///
+/// There is CGM state in the HomeStateModel and CGMSettingsStateModel, FetchGlucoseManager, and
+/// SettingsManger
+///
+/// The flow for adding a CGM:
+/// - Non-plugin: addCGM (considered onboarded at this point)
+/// - Plugin: addCGM -> cgmManagerOnboarding (after success)
+///
+/// For deleting a CGM:
+/// - Non-plugin: deleteCGM (in HomeStateModel and CGMSettingsStateModel)
+/// - Plugin: cgmManagerWantsDeletion (in PluginSource)
+/// Then, both non-plugin and plugin:  set settings.cgm (in FetchGlucoseManager) ->
+///     settingsDidChange (in HomeStateModel and CGMSettingsStateModel)
+
+extension Home.StateModel: CompletionDelegate {
+    func completionNotifyingDidComplete(_ notifying: CompletionNotifying) {
+        debug(.service, "Completion fired by: \(type(of: notifying))")
+        Task {
+            // this sleep is because this event and cgmManagerWantsDeletion
+            // are called in parallel.
+            try await Task.sleep(for: .seconds(0.2))
+            await MainActor.run {
+                if fetchGlucoseManager.cgmGlucoseSourceType == .none {
+                    cgmCurrent = cgmDefaultModel
+                }
+            }
+        }
+        shouldDisplayCGMSetupSheet = false
+    }
+}
+
+extension Home.StateModel: CGMManagerOnboardingDelegate {
+    func cgmManagerOnboarding(didCreateCGMManager manager: LoopKitUI.CGMManagerUI) {
+        settingsManager.settings.cgm = cgmCurrent.type
+        settingsManager.settings.cgmPluginIdentifier = cgmCurrent.id
+        fetchGlucoseManager.updateGlucoseSource(
+            cgmGlucoseSourceType: cgmCurrent.type,
+            cgmGlucosePluginId: cgmCurrent.id,
+            newManager: manager
+        )
+        DispatchQueue.main.async {
+            self.broadcaster.notify(GlucoseObserver.self, on: .main) {
+                $0.glucoseDidUpdate([])
+            }
+        }
+    }
+
+    func cgmManagerOnboarding(didOnboardCGMManager _: LoopKitUI.CGMManagerUI) {
+        // nothing to do
+    }
+}

+ 0 - 76
Trio/Sources/Modules/Home/HomeStateModel.swift

@@ -7,44 +7,6 @@ import Observation
 import SwiftDate
 import SwiftUI
 
-/// Notes on the CGM lifecycle:
-/// There are two classes of CGM devices: plugins and non-plugins. Plugins are implemented using
-/// LoopKit APIs and include most hardware CGMs like Dexcom G6, G7, Libre, and so on. Non-plugins
-/// drivers are implemented directly in Trio, and include the CGM Simulator and Nightscout CGM. For
-/// these different CGMs, there are a few different events, handled in different places, that happen to
-/// signify a change in the CGM lifecycle.
-///
-/// Both:
-/// - addCGM function invocation: Called by the UI in response to a user clicking the "add CGM" button
-///
-/// Non-plugins only:
-/// - deleteCGM function invocation: Called by the CGM View in response to a user clicking the "delete CGM" button
-///
-/// Plugins only:
-/// - completionNotifyingDidComplete: Called by the CGM driver to signify that Trio should close its UIViewController
-/// - cgmManagerOnboarding didCreateCGMManager: Called by the CGM driver after adding a new CGM
-/// - cgmManagerWantsDeletion: Called by the CGM driver when the user asks to delete a CGM
-/// There are no ordering constraints between completionNotifyingDidComplete and the other two
-/// Plugin events (it's up to the implementation of each individual driver). For example, the G7 driver invokes
-/// cgmManagerWantsDeletion on the delegate's queue while calling completionNotifyingDidComplete in parallel
-/// on the main queue.
-///
-/// In additinon to having different events for different types of CGMs, the handling of these events is spread out
-/// across various state managers, like HomeStateModel, CGMSettingsStateModel, and PluginSource.
-///
-/// There is CGM state in the HomeStateModel and CGMSettingsStateModel, FetchGlucoseManager, and
-/// SettingsManger
-///
-/// The flow for adding a CGM:
-/// - Non-plugin: addCGM (considered onboarded at this point)
-/// - Plugin: addCGM -> cgmManagerOnboarding (after success)
-///
-/// For deleting a CGM:
-/// - Non-plugin: deleteCGM (in HomeStateModel and CGMSettingsStateModel)
-/// - Plugin: cgmManagerWantsDeletion (in PluginSource)
-/// Then, both non-plugin and plugin:  set settings.cgm (in FetchGlucoseManager) ->
-///     settingsDidChange (in HomeStateModel and CGMSettingsStateModel)
-
 extension Home {
     @Observable final class StateModel: BaseStateModel<Provider> {
         @ObservationIgnored @Injected() var broadcaster: Broadcaster!
@@ -742,23 +704,6 @@ extension Home.StateModel:
     }
 }
 
-extension Home.StateModel: CompletionDelegate {
-    func completionNotifyingDidComplete(_ notifying: CompletionNotifying) {
-        debug(.service, "Completion fired by: \(type(of: notifying))")
-        Task {
-            // this sleep is because this event and cgmManagerWantsDeletion
-            // are called in parallel.
-            try await Task.sleep(for: .seconds(0.2))
-            await MainActor.run {
-                if fetchGlucoseManager.cgmGlucoseSourceType == .none {
-                    cgmCurrent = cgmDefaultModel
-                }
-            }
-        }
-        shouldDisplayCGMSetupSheet = false
-    }
-}
-
 extension Home.StateModel: PumpManagerOnboardingDelegate {
     func pumpManagerOnboarding(didCreatePumpManager pumpManager: PumpManagerUI) {
         provider.apsManager.pumpManager = pumpManager
@@ -775,24 +720,3 @@ extension Home.StateModel: PumpManagerOnboardingDelegate {
         // nothing to do
     }
 }
-
-extension Home.StateModel: CGMManagerOnboardingDelegate {
-    func cgmManagerOnboarding(didCreateCGMManager manager: LoopKitUI.CGMManagerUI) {
-        settingsManager.settings.cgm = cgmCurrent.type
-        settingsManager.settings.cgmPluginIdentifier = cgmCurrent.id
-        fetchGlucoseManager.updateGlucoseSource(
-            cgmGlucoseSourceType: cgmCurrent.type,
-            cgmGlucosePluginId: cgmCurrent.id,
-            newManager: manager
-        )
-        DispatchQueue.main.async {
-            self.broadcaster.notify(GlucoseObserver.self, on: .main) {
-                $0.glucoseDidUpdate([])
-            }
-        }
-    }
-
-    func cgmManagerOnboarding(didOnboardCGMManager _: LoopKitUI.CGMManagerUI) {
-        // nothing to do
-    }
-}