From 36a2a533364eaa59416278ccd5b5e63c06aa6f90 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sun, 2 Sep 2018 16:11:37 -0500 Subject: [PATCH 01/56] Omnikit --- Cartfile | 13 +++++----- Loop/Managers/PumpManagerState.swift | 38 ++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 Loop/Managers/PumpManagerState.swift diff --git a/Cartfile b/Cartfile index d4ce49bda8..5977f1854c 100644 --- a/Cartfile +++ b/Cartfile @@ -1,8 +1,7 @@ - -github "LoopKit/LoopKit" "dev" -github "LoopKit/CGMBLEKit" "dev" -github "i-schuetz/SwiftCharts" == 0.6.1 -github "LoopKit/dexcom-share-client-swift" "carthage-recursive" -github "LoopKit/G4ShareSpy" "fix-cartfile" -github "ps2/rileylink_ios" "dev" +github "LoopKit/LoopKit" == "omnikit" +github "LoopKit/CGMBLEKit" == 2.1.1 +github "i-schuetz/SwiftCharts" == 0.6.2 +github "mddub/dexcom-share-client-swift" == 0.4.1 +github "mddub/G4ShareSpy" == 0.3.3 +github "ps2/rileylink_ios" == "omnikit" github "LoopKit/Amplitude-iOS" "decreepify" diff --git a/Loop/Managers/PumpManagerState.swift b/Loop/Managers/PumpManagerState.swift new file mode 100644 index 0000000000..20342edb09 --- /dev/null +++ b/Loop/Managers/PumpManagerState.swift @@ -0,0 +1,38 @@ +// +// PumpManagerState.swift +// Loop +// +// Copyright © 2018 LoopKit Authors. All rights reserved. +// + +import Foundation +import LoopKit +import MinimedKit +import OmniKit + + +let allPumpManagers: [String: PumpManager.Type] = [ + OmnipodPumpManager.managerIdentifier: OmnipodPumpManager.self + //MinimedPumpManager.managerIdentifier: MinimedPumpManager.self +] + + +func PumpManagerFromRawValue(_ rawValue: [String: Any]) -> PumpManager? { + guard let managerIdentifier = rawValue["managerIdentifier"] as? String, + let rawState = rawValue["state"] as? PumpManager.RawStateValue, + let Manager = allPumpManagers[managerIdentifier] + else { + return nil + } + + return Manager.init(rawState: rawState) +} + +extension PumpManager { + var rawValue: [String: Any] { + return [ + "managerIdentifier": type(of: self).managerIdentifier, + "state": self.rawState + ] + } +} From 5746df17f1d72446a84cb66614a838f04d320034 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 10 Sep 2018 19:23:54 -0500 Subject: [PATCH 02/56] Add OmniKit frameworks --- Loop.xcodeproj/project.pbxproj | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj index 7f6427c05b..c1d58c96cd 100644 --- a/Loop.xcodeproj/project.pbxproj +++ b/Loop.xcodeproj/project.pbxproj @@ -276,6 +276,8 @@ C18C8C511D5A351900E043FB /* NightscoutDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C18C8C501D5A351900E043FB /* NightscoutDataManager.swift */; }; C1C6591C1E1B1FDA0025CC58 /* recommend_temp_basal_dropping_then_rising.json in Resources */ = {isa = PBXBuildFile; fileRef = C1C6591B1E1B1FDA0025CC58 /* recommend_temp_basal_dropping_then_rising.json */; }; C1C73F0D1DE3D0270022FC89 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = C1C73F0F1DE3D0270022FC89 /* InfoPlist.strings */; }; + C1CB13A9213EE35800F9EEDA /* OmniKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1CB13A8213EE35800F9EEDA /* OmniKit.framework */; }; + C1CB13AB213EE35800F9EEDA /* OmniKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1CB13AA213EE35800F9EEDA /* OmniKitUI.framework */; }; C9886AE51E5B2FAD00473BB8 /* gallery.ckcomplication in Resources */ = {isa = PBXBuildFile; fileRef = C9886AE41E5B2FAD00473BB8 /* gallery.ckcomplication */; }; /* End PBXBuildFile section */ @@ -787,6 +789,8 @@ C18852E12082AB1A00BECC8C /* RileyLinkKitUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RileyLinkKitUI.framework; path = Carthage/Build/iOS/RileyLinkKitUI.framework; sourceTree = ""; }; C18C8C501D5A351900E043FB /* NightscoutDataManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NightscoutDataManager.swift; sourceTree = ""; }; C1C6591B1E1B1FDA0025CC58 /* recommend_temp_basal_dropping_then_rising.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = recommend_temp_basal_dropping_then_rising.json; sourceTree = ""; }; + C1CB13A8213EE35800F9EEDA /* OmniKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = OmniKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C1CB13AA213EE35800F9EEDA /* OmniKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = OmniKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C9886AE41E5B2FAD00473BB8 /* gallery.ckcomplication */ = {isa = PBXFileReference; lastKnownFileType = folder; path = gallery.ckcomplication; sourceTree = ""; }; /* End PBXFileReference section */ @@ -802,6 +806,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + C1CB13A9213EE35800F9EEDA /* OmniKit.framework in Frameworks */, + C1CB13AB213EE35800F9EEDA /* OmniKitUI.framework in Frameworks */, 4F7528941DFE1E9500C322D6 /* LoopUI.framework in Frameworks */, 434FB6461D68F1CD007B9C70 /* Amplitude.framework in Frameworks */, 43A8EC6F210E622700A81379 /* CGMBLEKitUI.framework in Frameworks */, @@ -1298,6 +1304,9 @@ isa = PBXGroup; children = ( 434FB6451D68F1CD007B9C70 /* Amplitude.framework */, + C1CB13A8213EE35800F9EEDA /* OmniKit.framework */, + C1CB13AA213EE35800F9EEDA /* OmniKitUI.framework */, + 43709AE920DF3F8200F941B3 /* MinimedKitUI.framework */, 4344628420A7A3BE00C4BE6F /* CGMBLEKit.framework */, 438A95A71D8B9B24009D12E1 /* CGMBLEKit.framework */, 43A8EC6E210E622600A81379 /* CGMBLEKitUI.framework */, @@ -1734,15 +1743,15 @@ "$(SRCROOT)/Carthage/Build/iOS/RileyLinkKitUI.framework", "$(SRCROOT)/Carthage/Build/iOS/LoopKitUI.framework", "$(SRCROOT)/Carthage/Build/iOS/MinimedKitUI.framework", - "$(SRCROOT)/Carthage/Build/iOS/CGMBLEKitUI.framework", - "$(SRCROOT)/Carthage/Build/iOS/ShareClientUI.framework", + "$(SRCROOT)/Carthage/Build/iOS/OmniKit.framework", + "$(SRCROOT)/Carthage/Build/iOS/OmniKitUI.framework", ); name = "Copy Frameworks with Carthage"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "carthage_frameworks_dir=${SRCROOT}/Carthage/Build/iOS\nif [ -f $PROJECT_DIR/.gitmodules && [ $ACTION != \"install\" ]; then\nfor varname in ${!SCRIPT_INPUT_FILE_*}\ndo\nexport ${varname}=${!varname/$carthage_frameworks_dir/$BUILT_PRODUCTS_DIR}\ndone\nfi\n/usr/local/bin/carthage copy-frameworks"; + shellScript = "carthage_frameworks_dir=${SRCROOT}/Carthage/Build/iOS\nif [ -f $PROJECT_DIR/.gitmodules ] && [ $ACTION != \"install\" ]; then\nfor varname in ${!SCRIPT_INPUT_FILE_*}\ndo\necho using $BUILT_PRODUCTS_DIR for ${varname}\nexport ${varname}=${!varname/$carthage_frameworks_dir/$BUILT_PRODUCTS_DIR}\ndone\nfi\n/usr/local/bin/carthage copy-frameworks"; }; 43FF3DF620A8EFE800F8E62C /* Copy Frameworks with Carthage */ = { isa = PBXShellScriptBuildPhase; From 6988bb87b88e8419ffe71d4e8a2e1043bac293b3 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Wed, 12 Sep 2018 18:57:40 -0500 Subject: [PATCH 03/56] fix cartfile --- Cartfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cartfile b/Cartfile index 5977f1854c..0ca10b4117 100644 --- a/Cartfile +++ b/Cartfile @@ -1,7 +1,7 @@ -github "LoopKit/LoopKit" == "omnikit" +github "LoopKit/LoopKit" "dev" github "LoopKit/CGMBLEKit" == 2.1.1 github "i-schuetz/SwiftCharts" == 0.6.2 github "mddub/dexcom-share-client-swift" == 0.4.1 github "mddub/G4ShareSpy" == 0.3.3 -github "ps2/rileylink_ios" == "omnikit" +github "ps2/rileylink_ios" "omnikit" github "LoopKit/Amplitude-iOS" "decreepify" From 1b2317760b330c599012a39876d73121e811ab6e Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 15 Sep 2018 10:38:47 -0500 Subject: [PATCH 04/56] Track lastAddedPumpData, including lastAddedPumpEvents --- Cartfile | 2 +- Cartfile.resolved | 2 +- Loop/Managers/DeviceDataManager.swift | 3 ++- Loop/Managers/LoopDataManager.swift | 13 ++++++++----- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Cartfile b/Cartfile index 0ca10b4117..74a298c847 100644 --- a/Cartfile +++ b/Cartfile @@ -1,4 +1,4 @@ -github "LoopKit/LoopKit" "dev" +github "LoopKit/LoopKit" == 2.1.2 github "LoopKit/CGMBLEKit" == 2.1.1 github "i-schuetz/SwiftCharts" == 0.6.2 github "mddub/dexcom-share-client-swift" == 0.4.1 diff --git a/Cartfile.resolved b/Cartfile.resolved index 6b6657b49e..4e211b699c 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -4,4 +4,4 @@ github "LoopKit/G4ShareSpy" "47931f1ee70f1081db6eebf3a68bb8f4146e5fca" github "LoopKit/LoopKit" "8c553f7bd03c2032b146e4a52d58d527a4285c15" github "LoopKit/dexcom-share-client-swift" "f0125aed8960586a9473dca02d17b3e5969558ac" github "i-schuetz/SwiftCharts" "0.6.1" -github "ps2/rileylink_ios" "9f62a563cc7e6ea17a3f3be3a3f351aba202d624" +github "ps2/rileylink_ios" "22aa9a15ce939f43a6a76c4fb9f25c4c335848c1" diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index 95c3c28647..e0550c1b1f 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -268,7 +268,7 @@ extension DeviceDataManager: PumpManagerDelegate { } } } - + func pumpManagerRecommendsLoop(_ pumpManager: PumpManager) { loopManager.loop() } @@ -280,6 +280,7 @@ extension DeviceDataManager: PumpManagerDelegate { func startDateToFilterNewReservoirEvents(for manager: PumpManager) -> Date { return loopManager.doseStore.lastReservoirValue?.startDate ?? .distantPast } + } diff --git a/Loop/Managers/LoopDataManager.swift b/Loop/Managers/LoopDataManager.swift index 350415712e..5a48ffa966 100644 --- a/Loop/Managers/LoopDataManager.swift +++ b/Loop/Managers/LoopDataManager.swift @@ -866,11 +866,8 @@ extension LoopDataManager { throw LoopError.missingDataError(.glucose) } - guard let pumpStatusDate = doseStore.lastReservoirValue?.startDate else { - self.predictedGlucose = nil - throw LoopError.missingDataError(.reservoir) - } - + let pumpStatusDate = doseStore.lastAddedPumpData + let startDate = Date() guard startDate.timeIntervalSince(glucose.startDate) <= settings.recencyInterval else { @@ -1192,3 +1189,9 @@ protocol LoopDataManagerDelegate: class { /// - result: The enacted basal func loopDataManager(_ manager: LoopDataManager, didRecommendBasalChange basal: (recommendation: TempBasalRecommendation, date: Date), completion: @escaping (_ result: Result) -> Void) -> Void } + +extension DoseStore { + var lastAddedPumpData: Date { + return max(lastReservoirValue?.startDate ?? .distantPast, lastAddedPumpEvents) + } +} From 6b4544ccdcb98bbc0059f5eff85d6c5fbca4e5b7 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Wed, 19 Sep 2018 10:26:30 -0500 Subject: [PATCH 05/56] Fix carthage copy frameworks script --- Cartfile | 4 ++-- Loop.xcodeproj/project.pbxproj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cartfile b/Cartfile index 74a298c847..59851380e5 100644 --- a/Cartfile +++ b/Cartfile @@ -1,7 +1,7 @@ -github "LoopKit/LoopKit" == 2.1.2 +github "LoopKit/LoopKit" == 2.1.3 github "LoopKit/CGMBLEKit" == 2.1.1 github "i-schuetz/SwiftCharts" == 0.6.2 github "mddub/dexcom-share-client-swift" == 0.4.1 github "mddub/G4ShareSpy" == 0.3.3 -github "ps2/rileylink_ios" "omnikit" +github "ps2/rileylink_ios" "dev" github "LoopKit/Amplitude-iOS" "decreepify" diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj index c1d58c96cd..d8d339374a 100644 --- a/Loop.xcodeproj/project.pbxproj +++ b/Loop.xcodeproj/project.pbxproj @@ -1751,7 +1751,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "carthage_frameworks_dir=${SRCROOT}/Carthage/Build/iOS\nif [ -f $PROJECT_DIR/.gitmodules ] && [ $ACTION != \"install\" ]; then\nfor varname in ${!SCRIPT_INPUT_FILE_*}\ndo\necho using $BUILT_PRODUCTS_DIR for ${varname}\nexport ${varname}=${!varname/$carthage_frameworks_dir/$BUILT_PRODUCTS_DIR}\ndone\nfi\n/usr/local/bin/carthage copy-frameworks"; + shellScript = "carthage_frameworks_dir=${SRCROOT}/Carthage/Build/iOS\nif [ -f $PROJECT_DIR/.gitmodules ] && [ $ACTION != \"install\" ]; then\nfor varname in ${!SCRIPT_INPUT_FILE_*}\ndo\necho using $BUILT_PRODUCTS_DIR for ${varname}\nexport ${varname}=${!varname/$carthage_frameworks_dir/$BUILT_PRODUCTS_DIR}\ndone\nfi\n/usr/local/bin/carthage copy-frameworks\n"; }; 43FF3DF620A8EFE800F8E62C /* Copy Frameworks with Carthage */ = { isa = PBXShellScriptBuildPhase; @@ -1771,7 +1771,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "carthage_frameworks_dir=${SRCROOT}/Carthage/Build/iOS\nif [ -f $PROJECT_DIR/.gitmodules && [ $ACTION != \"install\" ]; then\nfor varname in ${!SCRIPT_INPUT_FILE_*}\ndo\nexport ${varname}=${!varname/$carthage_frameworks_dir/$BUILT_PRODUCTS_DIR}\ndone\nfi\n/usr/local/bin/carthage copy-frameworks"; + shellScript = "carthage_frameworks_dir=${SRCROOT}/Carthage/Build/iOS\nif [ -f $PROJECT_DIR/.gitmodules ] && [ $ACTION != \"install\" ]; then\nfor varname in ${!SCRIPT_INPUT_FILE_*}\ndo\nexport ${varname}=${!varname/$carthage_frameworks_dir/$BUILT_PRODUCTS_DIR}\ndone\nfi\n/usr/local/bin/carthage copy-frameworks\n"; }; /* End PBXShellScriptBuildPhase section */ From 5e9f41a5cce051851327a3ac9a14c908c1f7ba57 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Thu, 20 Sep 2018 12:31:08 -0500 Subject: [PATCH 06/56] rebase --- Cartfile | 8 ++++---- Cartfile.resolved | 10 +++++----- Loop.xcodeproj/project.pbxproj | 5 ++++- Loop/Managers/PumpManager.swift | 4 +++- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/Cartfile b/Cartfile index 59851380e5..28a0f2740e 100644 --- a/Cartfile +++ b/Cartfile @@ -1,7 +1,7 @@ -github "LoopKit/LoopKit" == 2.1.3 -github "LoopKit/CGMBLEKit" == 2.1.1 +github "LoopKit/LoopKit" "dev" +github "LoopKit/CGMBLEKit" "dev" github "i-schuetz/SwiftCharts" == 0.6.2 -github "mddub/dexcom-share-client-swift" == 0.4.1 -github "mddub/G4ShareSpy" == 0.3.3 +github "LoopKit/dexcom-share-client-swift" "carthage-recursive" +github "LoopKit/G4ShareSpy" "fix-cartfile" github "ps2/rileylink_ios" "dev" github "LoopKit/Amplitude-iOS" "decreepify" diff --git a/Cartfile.resolved b/Cartfile.resolved index 4e211b699c..7fda8569a7 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,7 +1,7 @@ github "LoopKit/Amplitude-iOS" "2137d5fd44bf630ed33e1e72d7af6d8f8612f270" -github "LoopKit/CGMBLEKit" "97433c2c546b50268bbfe2e1a42cb377c6066e78" -github "LoopKit/G4ShareSpy" "47931f1ee70f1081db6eebf3a68bb8f4146e5fca" +github "LoopKit/CGMBLEKit" "cf66c46b1a6b0fcd1a833a62b8333155e14cb4ea" +github "LoopKit/G4ShareSpy" "d3fbcb5cd8528eef71dce59314624d661f610c6a" github "LoopKit/LoopKit" "8c553f7bd03c2032b146e4a52d58d527a4285c15" -github "LoopKit/dexcom-share-client-swift" "f0125aed8960586a9473dca02d17b3e5969558ac" -github "i-schuetz/SwiftCharts" "0.6.1" -github "ps2/rileylink_ios" "22aa9a15ce939f43a6a76c4fb9f25c4c335848c1" +github "LoopKit/dexcom-share-client-swift" "0d3a8886bd9b55da2054c9114f46c402c712915f" +github "i-schuetz/SwiftCharts" "0.6.2" +github "ps2/rileylink_ios" "49a43189c1606875d27133589c6d6b92fbd3a0a1" diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj index d8d339374a..ef7108f0fc 100644 --- a/Loop.xcodeproj/project.pbxproj +++ b/Loop.xcodeproj/project.pbxproj @@ -788,6 +788,7 @@ C17824A41E1AD4D100D9D25C /* BolusRecommendation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BolusRecommendation.swift; sourceTree = ""; }; C18852E12082AB1A00BECC8C /* RileyLinkKitUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RileyLinkKitUI.framework; path = Carthage/Build/iOS/RileyLinkKitUI.framework; sourceTree = ""; }; C18C8C501D5A351900E043FB /* NightscoutDataManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NightscoutDataManager.swift; sourceTree = ""; }; + C1C108C22152F46D00EA5165 /* CGMBLEKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CGMBLEKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C1C6591B1E1B1FDA0025CC58 /* recommend_temp_basal_dropping_then_rising.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = recommend_temp_basal_dropping_then_rising.json; sourceTree = ""; }; C1CB13A8213EE35800F9EEDA /* OmniKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = OmniKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C1CB13AA213EE35800F9EEDA /* OmniKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = OmniKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1303,10 +1304,10 @@ 968DCD53F724DE56FFE51920 /* Frameworks */ = { isa = PBXGroup; children = ( + C1C108C22152F46D00EA5165 /* CGMBLEKitUI.framework */, 434FB6451D68F1CD007B9C70 /* Amplitude.framework */, C1CB13A8213EE35800F9EEDA /* OmniKit.framework */, C1CB13AA213EE35800F9EEDA /* OmniKitUI.framework */, - 43709AE920DF3F8200F941B3 /* MinimedKitUI.framework */, 4344628420A7A3BE00C4BE6F /* CGMBLEKit.framework */, 438A95A71D8B9B24009D12E1 /* CGMBLEKit.framework */, 43A8EC6E210E622600A81379 /* CGMBLEKitUI.framework */, @@ -1745,6 +1746,8 @@ "$(SRCROOT)/Carthage/Build/iOS/MinimedKitUI.framework", "$(SRCROOT)/Carthage/Build/iOS/OmniKit.framework", "$(SRCROOT)/Carthage/Build/iOS/OmniKitUI.framework", + "$(SRCROOT)/Carthage/Build/iOS/CGMBLEKitUI.framework", + "$(SRCROOT)/Carthage/Build/iOS/ShareClientUI.framework", ); name = "Copy Frameworks with Carthage"; outputPaths = ( diff --git a/Loop/Managers/PumpManager.swift b/Loop/Managers/PumpManager.swift index 60e172b4a6..235a94f147 100644 --- a/Loop/Managers/PumpManager.swift +++ b/Loop/Managers/PumpManager.swift @@ -8,10 +8,12 @@ import Foundation import LoopKit import MinimedKit +import OmniKit let allPumpManagers: [PumpManager.Type] = [ - MinimedPumpManager.self + OmnipodPumpManager.self, + //MinimedPumpManager.self ] private let managersByIdentifier: [String: PumpManager.Type] = allPumpManagers.reduce(into: [:]) { (map, Type) in From 096b3474bbbbbd980c9159b244c93896b20025e3 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 25 Sep 2018 16:35:19 -0500 Subject: [PATCH 07/56] update deps --- Cartfile.resolved | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cartfile.resolved b/Cartfile.resolved index 7fda8569a7..59e713fb71 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,7 +1,7 @@ github "LoopKit/Amplitude-iOS" "2137d5fd44bf630ed33e1e72d7af6d8f8612f270" -github "LoopKit/CGMBLEKit" "cf66c46b1a6b0fcd1a833a62b8333155e14cb4ea" -github "LoopKit/G4ShareSpy" "d3fbcb5cd8528eef71dce59314624d661f610c6a" -github "LoopKit/LoopKit" "8c553f7bd03c2032b146e4a52d58d527a4285c15" -github "LoopKit/dexcom-share-client-swift" "0d3a8886bd9b55da2054c9114f46c402c712915f" +github "LoopKit/CGMBLEKit" "894492e64d405188e09573f9f74adce8995369fa" +github "LoopKit/G4ShareSpy" "7479d0a269a1984eb6716a14293ceb148d6e9165" +github "LoopKit/LoopKit" "f130260f76d5e58a5984045484331a363e1b7080" +github "LoopKit/dexcom-share-client-swift" "7af726cb6c24a25abc9c056294578cff6cd9c245" github "i-schuetz/SwiftCharts" "0.6.2" -github "ps2/rileylink_ios" "49a43189c1606875d27133589c6d6b92fbd3a0a1" +github "ps2/rileylink_ios" "72590877d063ef6fc2a5a564210ea679fa9bebf6" From 65e3c9e8302654616e8c592af3030afa8357dc86 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Wed, 26 Sep 2018 13:21:18 -0500 Subject: [PATCH 08/56] Initialize setupViewController with existing pump settings --- Loop/View Controllers/SettingsTableViewController.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Loop/View Controllers/SettingsTableViewController.swift b/Loop/View Controllers/SettingsTableViewController.swift index 48b76fca8d..7864783800 100644 --- a/Loop/View Controllers/SettingsTableViewController.swift +++ b/Loop/View Controllers/SettingsTableViewController.swift @@ -330,6 +330,9 @@ final class SettingsTableViewController: UITableViewController { if let PumpManagerType = pumpManagers.first { var setupViewController = PumpManagerType.setupViewController() setupViewController.setupDelegate = self + setupViewController.basalSchedule = dataManager.loopManager.basalRateSchedule + setupViewController.maxBolusUnits = dataManager.loopManager.settings.maximumBolus + setupViewController.maxBasalRateUnitsPerHour = dataManager.loopManager.settings.maximumBasalRatePerHour present(setupViewController, animated: true, completion: nil) } case let x where x > 1: From 2ee5feb9c89e4c1a3224dee7f1c32f067b178a2a Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Fri, 28 Sep 2018 14:09:46 -0500 Subject: [PATCH 09/56] Suspend/Resume --- Loop.xcodeproj/project.pbxproj | 16 +-- Loop/Managers/DeviceDataManager.swift | 13 ++ Loop/Managers/PumpManager.swift | 2 +- .../SettingsTableViewController.swift | 121 ++++++++++++++-- .../StatusTableViewController.swift | 131 ++++++++++++++---- Loop/Views/SettingsImageTableViewCell.swift | 2 + 6 files changed, 242 insertions(+), 43 deletions(-) diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj index ef7108f0fc..d681784f84 100644 --- a/Loop.xcodeproj/project.pbxproj +++ b/Loop.xcodeproj/project.pbxproj @@ -2505,7 +2505,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Loop/Loop.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; INFOPLIST_FILE = Loop/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; "OTHER_SWIFT_FLAGS[sdk=iphonesimulator*]" = "-D IOS_SIMULATOR"; @@ -2522,7 +2522,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Loop/Loop.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; INFOPLIST_FILE = Loop/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER)"; @@ -2538,7 +2538,7 @@ CODE_SIGN_ENTITLEMENTS = "WatchApp Extension/WatchApp Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/watchOS"; INFOPLIST_FILE = "WatchApp Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; @@ -2558,7 +2558,7 @@ CODE_SIGN_ENTITLEMENTS = "WatchApp Extension/WatchApp Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/watchOS"; INFOPLIST_FILE = "WatchApp Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; @@ -2578,7 +2578,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; FRAMEWORK_SEARCH_PATHS = ""; IBSC_MODULE = WatchApp_Extension; INFOPLIST_FILE = WatchApp/Info.plist; @@ -2599,7 +2599,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; FRAMEWORK_SEARCH_PATHS = ""; IBSC_MODULE = WatchApp_Extension; INFOPLIST_FILE = WatchApp/Info.plist; @@ -2678,7 +2678,7 @@ CODE_SIGN_ENTITLEMENTS = "Loop Status Extension/Loop Status Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; INFOPLIST_FILE = "Loop Status Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).statuswidget"; @@ -2697,7 +2697,7 @@ CODE_SIGN_ENTITLEMENTS = "Loop Status Extension/Loop Status Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; INFOPLIST_FILE = "Loop Status Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).statuswidget"; diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index e0550c1b1f..e51e6c4a56 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -161,6 +161,7 @@ extension DeviceDataManager: CGMManagerDelegate { extension DeviceDataManager: PumpManagerDelegate { + func pumpManager(_ pumpManager: PumpManager, didAdjustPumpClockBy adjustment: TimeInterval) { AnalyticsManager.shared.pumpTimeDidDrift(adjustment) } @@ -281,6 +282,10 @@ extension DeviceDataManager: PumpManagerDelegate { return loopManager.doseStore.lastReservoirValue?.startDate ?? .distantPast } + func pumpManager(_ pumpManager: PumpManager, didUpdateSuspendState suspendState: Bool) { + NotificationCenter.default.post(name: .PumpSuspendStateChanged, object: self, userInfo: [DeviceDataManager.pumpSuspendStateKey: suspendState]) + } + } @@ -375,3 +380,11 @@ extension DeviceDataManager: CustomDebugStringConvertible { ].joined(separator: "\n") } } + +extension Notification.Name { + static let PumpSuspendStateChanged = Notification.Name(rawValue: "com.loopKit.notification.PumpSuspendStateChanged") +} + +extension DeviceDataManager { + public static let pumpSuspendStateKey = "com.loopkit.PumpSuspendState" +} diff --git a/Loop/Managers/PumpManager.swift b/Loop/Managers/PumpManager.swift index 235a94f147..a663ca71e2 100644 --- a/Loop/Managers/PumpManager.swift +++ b/Loop/Managers/PumpManager.swift @@ -13,7 +13,7 @@ import OmniKit let allPumpManagers: [PumpManager.Type] = [ OmnipodPumpManager.self, - //MinimedPumpManager.self + MinimedPumpManager.self ] private let managersByIdentifier: [String: PumpManager.Type] = allPumpManagers.reduce(into: [:]) { (map, Type) in diff --git a/Loop/View Controllers/SettingsTableViewController.swift b/Loop/View Controllers/SettingsTableViewController.swift index 7864783800..d5f281b344 100644 --- a/Loop/View Controllers/SettingsTableViewController.swift +++ b/Loop/View Controllers/SettingsTableViewController.swift @@ -25,6 +25,7 @@ final class SettingsTableViewController: UITableViewController { tableView.register(SettingsTableViewCell.self, forCellReuseIdentifier: SettingsTableViewCell.className) tableView.register(SettingsImageTableViewCell.self, forCellReuseIdentifier: SettingsImageTableViewCell.className) tableView.register(TextButtonTableViewCell.self, forCellReuseIdentifier: TextButtonTableViewCell.className) + tableView.register(SuspendResumeTableViewCell.self, forCellReuseIdentifier: SuspendResumeTableViewCell.className) } override func viewWillAppear(_ animated: Bool) { @@ -34,6 +35,7 @@ final class SettingsTableViewController: UITableViewController { _ = tableView(tableView, willDeselectRowAt: indexPath) } } + tableView.reloadSections([Section.pump.rawValue], with: .none) super.viewWillAppear(animated) } @@ -61,6 +63,7 @@ final class SettingsTableViewController: UITableViewController { fileprivate enum PumpRow: Int, CaseCountable { case pumpSettings = 0 + case suspendResume } fileprivate enum CGMRow: Int, CaseCountable { @@ -109,6 +112,15 @@ final class SettingsTableViewController: UITableViewController { } } + func configuredSetupViewController(for pumpManager: PumpManagerUI.Type) -> (UIViewController & PumpManagerSetupViewController) { + var setupViewController = pumpManager.setupViewController() + setupViewController.setupDelegate = self + setupViewController.basalSchedule = dataManager.loopManager.basalRateSchedule + setupViewController.maxBolusUnits = dataManager.loopManager.settings.maximumBolus + setupViewController.maxBasalRateUnitsPerHour = dataManager.loopManager.settings.maximumBasalRatePerHour + return setupViewController + } + // MARK: - UITableViewDataSource override func numberOfSections(in tableView: UITableView) -> Int { @@ -120,7 +132,11 @@ final class SettingsTableViewController: UITableViewController { case .loop: return LoopRow.count case .pump: - return PumpRow.count + if dataManager.pumpManager != nil { + return PumpRow.count + } else { + return 1 + } case .cgm: return 1 case .configuration: @@ -167,6 +183,11 @@ final class SettingsTableViewController: UITableViewController { cell.textLabel?.text = NSLocalizedString("Add Pump", comment: "Title text for button to set up a new pump") return cell } + case .suspendResume: + let pumpManager = dataManager.pumpManager! + let cell = tableView.dequeueReusableCell(withIdentifier: SuspendResumeTableViewCell.className, for: indexPath) as! SuspendResumeTableViewCell + cell.option = pumpManager.isDeliverySuspended ? .resume : .suspend + return cell } case .cgm: if let cgmManager = dataManager.cgmManager { @@ -328,18 +349,15 @@ final class SettingsTableViewController: UITableViewController { switch pumpManagers.count { case 1: if let PumpManagerType = pumpManagers.first { - var setupViewController = PumpManagerType.setupViewController() - setupViewController.setupDelegate = self - setupViewController.basalSchedule = dataManager.loopManager.basalRateSchedule - setupViewController.maxBolusUnits = dataManager.loopManager.settings.maximumBolus - setupViewController.maxBasalRateUnitsPerHour = dataManager.loopManager.settings.maximumBasalRatePerHour + let setupViewController = configuredSetupViewController(for: PumpManagerType) present(setupViewController, animated: true, completion: nil) } case let x where x > 1: let alert = UIAlertController(pumpManagers: pumpManagers) { [weak self] (manager) in - var setupViewController = manager.setupViewController() - setupViewController.setupDelegate = self - self?.present(setupViewController, animated: true, completion: nil) + if let self = self { + let setupViewController = self.configuredSetupViewController(for: manager) + self.present(setupViewController, animated: true, completion: nil) + } } alert.addCancelAction { (_) in @@ -351,6 +369,42 @@ final class SettingsTableViewController: UITableViewController { break } } + case .suspendResume: + if let cell = tableView.cellForRow(at: indexPath) as? SuspendResumeTableViewCell, + let pumpManager = dataManager.pumpManager + { + cell.isLoading = true + cell.isEnabled = false + switch cell.option { + case .resume: + pumpManager.resumeDelivery { (result) in + DispatchQueue.main.async { + cell.isEnabled = true + cell.isLoading = false + if case .failure(let error) = result { + let alert = UIAlertController(title: NSLocalizedString("Error Resuming", comment: "The alert title for a resume error"), error: error) + self.present(alert, animated: true, completion: nil) + } else { + self.tableView.reloadRows(at: [indexPath], with: .none) + } + } + } + case .suspend: + pumpManager.suspendDelivery { (result) in + DispatchQueue.main.async { + cell.isEnabled = true + cell.isLoading = false + if case .failure(let error) = result { + let alert = UIAlertController(title: NSLocalizedString("Error Suspending", comment: "The alert title for a suspend error"), error: error) + self.present(alert, animated: true, completion: nil) + } else { + self.tableView.reloadRows(at: [indexPath], with: .none) + } + } + } + } + tableView.deselectRow(at: indexPath, animated: true) + } } case .cgm: if let cgmManager = dataManager.cgmManager as? CGMManagerUI { @@ -553,7 +607,7 @@ final class SettingsTableViewController: UITableViewController { case .loop: break case .pump: - tableView.reloadRows(at: [indexPath], with: .fade) + tableView.reloadSections([Section.pump.rawValue], with: .none) tableView.reloadRows(at: [[Section.cgm.rawValue, CGMRow.cgmSettings.rawValue]], with: .fade) case .cgm: tableView.reloadRows(at: [indexPath], with: .fade) @@ -739,3 +793,50 @@ extension SettingsTableViewController: DeliveryLimitSettingsTableViewControllerD tableView.reloadRows(at: [[Section.configuration.rawValue, ConfigurationRow.deliveryLimits.rawValue]], with: .none) } } + +extension UIAlertController { + fileprivate convenience init(title: String, error: Error) { + + let message: String + + if let localizedError = error as? LocalizedError { + let sentenceFormat = NSLocalizedString("%@.", comment: "Appends a full-stop to a statement") + message = [localizedError.failureReason, localizedError.recoverySuggestion].compactMap({ $0 }).map({ + String(format: sentenceFormat, $0) + }).joined(separator: "\n") + } else { + message = String(describing: error) + } + + self.init( + title: title, + message: message, + preferredStyle: .alert + ) + + addAction(UIAlertAction( + title: NSLocalizedString("OK", comment: "Button title to acknowledge error"), + style: .default, + handler: nil + )) + } +} + +class SuspendResumeTableViewCell: TextButtonTableViewCell { + + enum Option { + case suspend + case resume + } + + var option: Option = .suspend { + didSet { + switch option { + case .suspend: + textLabel?.text = NSLocalizedString("Suspend Delivery", comment: "Title text for button to suspend insulin delivery") + case .resume: + textLabel?.text = NSLocalizedString("Resume Delivery", comment: "Title text for button to resume insulin delivery") + } + } + } +} diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index 3b24aec0b4..594af5777d 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -24,7 +24,6 @@ private enum BolusState { case enacting } - private extension RefreshContext { static let all: Set = [.status, .glucose, .insulin, .carbs, .targets] } @@ -41,6 +40,10 @@ final class StatusTableViewController: ChartsTableViewController { min: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 100), max: HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 175) ) + + if let pumpManager = deviceManager.pumpManager { + pumpIsSuspended = pumpManager.isDeliverySuspended + } let notificationCenter = NotificationCenter.default @@ -71,6 +74,14 @@ final class StatusTableViewController: ChartsTableViewController { DispatchQueue.main.async { self?.hudView?.loopCompletionHUD.loopInProgress = true } + }, + notificationCenter.addObserver(forName: .PumpSuspendStateChanged, object: deviceManager, queue: OperationQueue.main) { [weak self] (notification: Notification) in + DispatchQueue.main.async { + if let isPumpSuspended = notification.userInfo?[DeviceDataManager.pumpSuspendStateKey] as? Bool, let self = self { + self.pumpIsSuspended = isPumpSuspended + self.reloadData(animated: true) + } + } } ] @@ -165,6 +176,12 @@ final class StatusTableViewController: ChartsTableViewController { refreshContext.update(with: .status) } } + + public var pumpIsSuspended: Bool = false { + didSet { + refreshContext.update(with: .status) + } + } // Toggles the display mode based on the screen aspect ratio. Should not be updated outside of reloadData(). private var landscapeMode = false @@ -433,15 +450,19 @@ final class StatusTableViewController: ChartsTableViewController { // Show/hide the table view rows let statusRowMode: StatusRowMode? - - switch bolusState { - case .recommended?, .enacting?: - statusRowMode = nil - case .none: - if let (recommendation: tempBasal, date: date) = newRecommendedTempBasal { - statusRowMode = .recommendedTempBasal(tempBasal: tempBasal, at: date, enacting: false) - } else { - statusRowMode = .hidden + + if self.pumpIsSuspended { + statusRowMode = .pumpSuspended(resuming: false) + } else { + switch bolusState { + case .recommended?, .enacting?: + statusRowMode = nil + case .none: + if let (recommendation: tempBasal, date: date) = newRecommendedTempBasal { + statusRowMode = .recommendedTempBasal(tempBasal: tempBasal, at: date, enacting: false) + } else { + statusRowMode = .hidden + } } } @@ -509,6 +530,7 @@ final class StatusTableViewController: ChartsTableViewController { case hidden case recommendedTempBasal(tempBasal: TempBasalRecommendation, at: Date, enacting: Bool) case enactingBolus + case pumpSuspended(resuming: Bool) var hasRow: Bool { switch self { @@ -576,6 +598,14 @@ final class StatusTableViewController: ChartsTableViewController { } case (.enactingBolus, .enactingBolus): break + case (.pumpSuspended(resuming: let wasResuming), .pumpSuspended(resuming: let isResuming)): + if isResuming, !wasResuming, let cell = tableView.cellForRow(at: statusIndexPath) as? TitleSubtitleTableViewCell { + let indicatorView = UIActivityIndicatorView(activityIndicatorStyle: .gray) + indicatorView.startAnimating() + cell.accessoryView = indicatorView + cell.subtitleLabel.text = nil + } + break default: self.tableView.reloadRows(at: [statusIndexPath], with: animated ? .fade : .none) } @@ -726,6 +756,10 @@ final class StatusTableViewController: ChartsTableViewController { let indicatorView = UIActivityIndicatorView(activityIndicatorStyle: .gray) indicatorView.startAnimating() cell.accessoryView = indicatorView + case .pumpSuspended: + cell.titleLabel.text = NSLocalizedString("Pump Suspended", comment: "The title of the cell indicating the pump is suspended") + cell.subtitleLabel.text = NSLocalizedString("Tap to Resume", comment: "The subtitle of the cell displaying an action to resume insulin delivery") + cell.selectionStyle = .default } } @@ -815,23 +849,43 @@ final class StatusTableViewController: ChartsTableViewController { case .status: tableView.deselectRow(at: indexPath, animated: true) - if case .recommendedTempBasal(tempBasal: let tempBasal, at: let date, enacting: let enacting) = statusRowMode, !enacting { - self.updateHUDandStatusRows(statusRowMode: .recommendedTempBasal(tempBasal: tempBasal, at: date, enacting: true), newSize: nil, animated: true) - - self.deviceManager.loopManager.enactRecommendedTempBasal { (error) in - DispatchQueue.main.async { - self.updateHUDandStatusRows(statusRowMode: .hidden, newSize: nil, animated: true) - - if let error = error { - self.deviceManager.logger.addError(error, fromSource: "TempBasal") - self.presentAlertController(with: error) - } else { - self.refreshContext.update(with: .status) - self.log.debug("[reloadData] after manually enacting temp basal") - self.reloadData() + switch statusRowMode { + case .recommendedTempBasal(tempBasal: let tempBasal, at: let date, enacting: let enacting): + if !enacting { + self.updateHUDandStatusRows(statusRowMode: .recommendedTempBasal(tempBasal: tempBasal, at: date, enacting: true), newSize: nil, animated: true) + + self.deviceManager.loopManager.enactRecommendedTempBasal { (error) in + DispatchQueue.main.async { + self.updateHUDandStatusRows(statusRowMode: .hidden, newSize: nil, animated: true) + + if let error = error { + self.deviceManager.logger.addError(error, fromSource: "TempBasal") + self.presentAlertController(with: error) + } else { + self.refreshContext.update(with: .status) + self.log.debug("[reloadData] after manually enacting temp basal") + self.reloadData() + } } } } + case .pumpSuspended(let resuming): + if !resuming { + self.updateHUDandStatusRows(statusRowMode: .pumpSuspended(resuming: true) , newSize: nil, animated: true) + self.deviceManager.pumpManager?.resumeDelivery(completion: { (result) in + DispatchQueue.main.async { + switch result { + case .failure(let error): + let alert = UIAlertController(title: NSLocalizedString("Error Resuming", comment: "The alert title for a resume error"), error: error) + self.present(alert, animated: true, completion: nil) + case .success: + break + } + } + }) + } + default: + break } } case .hud: @@ -1024,3 +1078,32 @@ final class StatusTableViewController: ChartsTableViewController { } } } + +extension UIAlertController { + fileprivate convenience init(title: String, error: Error) { + + let message: String + + if let localizedError = error as? LocalizedError { + let sentenceFormat = NSLocalizedString("%@.", comment: "Appends a full-stop to a statement") + message = [localizedError.failureReason, localizedError.recoverySuggestion].compactMap({ $0 }).map({ + String(format: sentenceFormat, $0) + }).joined(separator: "\n") + } else { + message = String(describing: error) + } + + self.init( + title: title, + message: message, + preferredStyle: .alert + ) + + addAction(UIAlertAction( + title: NSLocalizedString("OK", comment: "Button title to acknowledge error"), + style: .default, + handler: nil + )) + } +} + diff --git a/Loop/Views/SettingsImageTableViewCell.swift b/Loop/Views/SettingsImageTableViewCell.swift index e99ea9a968..656371f5bf 100644 --- a/Loop/Views/SettingsImageTableViewCell.swift +++ b/Loop/Views/SettingsImageTableViewCell.swift @@ -25,6 +25,8 @@ class SettingsImageTableViewCell: UITableViewCell { guard let textLabel = textLabel, let imageView = imageView else { return } + + separatorInset = .zero textLabel.adjustsFontForContentSizeCategory = true textLabel.font = UIFont.preferredFont(forTextStyle: .body) From ad73ea8036dad5f6d21b108771509ef6dc497d70 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Fri, 28 Sep 2018 16:35:50 -0500 Subject: [PATCH 10/56] Use normal separator behavior --- Loop/Views/SettingsImageTableViewCell.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/Loop/Views/SettingsImageTableViewCell.swift b/Loop/Views/SettingsImageTableViewCell.swift index 656371f5bf..1b997ae9fb 100644 --- a/Loop/Views/SettingsImageTableViewCell.swift +++ b/Loop/Views/SettingsImageTableViewCell.swift @@ -26,8 +26,6 @@ class SettingsImageTableViewCell: UITableViewCell { return } - separatorInset = .zero - textLabel.adjustsFontForContentSizeCategory = true textLabel.font = UIFont.preferredFont(forTextStyle: .body) textLabel.translatesAutoresizingMaskIntoConstraints = false From 230a4412a4ee21994c46b2cdfa5babb728e942d9 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 29 Sep 2018 09:23:42 -0500 Subject: [PATCH 11/56] Reload pump section after adding pumpmanager --- Loop/View Controllers/SettingsTableViewController.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Loop/View Controllers/SettingsTableViewController.swift b/Loop/View Controllers/SettingsTableViewController.swift index d5f281b344..7369ee3155 100644 --- a/Loop/View Controllers/SettingsTableViewController.swift +++ b/Loop/View Controllers/SettingsTableViewController.swift @@ -629,6 +629,7 @@ final class SettingsTableViewController: UITableViewController { extension SettingsTableViewController: PumpManagerSetupViewControllerDelegate { func pumpManagerSetupViewController(_ pumpManagerSetupViewController: PumpManagerSetupViewController, didSetUpPumpManager pumpManager: PumpManagerUI) { dataManager.pumpManager = pumpManager + tableView.reloadSections([Section.pump.rawValue], with: .none) tableView.selectRow(at: IndexPath(row: PumpRow.pumpSettings.rawValue, section: Section.pump.rawValue), animated: false, scrollPosition: .none) if let basalRateSchedule = pumpManagerSetupViewController.basalSchedule { From 83f2943590c3a481f4a33fc3e00e7966025844d0 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Thu, 11 Oct 2018 09:31:14 -0500 Subject: [PATCH 12/56] LoopKit PumpManagerStatus updates --- Loop/Managers/DeviceDataManager.swift | 61 +++++++----- Loop/Managers/NightscoutDataManager.swift | 94 +++++++------------ .../Managers/StatusExtensionDataManager.swift | 5 +- .../SettingsTableViewController.swift | 10 +- .../StatusTableViewController.swift | 4 +- 5 files changed, 81 insertions(+), 93 deletions(-) diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index e51e6c4a56..5e4190de2b 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -57,6 +57,37 @@ final class DeviceDataManager { UserDefaults.appGroup.cgmManager = cgmManager } } + + var pumpManagerStatus: PumpManagerStatus? { + didSet { + if let status = pumpManagerStatus { + + loopManager.doseStore.device = status.device + + if let newBatteryValue = status.pumpBatteryChargeRemaining { + if newBatteryValue == 0 { + NotificationManager.sendPumpBatteryLowNotification() + } else { + NotificationManager.clearPumpBatteryLowNotification() + } + + if let oldBatteryValue = oldValue?.pumpBatteryChargeRemaining, newBatteryValue - oldBatteryValue >= 0.5 { + AnalyticsManager.shared.pumpBatteryWasReplaced() + } + } + + if oldValue?.isSuspended != status.isSuspended { + NotificationCenter.default.post(name: .PumpSuspendStateChanged, object: self, userInfo: [DeviceDataManager.pumpSuspendStateKey: status.isSuspended]) + } + + // Update the pump-schedule based settings + loopManager.setScheduleTimeZone(status.timeZone) + + } else { + loopManager.doseStore.device = nil + } + } + } /// TODO: Isolate to queue private func setupCGM() { @@ -68,6 +99,11 @@ final class DeviceDataManager { private func setupPump() { pumpManager?.pumpManagerDelegate = self + + if let pumpManager = pumpManager { + self.pumpManagerStatus = pumpManager.status + self.loopManager.doseStore.device = self.pumpManagerStatus?.device + } // Proliferate PumpModel preferences to DoseStore if let pumpRecordsBasalProfileStartEvents = pumpManager?.pumpRecordsBasalProfileStartEvents { @@ -96,7 +132,7 @@ final class DeviceDataManager { } else if UserDefaults.appGroup.isCGMManagerValidPumpManager { self.cgmManager = pumpManager as? CGMManager } - + remoteDataManager.delegate = self statusExtensionManager = StatusExtensionDataManager(deviceDataManager: self) loopManager = LoopDataManager( @@ -166,20 +202,6 @@ extension DeviceDataManager: PumpManagerDelegate { AnalyticsManager.shared.pumpTimeDidDrift(adjustment) } - func pumpManagerDidUpdatePumpBatteryChargeRemaining(_ pumpManager: PumpManager, oldValue: Double?) { - if let newValue = pumpManager.pumpBatteryChargeRemaining { - if newValue == 0 { - NotificationManager.sendPumpBatteryLowNotification() - } else { - NotificationManager.clearPumpBatteryLowNotification() - } - - if let oldValue = oldValue, newValue - oldValue >= 0.5 { - AnalyticsManager.shared.pumpBatteryWasReplaced() - } - } - } - func pumpManagerDidUpdateState(_ pumpManager: PumpManager) { UserDefaults.appGroup.pumpManager = pumpManager } @@ -202,10 +224,7 @@ extension DeviceDataManager: PumpManagerDelegate { } func pumpManager(_ pumpManager: PumpManager, didUpdateStatus status: PumpManagerStatus) { - loopManager.doseStore.device = status.device - // Update the pump-schedule based settings - loopManager.setScheduleTimeZone(status.timeZone) - nightscoutDataManager.upload(pumpStatus: status) + self.pumpManagerStatus = status } func pumpManagerWillDeactivate(_ pumpManager: PumpManager) { @@ -282,10 +301,6 @@ extension DeviceDataManager: PumpManagerDelegate { return loopManager.doseStore.lastReservoirValue?.startDate ?? .distantPast } - func pumpManager(_ pumpManager: PumpManager, didUpdateSuspendState suspendState: Bool) { - NotificationCenter.default.post(name: .PumpSuspendStateChanged, object: self, userInfo: [DeviceDataManager.pumpSuspendStateKey: suspendState]) - } - } diff --git a/Loop/Managers/NightscoutDataManager.swift b/Loop/Managers/NightscoutDataManager.swift index 09c2a7483b..67ee491022 100644 --- a/Loop/Managers/NightscoutDataManager.swift +++ b/Loop/Managers/NightscoutDataManager.swift @@ -129,8 +129,36 @@ final class NightscoutDataManager { let loopVersion = Bundle.main.shortVersionString let loopStatus = LoopStatus(name: loopName, version: loopVersion, timestamp: statusTime, iob: iob, cob: cob, predicted: predicted, recommendedTempBasal: recommended, recommendedBolus: recommendedBolus, enacted: loopEnacted, failureReason: loopError) + - upload(pumpStatus: nil, loopStatus: loopStatus, deviceName: nil, firmwareVersion: nil, lastValidFrequency: nil, lastTuned: nil, uploaderStatus: getUploaderStatus()) + + let pumpStatus: NightscoutUploadKit.PumpStatus? + + if let pumpManagerStatus = deviceManager.pumpManagerStatus + { + + let battery: BatteryStatus? + + if let chargeRemaining = pumpManagerStatus.pumpBatteryChargeRemaining { + battery = BatteryStatus(percent: Int(round(chargeRemaining * 100)), voltage: nil, status: nil) + } else { + battery = nil + } + + pumpStatus = NightscoutUploadKit.PumpStatus( + clock: Date(), + pumpID: pumpManagerStatus.device.localIdentifier ?? "Unknown", + iob: nil, + battery: battery, + suspended: pumpManagerStatus.isSuspended, + bolusing: pumpManagerStatus.isBolusing, + reservoir: deviceManager.loopManager.doseStore.lastReservoirValue?.unitVolume, + secondsFromGMT: pumpManagerStatus.timeZone.secondsFromGMT()) + } else { + pumpStatus = nil + } + + upload(pumpStatus: pumpStatus, loopStatus: loopStatus, deviceName: nil, firmwareVersion: nil, uploaderStatus: getUploaderStatus()) } @@ -147,21 +175,11 @@ final class NightscoutDataManager { return UploaderStatus(name: uploaderDevice.name, timestamp: Date(), battery: battery) } - func upload(pumpStatus: PumpManagerStatus) { - upload( - pumpStatus: pumpStatus.pumpStatus, - deviceName: pumpStatus.device?.name, - firmwareVersion: pumpStatus.device?.firmwareVersion, - lastValidFrequency: pumpStatus.lastValidFrequency, - lastTuned: pumpStatus.lastTuned - ) - } - - func upload(pumpStatus: NightscoutUploadKit.PumpStatus?, deviceName: String?, firmwareVersion: String?, lastValidFrequency: Measurement?, lastTuned: Date?) { - upload(pumpStatus: pumpStatus, loopStatus: nil, deviceName: deviceName, firmwareVersion: firmwareVersion, lastValidFrequency: lastValidFrequency, lastTuned: lastTuned, uploaderStatus: nil) + func upload(pumpStatus: NightscoutUploadKit.PumpStatus?, deviceName: String?, firmwareVersion: String?) { + upload(pumpStatus: pumpStatus, loopStatus: nil, deviceName: deviceName, firmwareVersion: firmwareVersion, uploaderStatus: nil) } - private func upload(pumpStatus: NightscoutUploadKit.PumpStatus?, loopStatus: LoopStatus?, deviceName: String?, firmwareVersion: String?, lastValidFrequency: Measurement?, lastTuned: Date?, uploaderStatus: UploaderStatus?) { + private func upload(pumpStatus: NightscoutUploadKit.PumpStatus?, loopStatus: LoopStatus?, deviceName: String?, firmwareVersion: String?, uploaderStatus: UploaderStatus?) { guard let uploader = deviceManager.remoteDataManager.nightscoutService.uploader else { return @@ -176,22 +194,8 @@ final class NightscoutDataManager { let uploaderDevice = UIDevice.current - var radioAdapter: NightscoutUploadKit.RadioAdapter? = nil - - if let firmwareVersion = firmwareVersion { - radioAdapter = NightscoutUploadKit.RadioAdapter( - hardware: "RileyLink", - frequency: lastValidFrequency?.value, - name: deviceName ?? "Unknown", - lastTuned: lastTuned, - firmwareVersion: firmwareVersion, - RSSI: nil, // TODO: device.RSSI, - pumpRSSI: nil // TODO: device.pumpRSSI - ) - } - // Build DeviceStatus - let deviceStatus = DeviceStatus(device: "loop://\(uploaderDevice.name)", timestamp: Date(), pumpStatus: pumpStatus, uploaderStatus: uploaderStatus, loopStatus: loopStatus, radioAdapter: radioAdapter) + let deviceStatus = DeviceStatus(device: "loop://\(uploaderDevice.name)", timestamp: Date(), pumpStatus: pumpStatus, uploaderStatus: uploaderStatus, loopStatus: loopStatus, radioAdapter: nil) self.lastDeviceStatusUpload = Date() uploader.uploadDeviceStatus(deviceStatus) @@ -231,35 +235,3 @@ final class NightscoutDataManager { } } - -private extension PumpManagerStatus { - var batteryStatus: NightscoutUploadKit.BatteryStatus? { - return NightscoutUploadKit.BatteryStatus( - percent: battery?.percent != nil ? Int(battery!.percent! * 100) : nil, - voltage: battery?.voltage?.converted(to: .volts).value, - status: { - switch battery?.state { - case .normal?: - return .normal - case .low?: - return .low - case .none: - return nil - } - }() - ) - } - - var pumpStatus: NightscoutUploadKit.PumpStatus { - return PumpStatus( - clock: date, - pumpID: device?.localIdentifier ?? "", - iob: nil, - battery: batteryStatus, - suspended: isSuspended, - bolusing: isBolusing, - reservoir: remainingReservoir?.doubleValue(for: .internationalUnit()), - secondsFromGMT: timeZone.secondsFromGMT() - ) - } -} diff --git a/Loop/Managers/StatusExtensionDataManager.swift b/Loop/Managers/StatusExtensionDataManager.swift index ae5a1c13f8..8f451cc64f 100644 --- a/Loop/Managers/StatusExtensionDataManager.swift +++ b/Loop/Managers/StatusExtensionDataManager.swift @@ -98,8 +98,9 @@ final class StatusExtensionDataManager { context.netBasal = NetBasalContext(rate: netBasal.rate, percentage: netBasal.percent, start: netBasal.start, end: netBasal.end) } - - context.batteryPercentage = dataManager.pumpManager?.pumpBatteryChargeRemaining + + + context.batteryPercentage = dataManager.pumpManager?.status.pumpBatteryChargeRemaining context.reservoirCapacity = dataManager.pumpManager?.pumpReservoirCapacity if let sensorInfo = dataManager.cgmManager?.sensorState { diff --git a/Loop/View Controllers/SettingsTableViewController.swift b/Loop/View Controllers/SettingsTableViewController.swift index 7369ee3155..c5c0e368b3 100644 --- a/Loop/View Controllers/SettingsTableViewController.swift +++ b/Loop/View Controllers/SettingsTableViewController.swift @@ -186,7 +186,7 @@ final class SettingsTableViewController: UITableViewController { case .suspendResume: let pumpManager = dataManager.pumpManager! let cell = tableView.dequeueReusableCell(withIdentifier: SuspendResumeTableViewCell.className, for: indexPath) as! SuspendResumeTableViewCell - cell.option = pumpManager.isDeliverySuspended ? .resume : .suspend + cell.option = pumpManager.status.isSuspended ? .resume : .suspend return cell } case .cgm: @@ -463,7 +463,7 @@ final class SettingsTableViewController: UITableViewController { scheduleVC.timeZone = schedule.timeZone scheduleVC.scheduleItems = schedule.items scheduleVC.unit = schedule.unit - } else if let timeZone = dataManager.pumpManager?.pumpTimeZone { + } else if let timeZone = dataManager.pumpManager?.status.timeZone { scheduleVC.timeZone = timeZone } @@ -481,7 +481,7 @@ final class SettingsTableViewController: UITableViewController { show(scheduleVC, sender: sender) } else { - if let timeZone = dataManager.pumpManager?.pumpTimeZone { + if let timeZone = dataManager.pumpManager?.status.timeZone { scheduleVC.timeZone = timeZone } @@ -504,7 +504,7 @@ final class SettingsTableViewController: UITableViewController { show(scheduleVC, sender: sender) } else { - if let timeZone = dataManager.pumpManager?.pumpTimeZone { + if let timeZone = dataManager.pumpManager?.status.timeZone { scheduleVC.timeZone = timeZone } @@ -546,7 +546,7 @@ final class SettingsTableViewController: UITableViewController { if let profile = dataManager.loopManager.basalRateSchedule { vc.scheduleItems = profile.items vc.timeZone = profile.timeZone - } else if let timeZone = dataManager.pumpManager?.pumpTimeZone { + } else if let timeZone = dataManager.pumpManager?.status.timeZone { vc.timeZone = timeZone } diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index 594af5777d..51d2d82249 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -42,7 +42,7 @@ final class StatusTableViewController: ChartsTableViewController { ) if let pumpManager = deviceManager.pumpManager { - pumpIsSuspended = pumpManager.isDeliverySuspended + self.pumpIsSuspended = pumpManager.status.isSuspended } let notificationCenter = NotificationCenter.default @@ -445,7 +445,7 @@ final class StatusTableViewController: ChartsTableViewController { } // Battery HUD - hudView.batteryHUD.batteryLevel = self.deviceManager.pumpManager?.pumpBatteryChargeRemaining ?? UserDefaults.appGroup.statusExtensionContext?.batteryPercentage + hudView.batteryHUD.batteryLevel = self.deviceManager.pumpManager?.status.pumpBatteryChargeRemaining ?? UserDefaults.appGroup.statusExtensionContext?.batteryPercentage } // Show/hide the table view rows From d0c4a918b1353b912d57d98e6a0bdd3d1691a7ba Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Thu, 18 Oct 2018 16:58:28 -0500 Subject: [PATCH 13/56] PumpManagerUI vended HUD views --- Common/Models/PumpManagerUI.swift | 52 ++++++ Common/Models/StatusExtensionContext.swift | 38 +++++ Loop Status Extension/StateColorPalette.swift | 1 + .../StatusViewController.swift | 30 ++-- Loop.xcodeproj/project.pbxproj | 64 +++----- Loop/Extensions/StateColorPalette.swift | 16 -- Loop/Extensions/UIImage.swift | 8 - Loop/Managers/DeviceDataManager.swift | 3 + .../Managers/StatusExtensionDataManager.swift | 4 + .../StatusTableViewController.swift | 55 +++++-- .../Contents.json | 0 .../battery/Contents.json | 0 .../battery/battery.imageset/Contents.json | 0 .../battery/battery.imageset/battery.pdf | Bin .../battery_mask.imageset/Contents.json | 0 .../battery_mask.imageset/battery_mask.pdf | Bin .../reservoir/Contents.json | 0 .../reservoir.imageset/Contents.json | 0 .../reservoir.imageset/reservoir.pdf | Bin .../reservoir_mask.imageset/Contents.json | 0 .../reservoir_mask.pdf | Bin LoopUI/HUDView.xib | 149 ++---------------- LoopUI/Models/StateColorPalette.swift | 24 --- LoopUI/Views/BasalRateHUDView.swift | 2 +- LoopUI/Views/BaseHUDView.swift | 19 --- LoopUI/Views/BatteryLevelHUDView.swift | 34 ---- LoopUI/Views/GlucoseHUDView.swift | 2 +- LoopUI/Views/HUDView.swift | 18 ++- LoopUI/Views/LevelHUDView.swift | 52 ------ LoopUI/Views/LevelMaskView.swift | 85 ---------- LoopUI/Views/LoopCompletionHUDView.swift | 1 + LoopUI/Views/ReservoirVolumeHUDView.swift | 65 -------- 32 files changed, 203 insertions(+), 519 deletions(-) create mode 100644 Common/Models/PumpManagerUI.swift delete mode 100644 Loop/Extensions/StateColorPalette.swift rename LoopUI/{Assets.xcassets => HUDAssets.xcassets}/Contents.json (100%) rename LoopUI/{Assets.xcassets => HUDAssets.xcassets}/battery/Contents.json (100%) rename LoopUI/{Assets.xcassets => HUDAssets.xcassets}/battery/battery.imageset/Contents.json (100%) rename LoopUI/{Assets.xcassets => HUDAssets.xcassets}/battery/battery.imageset/battery.pdf (100%) rename LoopUI/{Assets.xcassets => HUDAssets.xcassets}/battery/battery_mask.imageset/Contents.json (100%) rename LoopUI/{Assets.xcassets => HUDAssets.xcassets}/battery/battery_mask.imageset/battery_mask.pdf (100%) rename LoopUI/{Assets.xcassets => HUDAssets.xcassets}/reservoir/Contents.json (100%) rename LoopUI/{Assets.xcassets => HUDAssets.xcassets}/reservoir/reservoir.imageset/Contents.json (100%) rename LoopUI/{Assets.xcassets => HUDAssets.xcassets}/reservoir/reservoir.imageset/reservoir.pdf (100%) rename LoopUI/{Assets.xcassets => HUDAssets.xcassets}/reservoir/reservoir_mask.imageset/Contents.json (100%) rename LoopUI/{Assets.xcassets => HUDAssets.xcassets}/reservoir/reservoir_mask.imageset/reservoir_mask.pdf (100%) delete mode 100644 LoopUI/Models/StateColorPalette.swift delete mode 100644 LoopUI/Views/BaseHUDView.swift delete mode 100644 LoopUI/Views/BatteryLevelHUDView.swift delete mode 100644 LoopUI/Views/LevelHUDView.swift delete mode 100644 LoopUI/Views/LevelMaskView.swift delete mode 100644 LoopUI/Views/ReservoirVolumeHUDView.swift diff --git a/Common/Models/PumpManagerUI.swift b/Common/Models/PumpManagerUI.swift new file mode 100644 index 0000000000..a40c6c0c93 --- /dev/null +++ b/Common/Models/PumpManagerUI.swift @@ -0,0 +1,52 @@ +// +// PumpManagerUI.swift +// Loop +// +// Created by Pete Schwamb on 10/18/18. +// Copyright © 2018 LoopKit Authors. All rights reserved. +// + +import Foundation +import LoopKitUI +import OmniKit +import OmniKitUI +import MinimedKit +import MinimedKitUI + +let allPumpManagerUIs: [PumpManagerUI.Type] = [ + OmnipodPumpManager.self, + MinimedPumpManager.self +] + +private let managersByIdentifier: [String: PumpManagerUI.Type] = allPumpManagerUIs.reduce(into: [:]) { (map, Type) in + map[Type.managerIdentifier] = Type +} + +func PumpManagerUITypeFromRawValue(_ rawValue: [String: Any]) -> PumpManagerUI.Type? { + guard let managerIdentifier = rawValue["managerIdentifier"] as? String else { + return nil + } + + return managersByIdentifier[managerIdentifier] +} + +func PumpManagerHUDViewsFromRawValue(_ rawValue: [String: Any]) -> [BaseHUDView]? { + guard let rawState = rawValue["pumpManagerHUDViews"] as? PumpManagerUI.PumpManagerHUDViewsRawState, + let Manager = PumpManagerUITypeFromRawValue(rawValue) + else { + return nil + } + + return Manager.instantiateHUDViews(rawValue: rawState) +} + +extension PumpManagerUI { + var rawPumpManagerHUDViewsValue: [String: Any] { + return [ + "managerIdentifier": type(of: self).managerIdentifier, + "pumpManagerHUDViews": self.hudViewsRawState + ] + } +} + + diff --git a/Common/Models/StatusExtensionContext.swift b/Common/Models/StatusExtensionContext.swift index f385cf30cc..e05ead7675 100644 --- a/Common/Models/StatusExtensionContext.swift +++ b/Common/Models/StatusExtensionContext.swift @@ -10,6 +10,7 @@ import Foundation import HealthKit import LoopKit +import LoopKitUI struct NetBasalContext { @@ -151,6 +152,35 @@ extension PredictedGlucoseContext: RawRepresentable { } } +struct PumpManagerHUDViewsContext: RawRepresentable { + typealias RawValue = [String: Any] + + let hudViews: [BaseHUDView]? + let pumpManagerUI: PumpManagerUI? + + init(pumpManagerUI: PumpManagerUI) { + self.pumpManagerUI = pumpManagerUI + self.hudViews = nil + } + + init?(rawValue: [String : Any]) { + pumpManagerUI = nil + if let hudViews = PumpManagerHUDViewsFromRawValue(rawValue) { + self.hudViews = hudViews + } else { + return nil + } + } + + var rawValue: [String : Any] { + if let pumpManagerUI = pumpManagerUI { + return pumpManagerUI.rawPumpManagerHUDViewsValue + } else { + return [:] + } + } +} + struct StatusExtensionContext: RawRepresentable { typealias RawValue = [String: Any] private let version = 5 @@ -161,6 +191,7 @@ struct StatusExtensionContext: RawRepresentable { var batteryPercentage: Double? var reservoirCapacity: Double? var sensor: SensorDisplayableContext? + var pumpManagerHUDViewsContext: PumpManagerHUDViewsContext? init() { } @@ -184,6 +215,11 @@ struct StatusExtensionContext: RawRepresentable { if let rawValue = rawValue["sensor"] as? SensorDisplayableContext.RawValue { sensor = SensorDisplayableContext(rawValue: rawValue) } + + if let rawPumpManagerHUDViewsContext = rawValue["pumpManagerHUDViewsContext"] as? PumpManagerHUDViewsContext.RawValue { + pumpManagerHUDViewsContext = PumpManagerHUDViewsContext(rawValue: rawPumpManagerHUDViewsContext) + } + } var rawValue: RawValue { @@ -197,6 +233,8 @@ struct StatusExtensionContext: RawRepresentable { raw["batteryPercentage"] = batteryPercentage raw["reservoirCapacity"] = reservoirCapacity raw["sensor"] = sensor?.rawValue + raw["pumpManagerHUDViewsContext"] = pumpManagerHUDViewsContext?.rawValue + return raw } } diff --git a/Loop Status Extension/StateColorPalette.swift b/Loop Status Extension/StateColorPalette.swift index c4e67ba9c4..e6f18b436a 100644 --- a/Loop Status Extension/StateColorPalette.swift +++ b/Loop Status Extension/StateColorPalette.swift @@ -6,6 +6,7 @@ // import LoopUI +import LoopKitUI extension StateColorPalette { static let loopStatus = StateColorPalette(unknown: .unknownColor, normal: .freshColor, warning: .agingColor, error: .staleColor) diff --git a/Loop Status Extension/StatusViewController.swift b/Loop Status Extension/StatusViewController.swift index 68d1856898..e6ed17244b 100644 --- a/Loop Status Extension/StatusViewController.swift +++ b/Loop Status Extension/StatusViewController.swift @@ -9,6 +9,7 @@ import CoreData import HealthKit import LoopKit +import LoopKitUI import LoopUI import NotificationCenter import UIKit @@ -22,8 +23,6 @@ class StatusViewController: UIViewController, NCWidgetProviding { hudView.glucoseHUD.stateColors = .cgmStatus hudView.glucoseHUD.tintColor = .glucoseTintColor hudView.basalRateHUD.tintColor = .doseTintColor - hudView.reservoirVolumeHUD.stateColors = .pumpStatus - hudView.batteryHUD.stateColors = .pumpStatus } } @IBOutlet weak var subtitleLabel: UILabel! @@ -159,7 +158,6 @@ class StatusViewController: UIViewController, NCWidgetProviding { let group = DispatchGroup() var activeInsulin: Double? - var lastReservoirValue: ReservoirValue? var glucose: [StoredGlucoseSample] = [] group.enter() @@ -173,17 +171,6 @@ class StatusViewController: UIViewController, NCWidgetProviding { group.leave() } - group.enter() - doseStore.getReservoirValues(since: .distantPast, limit: 1) { (result) in - switch result { - case .success(let values): - lastReservoirValue = values.first - case .failure: - lastReservoirValue = nil - } - group.leave() - } - charts.startDate = Calendar.current.nextDate(after: Date(timeIntervalSinceNow: .minutes(-5)), matching: DateComponents(minute: 0), matchingPolicy: .strict, direction: .backward) ?? Date() // Showing the whole history plus full prediction in the glucose plot @@ -201,13 +188,14 @@ class StatusViewController: UIViewController, NCWidgetProviding { return } - if let batteryPercentage = context.batteryPercentage { - self.hudView.batteryHUD.batteryLevel = Double(batteryPercentage) - } - - if let reservoir = lastReservoirValue, let capacity = context.reservoirCapacity { - self.hudView.reservoirVolumeHUD.reservoirLevel = min(1, max(0, Double(reservoir.unitVolume / capacity))) - self.hudView.reservoirVolumeHUD.setReservoirVolume(volume: reservoir.unitVolume, at: reservoir.startDate) + if let hudViewsContext = context.pumpManagerHUDViewsContext, + let hudViews = hudViewsContext.hudViews { + for view in hudViews { + if let levelView = view as? LevelHUDView { + levelView.stateColors = .pumpStatus + } + } + self.hudView.setAdditionalHUDViews(hudViews) } if let netBasal = context.netBasal { diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj index f9feb73c9e..7a2c91a36e 100644 --- a/Loop.xcodeproj/project.pbxproj +++ b/Loop.xcodeproj/project.pbxproj @@ -153,8 +153,6 @@ 43BFF0C51E465A2D00FF19A9 /* UIColor+HIG.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43BFF0C31E4659E700FF19A9 /* UIColor+HIG.swift */; }; 43BFF0C61E465A4400FF19A9 /* UIColor+HIG.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43BFF0C31E4659E700FF19A9 /* UIColor+HIG.swift */; }; 43BFF0C71E465A4F00FF19A9 /* UIColor+HIG.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43BFF0C31E4659E700FF19A9 /* UIColor+HIG.swift */; }; - 43BFF0C91E465B0A00FF19A9 /* StateColorPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43BFF0C81E465B0A00FF19A9 /* StateColorPalette.swift */; }; - 43BFF0CB1E466C0900FF19A9 /* StateColorPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43BFF0CA1E466C0900FF19A9 /* StateColorPalette.swift */; }; 43BFF0CD1E466C8400FF19A9 /* StateColorPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43BFF0CC1E466C8400FF19A9 /* StateColorPalette.swift */; }; 43C0944A1CACCC73001F6403 /* NotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C094491CACCC73001F6403 /* NotificationManager.swift */; }; 43C246A81D89990F0031F8D1 /* Crypto.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43C246A71D89990F0031F8D1 /* Crypto.framework */; }; @@ -177,7 +175,6 @@ 43DE925A1C5479E4001FFDE1 /* CarbEntryUserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43DE92581C5479E4001FFDE1 /* CarbEntryUserInfo.swift */; }; 43DE92611C555C26001FFDE1 /* AbsorptionTimeType+CarbKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43DE92601C555C26001FFDE1 /* AbsorptionTimeType+CarbKit.swift */; }; 43DFB62320D4CAE7008A7BAE /* PumpManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C3B6F620BBCAA30026CAFA /* PumpManager.swift */; }; - 43E0F0A51E46D1670064F7CE /* LevelHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43E0F0A41E46D1670064F7CE /* LevelHUDView.swift */; }; 43E2D8C81D208D5B004DA55F /* KeychainManager+Loop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43E2D8C71D208D5B004DA55F /* KeychainManager+Loop.swift */; }; 43E2D8D41D20BF42004DA55F /* DoseMathTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43E2D8D31D20BF42004DA55F /* DoseMathTests.swift */; }; 43E2D8DB1D20C03B004DA55F /* NSTimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 439897341CD2F7DE00223065 /* NSTimeInterval.swift */; }; @@ -217,7 +214,6 @@ 4F11D3C220DD80B3006E072C /* WatchHistoricalGlucose.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F11D3C120DD80B3006E072C /* WatchHistoricalGlucose.swift */; }; 4F11D3C320DD84DB006E072C /* GlucoseBackfillRequestUserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F11D3BF20DCBEEC006E072C /* GlucoseBackfillRequestUserInfo.swift */; }; 4F11D3C420DD881A006E072C /* WatchHistoricalGlucose.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F11D3C120DD80B3006E072C /* WatchHistoricalGlucose.swift */; }; - 4F20AE621E6B879C00D07A06 /* ReservoirVolumeHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437CEEC71CD84CBB003C8C80 /* ReservoirVolumeHUDView.swift */; }; 4F20AE631E6B87B100D07A06 /* ChartContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4313EDDF1D8A6BF90060FA79 /* ChartContainerView.swift */; }; 4F2C15741E0209F500E160D4 /* NSTimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 439897341CD2F7DE00223065 /* NSTimeInterval.swift */; }; 4F2C15811E0495B200E160D4 /* WatchContext+WatchApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F2C15801E0495B200E160D4 /* WatchContext+WatchApp.swift */; }; @@ -226,7 +222,7 @@ 4F2C15851E075B8700E160D4 /* LoopUI.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F75288D1DFE1DC600C322D6 /* LoopUI.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4F2C15931E09BF2C00E160D4 /* HUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F2C15921E09BF2C00E160D4 /* HUDView.swift */; }; 4F2C15951E09BF3C00E160D4 /* HUDView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4F2C15941E09BF3C00E160D4 /* HUDView.xib */; }; - 4F2C15971E09E94E00E160D4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4F2C15961E09E94E00E160D4 /* Assets.xcassets */; }; + 4F2C15971E09E94E00E160D4 /* HUDAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4F2C15961E09E94E00E160D4 /* HUDAssets.xcassets */; }; 4F2C159A1E0C9E5600E160D4 /* LoopUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4F75288B1DFE1DC600C322D6 /* LoopUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 4F526D611DF8D9A900A04910 /* NetBasal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F526D601DF8D9A900A04910 /* NetBasal.swift */; }; 4F526D621DF9D95200A04910 /* NSBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 430DA58D1D4AEC230097D1CA /* NSBundle.swift */; }; @@ -241,13 +237,10 @@ 4F7528941DFE1E9500C322D6 /* LoopUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4F75288B1DFE1DC600C322D6 /* LoopUI.framework */; }; 4F7528951DFE1E9B00C322D6 /* LoopUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4F75288B1DFE1DC600C322D6 /* LoopUI.framework */; }; 4F75289A1DFE1F6000C322D6 /* BasalRateHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437CEEBF1CD6FCD8003C8C80 /* BasalRateHUDView.swift */; }; - 4F75289B1DFE1F6000C322D6 /* BatteryLevelHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437CEEC91CD84DB7003C8C80 /* BatteryLevelHUDView.swift */; }; 4F75289C1DFE1F6000C322D6 /* GlucoseHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4337615E1D52F487004A3647 /* GlucoseHUDView.swift */; }; - 4F75289D1DFE1F6000C322D6 /* BaseHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437CEEBB1CD6DE6A003C8C80 /* BaseHUDView.swift */; }; 4F75289E1DFE1F6000C322D6 /* LoopCompletionHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437CEEBD1CD6E0CB003C8C80 /* LoopCompletionHUDView.swift */; }; 4F7528A01DFE1F9D00C322D6 /* LoopStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 438DADC71CDE8F8B007697A5 /* LoopStateView.swift */; }; 4F7528A11DFE200B00C322D6 /* BasalStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43B371851CE583890013C5A6 /* BasalStateView.swift */; }; - 4F7528A21DFE200B00C322D6 /* LevelMaskView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43FBEDD71D73843700B21F22 /* LevelMaskView.swift */; }; 4F7528A51DFE208C00C322D6 /* NSTimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 439897341CD2F7DE00223065 /* NSTimeInterval.swift */; }; 4F7528AA1DFE215100C322D6 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F526D5E1DF2459000A04910 /* HKUnit.swift */; }; 4F75F00220FCFE8C00B5570E /* GlucoseChartScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F75F00120FCFE8C00B5570E /* GlucoseChartScene.swift */; }; @@ -307,6 +300,10 @@ C1C73F0D1DE3D0270022FC89 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = C1C73F0F1DE3D0270022FC89 /* InfoPlist.strings */; }; C1CB13A9213EE35800F9EEDA /* OmniKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1CB13A8213EE35800F9EEDA /* OmniKit.framework */; }; C1CB13AB213EE35800F9EEDA /* OmniKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1CB13AA213EE35800F9EEDA /* OmniKitUI.framework */; }; + C1FB428C217806A400FAB378 /* StateColorPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1FB428B217806A300FAB378 /* StateColorPalette.swift */; }; + C1FB428D21791D2500FAB378 /* PumpManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C3B6F620BBCAA30026CAFA /* PumpManager.swift */; }; + C1FB428F217921D600FAB378 /* PumpManagerUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1FB428E217921D600FAB378 /* PumpManagerUI.swift */; }; + C1FB4290217922A100FAB378 /* PumpManagerUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1FB428E217921D600FAB378 /* PumpManagerUI.swift */; }; C9886AE51E5B2FAD00473BB8 /* gallery.ckcomplication in Resources */ = {isa = PBXBuildFile; fileRef = C9886AE41E5B2FAD00473BB8 /* gallery.ckcomplication */; }; /* End PBXBuildFile section */ @@ -522,11 +519,8 @@ 43785EA32122774B0057DED1 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Intents.strings; sourceTree = ""; }; 4379CFEF21112CF700AADC79 /* ShareClientUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ShareClientUI.framework; path = Carthage/Build/iOS/ShareClientUI.framework; sourceTree = SOURCE_ROOT; }; 437AFEE6203688CF008C4892 /* LoopKitUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LoopKitUI.framework; path = Carthage/Build/iOS/LoopKitUI.framework; sourceTree = ""; }; - 437CEEBB1CD6DE6A003C8C80 /* BaseHUDView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseHUDView.swift; sourceTree = ""; }; 437CEEBD1CD6E0CB003C8C80 /* LoopCompletionHUDView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoopCompletionHUDView.swift; sourceTree = ""; }; 437CEEBF1CD6FCD8003C8C80 /* BasalRateHUDView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BasalRateHUDView.swift; sourceTree = ""; }; - 437CEEC71CD84CBB003C8C80 /* ReservoirVolumeHUDView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReservoirVolumeHUDView.swift; sourceTree = ""; }; - 437CEEC91CD84DB7003C8C80 /* BatteryLevelHUDView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BatteryLevelHUDView.swift; sourceTree = ""; }; 437CEEE31CDE5C0A003C8C80 /* UIImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImage.swift; sourceTree = ""; }; 437D9BA11D7B5203007245E8 /* Loop.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Loop.xcconfig; sourceTree = ""; }; 437D9BA21D7BC977007245E8 /* PredictionTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PredictionTableViewController.swift; sourceTree = ""; }; @@ -566,8 +560,6 @@ 43BFF0BB1E45C80600FF19A9 /* UIColor+Loop.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColor+Loop.swift"; sourceTree = ""; }; 43BFF0BE1E45C8EA00FF19A9 /* UIColor+Widget.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColor+Widget.swift"; sourceTree = ""; }; 43BFF0C31E4659E700FF19A9 /* UIColor+HIG.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColor+HIG.swift"; sourceTree = ""; }; - 43BFF0C81E465B0A00FF19A9 /* StateColorPalette.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StateColorPalette.swift; sourceTree = ""; }; - 43BFF0CA1E466C0900FF19A9 /* StateColorPalette.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StateColorPalette.swift; sourceTree = ""; }; 43BFF0CC1E466C8400FF19A9 /* StateColorPalette.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StateColorPalette.swift; sourceTree = ""; }; 43C094491CACCC73001F6403 /* NotificationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = ""; }; 43C246A71D89990F0031F8D1 /* Crypto.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Crypto.framework; path = Carthage/Build/iOS/Crypto.framework; sourceTree = SOURCE_ROOT; }; @@ -590,7 +582,6 @@ 43DBF0581C93F73800B3C386 /* CarbEntryTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CarbEntryTableViewController.swift; sourceTree = ""; }; 43DE92581C5479E4001FFDE1 /* CarbEntryUserInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CarbEntryUserInfo.swift; sourceTree = ""; }; 43DE92601C555C26001FFDE1 /* AbsorptionTimeType+CarbKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AbsorptionTimeType+CarbKit.swift"; sourceTree = ""; }; - 43E0F0A41E46D1670064F7CE /* LevelHUDView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LevelHUDView.swift; sourceTree = ""; }; 43E2D8C71D208D5B004DA55F /* KeychainManager+Loop.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "KeychainManager+Loop.swift"; sourceTree = ""; }; 43E2D8C91D20B9E7004DA55F /* KeychainManagerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeychainManagerTests.swift; sourceTree = ""; }; 43E2D8D11D20BF42004DA55F /* DoseMathTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DoseMathTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -620,7 +611,6 @@ 43F64DD81D9C92C900D24DC6 /* TitleSubtitleTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TitleSubtitleTableViewCell.swift; sourceTree = ""; }; 43F78D251C8FC000002152D1 /* DoseMath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DoseMath.swift; sourceTree = ""; }; 43F78D4B1C914197002152D1 /* LoopKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LoopKit.framework; path = Carthage/Build/iOS/LoopKit.framework; sourceTree = SOURCE_ROOT; }; - 43FBEDD71D73843700B21F22 /* LevelMaskView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LevelMaskView.swift; sourceTree = ""; }; 4D3B40021D4A9DFE00BC6334 /* G4ShareSpy.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = G4ShareSpy.framework; path = Carthage/Build/iOS/G4ShareSpy.framework; sourceTree = SOURCE_ROOT; }; 4F08DE7C1E7BB6E5006741EA /* ChartAxisValueDoubleLog.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartAxisValueDoubleLog.swift; sourceTree = ""; }; 4F08DE7D1E7BB6E5006741EA /* ChartAxisValueDoubleUnit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartAxisValueDoubleUnit.swift; sourceTree = ""; }; @@ -633,7 +623,7 @@ 4F2C15801E0495B200E160D4 /* WatchContext+WatchApp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "WatchContext+WatchApp.swift"; sourceTree = ""; }; 4F2C15921E09BF2C00E160D4 /* HUDView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HUDView.swift; sourceTree = ""; }; 4F2C15941E09BF3C00E160D4 /* HUDView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = HUDView.xib; sourceTree = ""; }; - 4F2C15961E09E94E00E160D4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 4F2C15961E09E94E00E160D4 /* HUDAssets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = HUDAssets.xcassets; sourceTree = ""; }; 4F526D5E1DF2459000A04910 /* HKUnit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = ""; }; 4F526D601DF8D9A900A04910 /* NetBasal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetBasal.swift; sourceTree = ""; }; 4F6663931E905FD2009E74FC /* ChartColorPalette+Loop.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ChartColorPalette+Loop.swift"; sourceTree = ""; }; @@ -840,6 +830,8 @@ C1C6591B1E1B1FDA0025CC58 /* recommend_temp_basal_dropping_then_rising.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = recommend_temp_basal_dropping_then_rising.json; sourceTree = ""; }; C1CB13A8213EE35800F9EEDA /* OmniKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = OmniKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C1CB13AA213EE35800F9EEDA /* OmniKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = OmniKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C1FB428B217806A300FAB378 /* StateColorPalette.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StateColorPalette.swift; sourceTree = ""; }; + C1FB428E217921D600FAB378 /* PumpManagerUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PumpManagerUI.swift; sourceTree = ""; }; C9886AE41E5B2FAD00473BB8 /* gallery.ckcomplication */ = {isa = PBXFileReference; lastKnownFileType = folder; path = gallery.ckcomplication; sourceTree = ""; }; /* End PBXFileReference section */ @@ -1135,7 +1127,7 @@ 438172D81F4E9E37003C3328 /* NewPumpEvent.swift */, 43CEE6E51E56AFD400CB9116 /* NightscoutUploader.swift */, 43DACFFF20A2736F000F8529 /* PersistedPumpEvent.swift */, - 43BFF0CA1E466C0900FF19A9 /* StateColorPalette.swift */, + C1FB428B217806A300FAB378 /* StateColorPalette.swift */, 43F41C361D3BF32400C11ED6 /* UIAlertController.swift */, 43BFF0BB1E45C80600FF19A9 /* UIColor+Loop.swift */, 437CEEE31CDE5C0A003C8C80 /* UIImage.swift */, @@ -1244,7 +1236,7 @@ 4F75288D1DFE1DC600C322D6 /* LoopUI.h */, 4F75288E1DFE1DC600C322D6 /* Info.plist */, 4F2C15941E09BF3C00E160D4 /* HUDView.xib */, - 4F2C15961E09E94E00E160D4 /* Assets.xcassets */, + 4F2C15961E09E94E00E160D4 /* HUDAssets.xcassets */, ); path = LoopUI; sourceTree = ""; @@ -1254,19 +1246,14 @@ children = ( 437CEEBF1CD6FCD8003C8C80 /* BasalRateHUDView.swift */, 43B371851CE583890013C5A6 /* BasalStateView.swift */, - 437CEEBB1CD6DE6A003C8C80 /* BaseHUDView.swift */, - 437CEEC91CD84DB7003C8C80 /* BatteryLevelHUDView.swift */, 4313EDDF1D8A6BF90060FA79 /* ChartContainerView.swift */, 4369618F1F19C86400447E89 /* ChartPointsContextFillLayer.swift */, 4F08DE831E7BB70B006741EA /* ChartPointsScatterDownTrianglesLayer.swift */, 4F08DE841E7BB70B006741EA /* ChartPointsTouchHighlightLayerViewCache.swift */, 4337615E1D52F487004A3647 /* GlucoseHUDView.swift */, 4F2C15921E09BF2C00E160D4 /* HUDView.swift */, - 43E0F0A41E46D1670064F7CE /* LevelHUDView.swift */, - 43FBEDD71D73843700B21F22 /* LevelMaskView.swift */, 437CEEBD1CD6E0CB003C8C80 /* LoopCompletionHUDView.swift */, 438DADC71CDE8F8B007697A5 /* LoopStateView.swift */, - 437CEEC71CD84CBB003C8C80 /* ReservoirVolumeHUDView.swift */, ); path = Views; sourceTree = ""; @@ -1278,7 +1265,6 @@ 4F08DE7D1E7BB6E5006741EA /* ChartAxisValueDoubleUnit.swift */, 4FB76FCD1E8C835D00B39636 /* ChartColorPalette.swift */, 4326BA631F3A44D9007CCAD4 /* ChartLineModel.swift */, - 43BFF0C81E465B0A00FF19A9 /* StateColorPalette.swift */, ); path = Models; sourceTree = ""; @@ -1343,6 +1329,7 @@ 4FF4D0FF1E18374700846527 /* WatchContext.swift */, 4F11D3C120DD80B3006E072C /* WatchHistoricalGlucose.swift */, 4F7E8AC620E2AC0300AEA65E /* WatchPredictedGlucose.swift */, + C1FB428E217921D600FAB378 /* PumpManagerUI.swift */, ); path = Models; sourceTree = ""; @@ -1769,7 +1756,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 4F2C15971E09E94E00E160D4 /* Assets.xcassets in Resources */, + 4F2C15971E09E94E00E160D4 /* HUDAssets.xcassets in Resources */, 7D70764A1FE06EE1004AC8EA /* Localizable.strings in Resources */, 7D7076451FE06EE0004AC8EA /* InfoPlist.strings in Resources */, 4F2C15951E09BF3C00E160D4 /* HUDView.xib in Resources */, @@ -1876,6 +1863,7 @@ 4F2C15821E074FC600E160D4 /* NSTimeInterval.swift in Sources */, 4311FB9B1F37FE1B00D4C0A7 /* TitleSubtitleTextFieldTableViewCell.swift in Sources */, 430DA58E1D4AEC230097D1CA /* NSBundle.swift in Sources */, + C1FB428F217921D600FAB378 /* PumpManagerUI.swift in Sources */, 43C513191E864C4E001547C7 /* GlucoseRangeSchedule.swift in Sources */, 43A51E1F1EB6D62A000736CC /* CarbAbsorptionViewController.swift in Sources */, 43776F901B8022E90074EA36 /* AppDelegate.swift in Sources */, @@ -1883,7 +1871,6 @@ 430B29932041F5B300BA9F93 /* UserDefaults+Loop.swift in Sources */, 4341F4EB1EDB92AC001C936B /* LogglyService.swift in Sources */, 43CE7CDE1CA8B63E003CC1B0 /* Data.swift in Sources */, - 43BFF0CB1E466C0900FF19A9 /* StateColorPalette.swift in Sources */, 439A7942211F631C0041B75F /* RootNavigationController.swift in Sources */, 4F11D3C020DCBEEC006E072C /* GlucoseBackfillRequestUserInfo.swift in Sources */, 43F5C2DB1B92A5E1003EB13D /* SettingsTableViewController.swift in Sources */, @@ -1932,6 +1919,7 @@ 43DAD00020A2736F000F8529 /* PersistedPumpEvent.swift in Sources */, 438849EC1D29EC34003B3F23 /* AmplitudeService.swift in Sources */, 43E93FB61E469A4000EAB8DB /* NumberFormatter.swift in Sources */, + C1FB428C217806A400FAB378 /* StateColorPalette.swift in Sources */, 4F08DE8F1E7BB871006741EA /* CollectionType+Loop.swift in Sources */, 435400341C9F878D00D5819C /* SetBolusUserInfo.swift in Sources */, 437D9BA31D7BC977007245E8 /* PredictionTableViewController.swift in Sources */, @@ -2060,7 +2048,9 @@ 4FB76FBA1E8C42CE00B39636 /* UIColor.swift in Sources */, 4F2C15831E0757E600E160D4 /* HKUnit.swift in Sources */, 430B29902041F57000BA9F93 /* GlucoseThreshold.swift in Sources */, + C1FB4290217922A100FAB378 /* PumpManagerUI.swift in Sources */, 434B2887206B4F07000EE07B /* WalshInsulinModel.swift in Sources */, + C1FB428D21791D2500FAB378 /* PumpManager.swift in Sources */, 43E93FB51E4675E800EAB8DB /* NumberFormatter.swift in Sources */, 43BFF0CD1E466C8400FF19A9 /* StateColorPalette.swift in Sources */, 430B29912041F57200BA9F93 /* LoopSettings.swift in Sources */, @@ -2080,7 +2070,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 4F20AE621E6B879C00D07A06 /* ReservoirVolumeHUDView.swift in Sources */, 4FB76FB91E8C42B000B39636 /* CollectionType.swift in Sources */, 7D23667D21250C7E0028B67D /* LocalizedString.swift in Sources */, 4FF4D0F91E17268800846527 /* IdentifiableClass.swift in Sources */, @@ -2100,18 +2089,13 @@ 43F1C31A1F5DC87700395429 /* ChartPoint.swift in Sources */, 4F7528A11DFE200B00C322D6 /* BasalStateView.swift in Sources */, 4F20AE631E6B87B100D07A06 /* ChartContainerView.swift in Sources */, - 4F7528A21DFE200B00C322D6 /* LevelMaskView.swift in Sources */, 43BFF0C61E465A4400FF19A9 /* UIColor+HIG.swift in Sources */, 4F7528A01DFE1F9D00C322D6 /* LoopStateView.swift in Sources */, 4FB76FCE1E8C835D00B39636 /* ChartColorPalette.swift in Sources */, 4FB76FB51E8C41E200B39636 /* ChartPointsScatterDownTrianglesLayer.swift in Sources */, 4F75289A1DFE1F6000C322D6 /* BasalRateHUDView.swift in Sources */, - 4F75289B1DFE1F6000C322D6 /* BatteryLevelHUDView.swift in Sources */, 4F75289C1DFE1F6000C322D6 /* GlucoseHUDView.swift in Sources */, 4FB76FB81E8C429D00B39636 /* CGPoint.swift in Sources */, - 4F75289D1DFE1F6000C322D6 /* BaseHUDView.swift in Sources */, - 43BFF0C91E465B0A00FF19A9 /* StateColorPalette.swift in Sources */, - 43E0F0A51E46D1670064F7CE /* LevelHUDView.swift in Sources */, 4F75289E1DFE1F6000C322D6 /* LoopCompletionHUDView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -2631,7 +2615,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Loop/Loop.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = Loop/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; "OTHER_SWIFT_FLAGS[sdk=iphonesimulator*]" = "-D IOS_SIMULATOR"; @@ -2648,7 +2632,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Loop/Loop.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = Loop/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER)"; @@ -2664,7 +2648,7 @@ CODE_SIGN_ENTITLEMENTS = "WatchApp Extension/WatchApp Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/watchOS"; INFOPLIST_FILE = "WatchApp Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; @@ -2684,7 +2668,7 @@ CODE_SIGN_ENTITLEMENTS = "WatchApp Extension/WatchApp Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/watchOS"; INFOPLIST_FILE = "WatchApp Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; @@ -2704,7 +2688,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = ""; IBSC_MODULE = WatchApp_Extension; INFOPLIST_FILE = WatchApp/Info.plist; @@ -2725,7 +2709,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = ""; IBSC_MODULE = WatchApp_Extension; INFOPLIST_FILE = WatchApp/Info.plist; @@ -2804,7 +2788,7 @@ CODE_SIGN_ENTITLEMENTS = "Loop Status Extension/Loop Status Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = "Loop Status Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).statuswidget"; @@ -2823,7 +2807,7 @@ CODE_SIGN_ENTITLEMENTS = "Loop Status Extension/Loop Status Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = "Loop Status Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).statuswidget"; diff --git a/Loop/Extensions/StateColorPalette.swift b/Loop/Extensions/StateColorPalette.swift deleted file mode 100644 index c4e67ba9c4..0000000000 --- a/Loop/Extensions/StateColorPalette.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// StateColorPalette.swift -// Loop -// -// Copyright © 2017 LoopKit Authors. All rights reserved. -// - -import LoopUI - -extension StateColorPalette { - static let loopStatus = StateColorPalette(unknown: .unknownColor, normal: .freshColor, warning: .agingColor, error: .staleColor) - - static let cgmStatus = loopStatus - - static let pumpStatus = StateColorPalette(unknown: .unknownColor, normal: .pumpStatusNormal, warning: .agingColor, error: .staleColor) -} diff --git a/Loop/Extensions/UIImage.swift b/Loop/Extensions/UIImage.swift index 74103bfea5..4508689393 100644 --- a/Loop/Extensions/UIImage.swift +++ b/Loop/Extensions/UIImage.swift @@ -31,14 +31,6 @@ extension UIImage { return suffix } - static func batteryHUDImageWithLevel(_ level: Double?) -> UIImage? { - return UIImage(named: "battery_\(imageSuffixForLevel(level))") - } - - static func reservoirHUDImageWithLevel(_ level: Double?) -> UIImage? { - return UIImage(named: "reservoir_\(imageSuffixForLevel(level))") - } - static func preMealImage(selected: Bool) -> UIImage? { return UIImage(named: selected ? "Pre-Meal Selected" : "Pre-Meal") } diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index 67904a360b..2ac72c9e64 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -23,6 +23,8 @@ final class DeviceDataManager { } setupPump() + + NotificationCenter.default.post(name: .PumpManagerChanged, object: self, userInfo: nil) UserDefaults.appGroup.pumpManager = pumpManager } @@ -400,6 +402,7 @@ extension DeviceDataManager: CustomDebugStringConvertible { extension Notification.Name { static let PumpSuspendStateChanged = Notification.Name(rawValue: "com.loopKit.notification.PumpSuspendStateChanged") + static let PumpManagerChanged = Notification.Name(rawValue: "com.loopKit.notification.PumpManagerChanged") } extension DeviceDataManager { diff --git a/Loop/Managers/StatusExtensionDataManager.swift b/Loop/Managers/StatusExtensionDataManager.swift index 8f451cc64f..cdd3feca3e 100644 --- a/Loop/Managers/StatusExtensionDataManager.swift +++ b/Loop/Managers/StatusExtensionDataManager.swift @@ -111,6 +111,10 @@ final class StatusExtensionDataManager { isLocal: sensorInfo.isLocal ) } + + if let pumpManager = dataManager.pumpManager { + context.pumpManagerHUDViewsContext = PumpManagerHUDViewsContext(pumpManagerUI: pumpManager) + } completionHandler(context) } diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index 44f2567c94..878505d456 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -83,7 +83,13 @@ final class StatusTableViewController: ChartsTableViewController { self.reloadData(animated: true) } } + }, + notificationCenter.addObserver(forName: .PumpManagerChanged, object: deviceManager, queue: OperationQueue.main) { [weak self] (notification: Notification) in + DispatchQueue.main.async { + self?.configurePumpManagerHUDViews() + } } + ] if let gestureRecognizer = charts.gestureRecognizer { @@ -435,18 +441,6 @@ final class StatusTableViewController: ChartsTableViewController { sensor: self.deviceManager.cgmManager?.sensorState ) } - - // Reservoir HUD - if let reservoir = lastReservoirValue { - if let capacity = self.deviceManager.pumpManager?.pumpReservoirCapacity { - hudView.reservoirVolumeHUD.reservoirLevel = min(1, max(0, reservoir.unitVolume / capacity)) - } - - hudView.reservoirVolumeHUD.setReservoirVolume(volume: reservoir.unitVolume, at: reservoir.startDate) - } - - // Battery HUD - hudView.batteryHUD.batteryLevel = self.deviceManager.pumpManager?.status.pumpBatteryChargeRemaining ?? UserDefaults.appGroup.statusExtensionContext?.batteryPercentage } // Show/hide the table view rows @@ -1069,19 +1063,36 @@ final class StatusTableViewController: ChartsTableViewController { if deviceManager.cgmManager?.appURL != nil { hudView.glucoseHUD.accessibilityHint = NSLocalizedString("Launches CGM app", comment: "Glucose HUD accessibility hint") } - + + configurePumpManagerHUDViews() + hudView.loopCompletionHUD.stateColors = .loopStatus hudView.glucoseHUD.stateColors = .cgmStatus hudView.glucoseHUD.tintColor = .glucoseTintColor hudView.basalRateHUD.tintColor = .doseTintColor - hudView.reservoirVolumeHUD.stateColors = .pumpStatus - hudView.batteryHUD.stateColors = .pumpStatus refreshContext.update(with: .status) self.log.debug("[reloadData] after hudView loaded") reloadData() } } + + private func configurePumpManagerHUDViews() { + if let pumpManager = deviceManager.pumpManager, + let hudView = hudView + { + let views = pumpManager.hudViews() + for view in views { + let hudTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(hudViewTapped(_:))) + view.addGestureRecognizer(hudTapGestureRecognizer) + + if let levelHUDView = view as? LevelHUDView { + levelHUDView.stateColors = .pumpStatus + } + } + hudView.setAdditionalHUDViews(views) + } + } @objc private func showLastError(_: Any) { // First, check whether we have a device error after the most recent completion date @@ -1099,6 +1110,20 @@ final class StatusTableViewController: ChartsTableViewController { UIApplication.shared.open(url) } } + + @objc private func hudViewTapped(_ sender: UIGestureRecognizer) { + if let hudSubView = sender.view as? BaseHUDView, + let pumpManager = deviceManager.pumpManager, + let action = pumpManager.hudTapAction(identifier: hudSubView.hudViewIdentifier) + { + switch action { + case .presentViewController(let vc): + self.present(vc, animated: true, completion: nil) + case .openAppURL(let url): + UIApplication.shared.open(url) + } + } + } } extension UIAlertController { diff --git a/LoopUI/Assets.xcassets/Contents.json b/LoopUI/HUDAssets.xcassets/Contents.json similarity index 100% rename from LoopUI/Assets.xcassets/Contents.json rename to LoopUI/HUDAssets.xcassets/Contents.json diff --git a/LoopUI/Assets.xcassets/battery/Contents.json b/LoopUI/HUDAssets.xcassets/battery/Contents.json similarity index 100% rename from LoopUI/Assets.xcassets/battery/Contents.json rename to LoopUI/HUDAssets.xcassets/battery/Contents.json diff --git a/LoopUI/Assets.xcassets/battery/battery.imageset/Contents.json b/LoopUI/HUDAssets.xcassets/battery/battery.imageset/Contents.json similarity index 100% rename from LoopUI/Assets.xcassets/battery/battery.imageset/Contents.json rename to LoopUI/HUDAssets.xcassets/battery/battery.imageset/Contents.json diff --git a/LoopUI/Assets.xcassets/battery/battery.imageset/battery.pdf b/LoopUI/HUDAssets.xcassets/battery/battery.imageset/battery.pdf similarity index 100% rename from LoopUI/Assets.xcassets/battery/battery.imageset/battery.pdf rename to LoopUI/HUDAssets.xcassets/battery/battery.imageset/battery.pdf diff --git a/LoopUI/Assets.xcassets/battery/battery_mask.imageset/Contents.json b/LoopUI/HUDAssets.xcassets/battery/battery_mask.imageset/Contents.json similarity index 100% rename from LoopUI/Assets.xcassets/battery/battery_mask.imageset/Contents.json rename to LoopUI/HUDAssets.xcassets/battery/battery_mask.imageset/Contents.json diff --git a/LoopUI/Assets.xcassets/battery/battery_mask.imageset/battery_mask.pdf b/LoopUI/HUDAssets.xcassets/battery/battery_mask.imageset/battery_mask.pdf similarity index 100% rename from LoopUI/Assets.xcassets/battery/battery_mask.imageset/battery_mask.pdf rename to LoopUI/HUDAssets.xcassets/battery/battery_mask.imageset/battery_mask.pdf diff --git a/LoopUI/Assets.xcassets/reservoir/Contents.json b/LoopUI/HUDAssets.xcassets/reservoir/Contents.json similarity index 100% rename from LoopUI/Assets.xcassets/reservoir/Contents.json rename to LoopUI/HUDAssets.xcassets/reservoir/Contents.json diff --git a/LoopUI/Assets.xcassets/reservoir/reservoir.imageset/Contents.json b/LoopUI/HUDAssets.xcassets/reservoir/reservoir.imageset/Contents.json similarity index 100% rename from LoopUI/Assets.xcassets/reservoir/reservoir.imageset/Contents.json rename to LoopUI/HUDAssets.xcassets/reservoir/reservoir.imageset/Contents.json diff --git a/LoopUI/Assets.xcassets/reservoir/reservoir.imageset/reservoir.pdf b/LoopUI/HUDAssets.xcassets/reservoir/reservoir.imageset/reservoir.pdf similarity index 100% rename from LoopUI/Assets.xcassets/reservoir/reservoir.imageset/reservoir.pdf rename to LoopUI/HUDAssets.xcassets/reservoir/reservoir.imageset/reservoir.pdf diff --git a/LoopUI/Assets.xcassets/reservoir/reservoir_mask.imageset/Contents.json b/LoopUI/HUDAssets.xcassets/reservoir/reservoir_mask.imageset/Contents.json similarity index 100% rename from LoopUI/Assets.xcassets/reservoir/reservoir_mask.imageset/Contents.json rename to LoopUI/HUDAssets.xcassets/reservoir/reservoir_mask.imageset/Contents.json diff --git a/LoopUI/Assets.xcassets/reservoir/reservoir_mask.imageset/reservoir_mask.pdf b/LoopUI/HUDAssets.xcassets/reservoir/reservoir_mask.imageset/reservoir_mask.pdf similarity index 100% rename from LoopUI/Assets.xcassets/reservoir/reservoir_mask.imageset/reservoir_mask.pdf rename to LoopUI/HUDAssets.xcassets/reservoir/reservoir_mask.imageset/reservoir_mask.pdf diff --git a/LoopUI/HUDView.xib b/LoopUI/HUDView.xib index 919a91a921..ee27795580 100644 --- a/LoopUI/HUDView.xib +++ b/LoopUI/HUDView.xib @@ -1,22 +1,19 @@ - + - - + - - @@ -24,16 +21,16 @@ - + - + @@ -64,28 +61,28 @@ - + - + - + @@ -163,130 +160,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/LoopUI/Models/StateColorPalette.swift b/LoopUI/Models/StateColorPalette.swift deleted file mode 100644 index 20052f10b2..0000000000 --- a/LoopUI/Models/StateColorPalette.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// StateColorPalette.swift -// Loop -// -// Copyright © 2017 LoopKit Authors. All rights reserved. -// - -import UIKit - - -/// A collection of colors for displaying state -public struct StateColorPalette { - public let unknown: UIColor - public let normal: UIColor - public let warning: UIColor - public let error: UIColor - - public init(unknown: UIColor, normal: UIColor, warning: UIColor, error: UIColor) { - self.unknown = unknown - self.normal = normal - self.warning = warning - self.error = error - } -} diff --git a/LoopUI/Views/BasalRateHUDView.swift b/LoopUI/Views/BasalRateHUDView.swift index 0c44579a5e..545ec1bf01 100644 --- a/LoopUI/Views/BasalRateHUDView.swift +++ b/LoopUI/Views/BasalRateHUDView.swift @@ -7,7 +7,7 @@ // import UIKit - +import LoopKitUI public final class BasalRateHUDView: BaseHUDView { diff --git a/LoopUI/Views/BaseHUDView.swift b/LoopUI/Views/BaseHUDView.swift deleted file mode 100644 index a0d2ad853e..0000000000 --- a/LoopUI/Views/BaseHUDView.swift +++ /dev/null @@ -1,19 +0,0 @@ -// -// HUDView.swift -// Naterade -// -// Created by Nathan Racklyeft on 5/1/16. -// Copyright © 2016 Nathan Racklyeft. All rights reserved. -// - -import UIKit - -public class BaseHUDView: UIView { - - @IBOutlet weak var caption: UILabel! { - didSet { - caption?.text = "—" - } - } - -} diff --git a/LoopUI/Views/BatteryLevelHUDView.swift b/LoopUI/Views/BatteryLevelHUDView.swift deleted file mode 100644 index e200c54530..0000000000 --- a/LoopUI/Views/BatteryLevelHUDView.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// BatteryLevelHUDView.swift -// Naterade -// -// Created by Nathan Racklyeft on 5/2/16. -// Copyright © 2016 Nathan Racklyeft. All rights reserved. -// - -import UIKit - - -public final class BatteryLevelHUDView: LevelHUDView { - - private lazy var numberFormatter: NumberFormatter = { - let formatter = NumberFormatter() - formatter.numberStyle = .percent - - return formatter - }() - - public var batteryLevel: Double? { - didSet { - if let value = batteryLevel, let level = numberFormatter.string(from: value) { - caption.text = level - accessibilityValue = level - } else { - caption.text = nil - } - - level = batteryLevel - } - } - -} diff --git a/LoopUI/Views/GlucoseHUDView.swift b/LoopUI/Views/GlucoseHUDView.swift index 9a7acf26c9..81ba445500 100644 --- a/LoopUI/Views/GlucoseHUDView.swift +++ b/LoopUI/Views/GlucoseHUDView.swift @@ -9,7 +9,7 @@ import UIKit import HealthKit import LoopKit - +import LoopKitUI public final class GlucoseHUDView: BaseHUDView { diff --git a/LoopUI/Views/HUDView.swift b/LoopUI/Views/HUDView.swift index af89b39068..bdcd8e06be 100644 --- a/LoopUI/Views/HUDView.swift +++ b/LoopUI/Views/HUDView.swift @@ -7,16 +7,17 @@ // import UIKit +import LoopKitUI public class HUDView: UIView, NibLoadable { @IBOutlet public weak var loopCompletionHUD: LoopCompletionHUDView! @IBOutlet public weak var glucoseHUD: GlucoseHUDView! @IBOutlet public weak var basalRateHUD: BasalRateHUDView! - @IBOutlet public weak var reservoirVolumeHUD: ReservoirVolumeHUDView! - @IBOutlet public weak var batteryHUD: BatteryLevelHUDView! + + private var stackView: UIStackView! func setup() { - let stackView = HUDView.nib().instantiate(withOwner: self, options: nil)[0] as! UIStackView + stackView = (HUDView.nib().instantiate(withOwner: self, options: nil)[0] as! UIStackView) self.addSubview(stackView) // Use AutoLayout to have the stack view fill its entire container. @@ -26,6 +27,17 @@ public class HUDView: UIView, NibLoadable { let heightConstraint = NSLayoutConstraint(item: stackView, attribute: .height, relatedBy: .equal, toItem: self, attribute: .height, multiplier: 1, constant: 0) self.addConstraints([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint]) } + + public func setAdditionalHUDViews(_ additionalViews: [BaseHUDView]) { + let standardViews: [UIView] = [loopCompletionHUD, glucoseHUD, basalRateHUD] + let nonStandardHudViews = stackView.subviews.filter { !standardViews.contains($0) } + for view in nonStandardHudViews { + view.removeFromSuperview() + } + for view in additionalViews { + stackView.addArrangedSubview(view) + } + } public override init(frame: CGRect) { super.init(frame: frame) diff --git a/LoopUI/Views/LevelHUDView.swift b/LoopUI/Views/LevelHUDView.swift deleted file mode 100644 index aec0371fd8..0000000000 --- a/LoopUI/Views/LevelHUDView.swift +++ /dev/null @@ -1,52 +0,0 @@ -// -// LevelHUDView.swift -// Loop -// -// Created by Nate Racklyeft on 2/4/17. -// Copyright © 2017 LoopKit Authors. All rights reserved. -// - -import UIKit - -public class LevelHUDView: BaseHUDView { - - @IBOutlet private weak var levelMaskView: LevelMaskView! - - override public func awakeFromNib() { - super.awakeFromNib() - - updateColor() - - accessibilityValue = LocalizedString("Unknown", comment: "Accessibility value for an unknown value") - } - - public var stateColors: StateColorPalette? { - didSet { - updateColor() - } - } - - private func updateColor() { - levelMaskView.tintColor = nil - - switch level { - case .none: - tintColor = stateColors?.unknown - case let x? where x > 0.25: - tintColor = stateColors?.normal - case let x? where x > 0.10: - tintColor = stateColors?.normal - levelMaskView.tintColor = stateColors?.warning - default: - tintColor = stateColors?.error - } - } - - internal var level: Double? { - didSet { - levelMaskView.value = level ?? 1.0 - updateColor() - } - } - -} diff --git a/LoopUI/Views/LevelMaskView.swift b/LoopUI/Views/LevelMaskView.swift deleted file mode 100644 index ec7840fd71..0000000000 --- a/LoopUI/Views/LevelMaskView.swift +++ /dev/null @@ -1,85 +0,0 @@ -// -// LevelMaskView.swift -// Loop -// -// Created by Nate Racklyeft on 8/28/16. -// Copyright © 2016 Nathan Racklyeft. All rights reserved. -// - -import UIKit - -// Displays a variable-height level indicator, masked by an image. -// Inspired by https://github.com/carekit-apple/CareKit/blob/master/CareKit/CareCard/OCKHeartView.h - -public class LevelMaskView: UIView { - var firstDataUpdate = true - - var value: Double = 1.0 { - didSet { - animateFill(duration: firstDataUpdate ? 0 : 1.25) - firstDataUpdate = false - } - } - - @IBInspectable var maskImage: UIImage? { - didSet { - fillView?.removeFromSuperview() - mask?.removeFromSuperview() - maskImageView?.removeFromSuperview() - - guard let maskImage = maskImage else { return } - - mask = UIView() - maskImageView = UIImageView(image: maskImage) - maskImageView!.contentMode = .center - mask!.addSubview(maskImageView!) - - clipsToBounds = true - - fillView = UIView() - fillView!.backgroundColor = tintColor - addSubview(fillView!) - } - } - - private var fillView: UIView? - - private var maskImageView: UIView? - - override public func layoutSubviews() { - super.layoutSubviews() - - guard let maskImage = maskImage else { return } - - let maskImageSize = maskImage.size - - mask?.frame = CGRect(origin: .zero, size: maskImageSize) - mask?.center = CGPoint(x: bounds.midX, y: bounds.midY) - maskImageView?.frame = mask?.bounds ?? bounds - - if (fillView?.layer.animationKeys()?.count ?? 0) == 0 { - updateFillViewFrame() - } - } - - override public func tintColorDidChange() { - super.tintColorDidChange() - - fillView?.backgroundColor = tintColor - } - - private func animateFill(duration: TimeInterval) { - UIView.animate(withDuration: duration, delay: 0, options: .beginFromCurrentState, animations: { - self.updateFillViewFrame() - }, completion: nil) - } - - private func updateFillViewFrame() { - guard let maskViewFrame = mask?.frame else { return } - - var fillViewFrame = maskViewFrame - fillViewFrame.origin.y = maskViewFrame.maxY - fillViewFrame.size.height = -CGFloat(value) * maskViewFrame.height - fillView?.frame = fillViewFrame - } -} diff --git a/LoopUI/Views/LoopCompletionHUDView.swift b/LoopUI/Views/LoopCompletionHUDView.swift index 077f699998..04e54b69d2 100644 --- a/LoopUI/Views/LoopCompletionHUDView.swift +++ b/LoopUI/Views/LoopCompletionHUDView.swift @@ -7,6 +7,7 @@ // import UIKit +import LoopKitUI public final class LoopCompletionHUDView: BaseHUDView { diff --git a/LoopUI/Views/ReservoirVolumeHUDView.swift b/LoopUI/Views/ReservoirVolumeHUDView.swift deleted file mode 100644 index 6f57fe09d1..0000000000 --- a/LoopUI/Views/ReservoirVolumeHUDView.swift +++ /dev/null @@ -1,65 +0,0 @@ -// -// ReservoirVolumeHUDView.swift -// Naterade -// -// Created by Nathan Racklyeft on 5/2/16. -// Copyright © 2016 Nathan Racklyeft. All rights reserved. -// - -import UIKit - -public final class ReservoirVolumeHUDView: LevelHUDView { - - @IBOutlet private weak var volumeLabel: UILabel! - - override public func awakeFromNib() { - super.awakeFromNib() - - volumeLabel.isHidden = true - } - - public var reservoirLevel: Double? { - didSet { - level = reservoirLevel - - switch reservoirLevel { - case .none: - volumeLabel.isHidden = true - case let x? where x > 0.25: - volumeLabel.isHidden = true - case let x? where x > 0.10: - volumeLabel.textColor = tintColor - volumeLabel.isHidden = false - default: - volumeLabel.textColor = tintColor - volumeLabel.isHidden = false - } - } - } - - private lazy var timeFormatter: DateFormatter = { - let formatter = DateFormatter() - formatter.dateStyle = .none - formatter.timeStyle = .short - - return formatter - }() - - private lazy var numberFormatter: NumberFormatter = { - let formatter = NumberFormatter() - formatter.numberStyle = .decimal - formatter.maximumFractionDigits = 0 - - return formatter - }() - - public func setReservoirVolume(volume: Double, at date: Date) { - if let units = numberFormatter.string(from: volume) { - volumeLabel.text = String(format: LocalizedString("%@U", comment: "Format string for reservoir volume. (1: The localized volume)"), units) - let time = timeFormatter.string(from: date) - caption?.text = time - - accessibilityValue = String(format: LocalizedString("%1$@ units remaining at %2$@", comment: "Accessibility format string for (1: localized volume)(2: time)"), units, time) - } - } -} From b2a68e0096f9e83e62590c3e0254b21b03885fa2 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sun, 21 Oct 2018 23:28:45 -0500 Subject: [PATCH 14/56] Add missing file --- Loop/Extensions/StateColorPalette.swift | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Loop/Extensions/StateColorPalette.swift diff --git a/Loop/Extensions/StateColorPalette.swift b/Loop/Extensions/StateColorPalette.swift new file mode 100644 index 0000000000..e6f18b436a --- /dev/null +++ b/Loop/Extensions/StateColorPalette.swift @@ -0,0 +1,17 @@ +// +// StateColorPalette.swift +// Loop +// +// Copyright © 2017 LoopKit Authors. All rights reserved. +// + +import LoopUI +import LoopKitUI + +extension StateColorPalette { + static let loopStatus = StateColorPalette(unknown: .unknownColor, normal: .freshColor, warning: .agingColor, error: .staleColor) + + static let cgmStatus = loopStatus + + static let pumpStatus = StateColorPalette(unknown: .unknownColor, normal: .pumpStatusNormal, warning: .agingColor, error: .staleColor) +} From 63932d19dd5ec97dd5204c0944057e3f74ef49e6 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 22 Oct 2018 17:41:52 -0500 Subject: [PATCH 15/56] Update to LoopKit naming changes --- Common/Models/PumpManagerUI.swift | 2 +- Loop/View Controllers/StatusTableViewController.swift | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Common/Models/PumpManagerUI.swift b/Common/Models/PumpManagerUI.swift index a40c6c0c93..0f24ac7713 100644 --- a/Common/Models/PumpManagerUI.swift +++ b/Common/Models/PumpManagerUI.swift @@ -37,7 +37,7 @@ func PumpManagerHUDViewsFromRawValue(_ rawValue: [String: Any]) -> [BaseHUDView] return nil } - return Manager.instantiateHUDViews(rawValue: rawState) + return Manager.createHUDViews(rawValue: rawState) } extension PumpManagerUI { diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index 878505d456..aa6003b0ad 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -1081,7 +1081,7 @@ final class StatusTableViewController: ChartsTableViewController { if let pumpManager = deviceManager.pumpManager, let hudView = hudView { - let views = pumpManager.hudViews() + let views = pumpManager.createHUDViews() for view in views { let hudTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(hudViewTapped(_:))) view.addGestureRecognizer(hudTapGestureRecognizer) @@ -1114,10 +1114,10 @@ final class StatusTableViewController: ChartsTableViewController { @objc private func hudViewTapped(_ sender: UIGestureRecognizer) { if let hudSubView = sender.view as? BaseHUDView, let pumpManager = deviceManager.pumpManager, - let action = pumpManager.hudTapAction(identifier: hudSubView.hudViewIdentifier) + let action = pumpManager.didTapOnHudView(hudSubView) { switch action { - case .presentViewController(let vc): + case .showViewController(let vc): self.present(vc, animated: true, completion: nil) case .openAppURL(let url): UIApplication.shared.open(url) From 852409388c735b600d1feb789f47e59111b30a9d Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 23 Oct 2018 12:33:43 -0500 Subject: [PATCH 16/56] Push instead of present pumpmanager vended vc in response to HUD view tap --- .../StatusViewController.swift | 4 +--- .../StatusTableViewController.swift | 20 ++----------------- LoopUI/Views/GlucoseHUDView.swift | 7 +++---- LoopUI/Views/LoopCompletionHUDView.swift | 7 +++---- 4 files changed, 9 insertions(+), 29 deletions(-) diff --git a/Loop Status Extension/StatusViewController.swift b/Loop Status Extension/StatusViewController.swift index e6ed17244b..484786189f 100644 --- a/Loop Status Extension/StatusViewController.swift +++ b/Loop Status Extension/StatusViewController.swift @@ -191,9 +191,7 @@ class StatusViewController: UIViewController, NCWidgetProviding { if let hudViewsContext = context.pumpManagerHUDViewsContext, let hudViews = hudViewsContext.hudViews { for view in hudViews { - if let levelView = view as? LevelHUDView { - levelView.stateColors = .pumpStatus - } + view.stateColors = .pumpStatus } self.hudView.setAdditionalHUDViews(hudViews) } diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index aa6003b0ad..11375f6c1a 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -254,7 +254,6 @@ final class StatusTableViewController: ChartsTableViewController { reloading = true let reloadGroup = DispatchGroup() - var lastReservoirValue: ReservoirValue? var newRecommendedTempBasal: (recommendation: TempBasalRecommendation, date: Date)? var glucoseValues: [StoredGlucoseSample]? var predictedGlucoseValues: [GlucoseValue]? @@ -367,18 +366,6 @@ final class StatusTableViewController: ChartsTableViewController { reloadGroup.leave() } - - reloadGroup.enter() - deviceManager.loopManager.doseStore.getReservoirValues(since: Date(timeIntervalSinceNow: .minutes(-30)), limit: 1) { (result) in - switch result { - case .success(let values): - lastReservoirValue = values.first - case .failure: - retryContext.update(with: .insulin) - } - - reloadGroup.leave() - } } workoutMode = deviceManager.loopManager.settings.glucoseTargetRangeSchedule?.overrideEnabledForContext(.workout) @@ -1085,10 +1072,7 @@ final class StatusTableViewController: ChartsTableViewController { for view in views { let hudTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(hudViewTapped(_:))) view.addGestureRecognizer(hudTapGestureRecognizer) - - if let levelHUDView = view as? LevelHUDView { - levelHUDView.stateColors = .pumpStatus - } + view.stateColors = .pumpStatus } hudView.setAdditionalHUDViews(views) } @@ -1118,7 +1102,7 @@ final class StatusTableViewController: ChartsTableViewController { { switch action { case .showViewController(let vc): - self.present(vc, animated: true, completion: nil) + self.navigationController?.pushViewController(vc, animated: true) case .openAppURL(let url): UIApplication.shared.open(url) } diff --git a/LoopUI/Views/GlucoseHUDView.swift b/LoopUI/Views/GlucoseHUDView.swift index 81ba445500..6abfcfa716 100644 --- a/LoopUI/Views/GlucoseHUDView.swift +++ b/LoopUI/Views/GlucoseHUDView.swift @@ -43,10 +43,9 @@ public final class GlucoseHUDView: BaseHUDView { glucoseLabel.textColor = tintColor } - public var stateColors: StateColorPalette? { - didSet { - updateColor() - } + override public func stateColorsDidUpdate() { + super.stateColorsDidUpdate() + updateColor() } private func updateColor() { diff --git a/LoopUI/Views/LoopCompletionHUDView.swift b/LoopUI/Views/LoopCompletionHUDView.swift index 04e54b69d2..a32f0cfa73 100644 --- a/LoopUI/Views/LoopCompletionHUDView.swift +++ b/LoopUI/Views/LoopCompletionHUDView.swift @@ -65,10 +65,9 @@ public final class LoopCompletionHUDView: BaseHUDView { } } - public var stateColors: StateColorPalette? { - didSet { - updateTintColor() - } + override public func stateColorsDidUpdate() { + super.stateColorsDidUpdate() + updateTintColor() } private func updateTintColor() { From 37ef4aa7187a11266bfcb72900991effb1653e65 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 23 Oct 2018 16:32:21 -0500 Subject: [PATCH 17/56] Add prep_workspace.sh script --- prep_workspace.sh | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 prep_workspace.sh diff --git a/prep_workspace.sh b/prep_workspace.sh new file mode 100644 index 0000000000..6e3f409cf8 --- /dev/null +++ b/prep_workspace.sh @@ -0,0 +1,30 @@ +set -x +set -u +set -e + +echo "RUN WITH: sh prep_workspace.sh, in the loop-priv folder." + +# Uncomment if you have not already cloned the repo: +# git clone https://github.com/ps2/loop-priv.git +# cd loop-priv + +git checkout omnikit + +carthage bootstrap --use-submodules --no-build + +git reset HEAD + +cd Carthage/Checkouts +cd LoopKit; git fetch; git checkout pumpmanager-updates; git pull; cd .. +cd rileylink_ios; git fetch; git checkout omnipod-testing; git pull; cd .. +cd CGMBLEKit; git fetch; git checkout dev; git pull; cd .. +cd dexcom-share-client-swift; git fetch; git checkout carthage-recursive; git pull; cd .. +cd G4ShareSpy; git fetch; git checkout fix-cartfile; git pull; cd .. +cd ../.. +carthage build + +echo "Open Xcode, and select File -> New -> Workspace and create "Loop.xcworkspace" in the loop-priv directory just created. +Select File -> Add Files to "Loop"... to add the Loop.xcodeproj project. +Repeatedly select File -> Add Files to "Loop"... to add the .xcodeproj file for each project within the Carthage/Checkouts directory. +run 'carthage build' at the top level Loop directory +Build Loop in Xcode!" From 996bc3d78d961fefd81e3a7044f2de695f43062d Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Fri, 26 Oct 2018 16:33:58 -0500 Subject: [PATCH 18/56] HUDProvider updates --- Common/Models/PumpManagerUI.swift | 10 ++--- Common/Models/StatusExtensionContext.swift | 12 +++--- .../StatusViewController.swift | 3 +- Loop/Managers/DeviceDataManager.swift | 7 +++- .../Managers/StatusExtensionDataManager.swift | 4 +- .../StatusTableViewController.swift | 42 +++++++++++++++---- LoopUI/Views/BasalRateHUDView.swift | 4 ++ LoopUI/Views/GlucoseHUDView.swift | 4 ++ LoopUI/Views/HUDView.swift | 16 +++++-- LoopUI/Views/LoopCompletionHUDView.swift | 4 ++ 10 files changed, 79 insertions(+), 27 deletions(-) diff --git a/Common/Models/PumpManagerUI.swift b/Common/Models/PumpManagerUI.swift index 0f24ac7713..32b54f003f 100644 --- a/Common/Models/PumpManagerUI.swift +++ b/Common/Models/PumpManagerUI.swift @@ -31,7 +31,7 @@ func PumpManagerUITypeFromRawValue(_ rawValue: [String: Any]) -> PumpManagerUI.T } func PumpManagerHUDViewsFromRawValue(_ rawValue: [String: Any]) -> [BaseHUDView]? { - guard let rawState = rawValue["pumpManagerHUDViews"] as? PumpManagerUI.PumpManagerHUDViewsRawState, + guard let rawState = rawValue["hudProviderViews"] as? HUDProvider.HUDViewsRawState, let Manager = PumpManagerUITypeFromRawValue(rawValue) else { return nil @@ -40,11 +40,11 @@ func PumpManagerHUDViewsFromRawValue(_ rawValue: [String: Any]) -> [BaseHUDView] return Manager.createHUDViews(rawValue: rawState) } -extension PumpManagerUI { - var rawPumpManagerHUDViewsValue: [String: Any] { +extension HUDProvider { + var rawHUDProviderViewsValue: [String: Any] { return [ - "managerIdentifier": type(of: self).managerIdentifier, - "pumpManagerHUDViews": self.hudViewsRawState + "managerIdentifier": self.managerIdentifier, + "hudProviderViews": self.hudViewsRawState ] } } diff --git a/Common/Models/StatusExtensionContext.swift b/Common/Models/StatusExtensionContext.swift index e05ead7675..a02f5a33b4 100644 --- a/Common/Models/StatusExtensionContext.swift +++ b/Common/Models/StatusExtensionContext.swift @@ -156,15 +156,15 @@ struct PumpManagerHUDViewsContext: RawRepresentable { typealias RawValue = [String: Any] let hudViews: [BaseHUDView]? - let pumpManagerUI: PumpManagerUI? + let pumpManagerHUDProvider: HUDProvider? - init(pumpManagerUI: PumpManagerUI) { - self.pumpManagerUI = pumpManagerUI + init(pumpManagerHUDProvider: HUDProvider) { + self.pumpManagerHUDProvider = pumpManagerHUDProvider self.hudViews = nil } init?(rawValue: [String : Any]) { - pumpManagerUI = nil + pumpManagerHUDProvider = nil if let hudViews = PumpManagerHUDViewsFromRawValue(rawValue) { self.hudViews = hudViews } else { @@ -173,8 +173,8 @@ struct PumpManagerHUDViewsContext: RawRepresentable { } var rawValue: [String : Any] { - if let pumpManagerUI = pumpManagerUI { - return pumpManagerUI.rawPumpManagerHUDViewsValue + if let pumpManagerHUDProvider = pumpManagerHUDProvider { + return pumpManagerHUDProvider.rawHUDProviderViewsValue } else { return [:] } diff --git a/Loop Status Extension/StatusViewController.swift b/Loop Status Extension/StatusViewController.swift index 484786189f..d59d38b673 100644 --- a/Loop Status Extension/StatusViewController.swift +++ b/Loop Status Extension/StatusViewController.swift @@ -190,10 +190,11 @@ class StatusViewController: UIViewController, NCWidgetProviding { if let hudViewsContext = context.pumpManagerHUDViewsContext, let hudViews = hudViewsContext.hudViews { + self.hudView.removeNonStandardHUDViews() for view in hudViews { view.stateColors = .pumpStatus + self.hudView.addHUDView(view) } - self.hudView.setAdditionalHUDViews(hudViews) } if let netBasal = context.netBasal { diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index 2ac72c9e64..e50b628c71 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -29,6 +29,8 @@ final class DeviceDataManager { UserDefaults.appGroup.pumpManager = pumpManager } } + + var pumpManagerHUDProvider: HUDProvider? let logger = DiagnosticLogger.shared @@ -105,6 +107,7 @@ final class DeviceDataManager { if let pumpManager = pumpManager { self.pumpManagerStatus = pumpManager.status self.loopManager.doseStore.device = self.pumpManagerStatus?.device + self.pumpManagerHUDProvider = pumpManager.hudProvider() } // Proliferate PumpModel preferences to DoseStore @@ -386,8 +389,8 @@ extension DeviceDataManager: CustomDebugStringConvertible { Bundle.main.localizedNameAndVersion, "", "## DeviceDataManager", - "launchDate: \(launchDate)", - "lastError: \(String(describing: lastError))", + "* launchDate: \(launchDate)", + "* lastError: \(String(describing: lastError))", "", cgmManager != nil ? String(reflecting: cgmManager!) : "cgmManager: nil", "", diff --git a/Loop/Managers/StatusExtensionDataManager.swift b/Loop/Managers/StatusExtensionDataManager.swift index cdd3feca3e..e72aedaee0 100644 --- a/Loop/Managers/StatusExtensionDataManager.swift +++ b/Loop/Managers/StatusExtensionDataManager.swift @@ -112,8 +112,8 @@ final class StatusExtensionDataManager { ) } - if let pumpManager = dataManager.pumpManager { - context.pumpManagerHUDViewsContext = PumpManagerHUDViewsContext(pumpManagerUI: pumpManager) + if let pumpManagerHUDProvider = dataManager.pumpManagerHUDProvider { + context.pumpManagerHUDViewsContext = PumpManagerHUDViewsContext(pumpManagerHUDProvider: pumpManagerHUDProvider) } completionHandler(context) diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index 11375f6c1a..89fd83e883 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -1065,16 +1065,24 @@ final class StatusTableViewController: ChartsTableViewController { } private func configurePumpManagerHUDViews() { - if let pumpManager = deviceManager.pumpManager, + if var pumpManagerHUDProvider = deviceManager.pumpManagerHUDProvider, let hudView = hudView { - let views = pumpManager.createHUDViews() + let views = pumpManagerHUDProvider.createHUDViews() + hudView.removeNonStandardHUDViews() for view in views { - let hudTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(hudViewTapped(_:))) - view.addGestureRecognizer(hudTapGestureRecognizer) - view.stateColors = .pumpStatus + addViewToHUD(view) } - hudView.setAdditionalHUDViews(views) + pumpManagerHUDProvider.delegate = self + } + } + + private func addViewToHUD(_ view: BaseHUDView) { + if let hudView = hudView { + let hudTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(hudViewTapped(_:))) + view.addGestureRecognizer(hudTapGestureRecognizer) + view.stateColors = .pumpStatus + hudView.addHUDView(view) } } @@ -1097,8 +1105,8 @@ final class StatusTableViewController: ChartsTableViewController { @objc private func hudViewTapped(_ sender: UIGestureRecognizer) { if let hudSubView = sender.view as? BaseHUDView, - let pumpManager = deviceManager.pumpManager, - let action = pumpManager.didTapOnHudView(hudSubView) + let pumpManagerHUDProvider = deviceManager.pumpManagerHUDProvider, + let action = pumpManagerHUDProvider.didTapOnHudView(hudSubView) { switch action { case .showViewController(let vc): @@ -1110,6 +1118,24 @@ final class StatusTableViewController: ChartsTableViewController { } } +extension StatusTableViewController: HUDProviderDelegate { + func newHUDViewsAvailable(_ views: [BaseHUDView]) { + DispatchQueue.main.async { + for view in views { + view.isHidden = true + view.alpha = 0 + self.addViewToHUD(view) + } + UIView.animate(withDuration: 1, animations: { + for view in views { + view.isHidden = false + view.alpha = 1 + } + }) + } + } +} + extension UIAlertController { fileprivate convenience init(title: String, error: Error) { diff --git a/LoopUI/Views/BasalRateHUDView.swift b/LoopUI/Views/BasalRateHUDView.swift index 545ec1bf01..0a4283d9cd 100644 --- a/LoopUI/Views/BasalRateHUDView.swift +++ b/LoopUI/Views/BasalRateHUDView.swift @@ -10,6 +10,10 @@ import UIKit import LoopKitUI public final class BasalRateHUDView: BaseHUDView { + + override public var orderPriority: HUDViewOrderPriority { + return 3 + } @IBOutlet private weak var basalStateView: BasalStateView! diff --git a/LoopUI/Views/GlucoseHUDView.swift b/LoopUI/Views/GlucoseHUDView.swift index 6abfcfa716..802ee17de0 100644 --- a/LoopUI/Views/GlucoseHUDView.swift +++ b/LoopUI/Views/GlucoseHUDView.swift @@ -12,6 +12,10 @@ import LoopKit import LoopKitUI public final class GlucoseHUDView: BaseHUDView { + + override public var orderPriority: HUDViewOrderPriority { + return 2 + } @IBOutlet private weak var unitLabel: UILabel! { didSet { diff --git a/LoopUI/Views/HUDView.swift b/LoopUI/Views/HUDView.swift index bdcd8e06be..b874fb6eb1 100644 --- a/LoopUI/Views/HUDView.swift +++ b/LoopUI/Views/HUDView.swift @@ -28,15 +28,25 @@ public class HUDView: UIView, NibLoadable { self.addConstraints([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint]) } - public func setAdditionalHUDViews(_ additionalViews: [BaseHUDView]) { + public func removeNonStandardHUDViews() { let standardViews: [UIView] = [loopCompletionHUD, glucoseHUD, basalRateHUD] let nonStandardHudViews = stackView.subviews.filter { !standardViews.contains($0) } for view in nonStandardHudViews { view.removeFromSuperview() } - for view in additionalViews { - stackView.addArrangedSubview(view) + } + + public func addHUDView(_ viewToAdd: BaseHUDView) { + var insertIndex = 0 + for view in stackView.arrangedSubviews { + if let hudView = view as? BaseHUDView { + if viewToAdd.orderPriority <= hudView.orderPriority { + break + } + } + insertIndex += 1 } + stackView.insertArrangedSubview(viewToAdd, at: insertIndex) } public override init(frame: CGRect) { diff --git a/LoopUI/Views/LoopCompletionHUDView.swift b/LoopUI/Views/LoopCompletionHUDView.swift index a32f0cfa73..3fbdd1aff4 100644 --- a/LoopUI/Views/LoopCompletionHUDView.swift +++ b/LoopUI/Views/LoopCompletionHUDView.swift @@ -12,6 +12,10 @@ import LoopKitUI public final class LoopCompletionHUDView: BaseHUDView { @IBOutlet private weak var loopStateView: LoopStateView! + + override public var orderPriority: HUDViewOrderPriority { + return 1 + } enum Freshness { case fresh From c32cd8cc7e762f6c02705593f184ef50114bb9cd Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Wed, 31 Oct 2018 12:40:40 -0500 Subject: [PATCH 19/56] Fix hud clearing after removing pump manager. Show boluses that take > 5 minutes --- Loop/Managers/DeviceDataManager.swift | 6 ++++++ Loop/Managers/StatusChartsManager+LoopKit.swift | 2 +- .../StatusTableViewController.swift | 15 ++++++++------- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index e50b628c71..53517c7da8 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -21,6 +21,12 @@ final class DeviceDataManager { if cgmManager is PumpManagerUI { cgmManager = nil } + + if let pumpManager = pumpManager { + pumpManagerHUDProvider = pumpManager.hudProvider() + } else { + pumpManagerHUDProvider = nil + } setupPump() diff --git a/Loop/Managers/StatusChartsManager+LoopKit.swift b/Loop/Managers/StatusChartsManager+LoopKit.swift index 2f54ca31ac..ef54bd9361 100644 --- a/Loop/Managers/StatusChartsManager+LoopKit.swift +++ b/Loop/Managers/StatusChartsManager+LoopKit.swift @@ -83,7 +83,7 @@ extension StatusChartsManager { for entry in doseEntries { let time = entry.endDate.timeIntervalSince(entry.startDate) - if entry.type == .bolus && entry.netBasalUnits > 0 && time < .minutes(5) { + if entry.type == .bolus && entry.units > 0 { let x = ChartAxisValueDate(date: entry.startDate, formatter: dateFormatter) let y = ChartAxisValueDoubleLog(actualDouble: entry.units, unitString: "U", formatter: doseFormatter) diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index 89fd83e883..bc0252f498 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -1065,15 +1065,16 @@ final class StatusTableViewController: ChartsTableViewController { } private func configurePumpManagerHUDViews() { - if var pumpManagerHUDProvider = deviceManager.pumpManagerHUDProvider, - let hudView = hudView - { - let views = pumpManagerHUDProvider.createHUDViews() + if let hudView = hudView { hudView.removeNonStandardHUDViews() - for view in views { - addViewToHUD(view) + if var pumpManagerHUDProvider = deviceManager.pumpManagerHUDProvider + { + let views = pumpManagerHUDProvider.createHUDViews() + for view in views { + addViewToHUD(view) + } + pumpManagerHUDProvider.delegate = self } - pumpManagerHUDProvider.delegate = self } } From 76c8f266095631d6a4de6e3845289f5e4d9485d2 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sun, 4 Nov 2018 07:49:18 -0800 Subject: [PATCH 20/56] PumpManager returns DoseEntry for requested bolus, including duration --- Loop/Extensions/NewPumpEvent.swift | 18 ++------------- Loop/Managers/DeviceDataManager.swift | 18 +++++++++++---- Loop/Managers/LoopDataManager.swift | 22 +++++++++---------- .../StatusChartsManager+LoopKit.swift | 2 +- .../StatusTableViewController.swift | 5 +++++ 5 files changed, 33 insertions(+), 32 deletions(-) diff --git a/Loop/Extensions/NewPumpEvent.swift b/Loop/Extensions/NewPumpEvent.swift index 52432cf229..af0e9fe9f3 100644 --- a/Loop/Extensions/NewPumpEvent.swift +++ b/Loop/Extensions/NewPumpEvent.swift @@ -10,28 +10,14 @@ import LoopKit extension NewPumpEvent { - /* - It takes a MM pump about 40s to deliver 1 Unit while bolusing - See: http://www.healthline.com/diabetesmine/ask-dmine-speed-insulin-pumps#3 - */ - private static let deliveryUnitsPerMinute = 1.5 - /// Constructs a pump event placeholder representing a bolus just enacted. /// /// - Parameters: /// - units: The units of insulin requested /// - date: The date the bolus was enacted - static func enactedBolus(units: Double, at date: Date) -> NewPumpEvent { - let dose = DoseEntry( - type: .bolus, - startDate: date, - endDate: date.addingTimeInterval(.minutes(units / NewPumpEvent.deliveryUnitsPerMinute)), - value: units, - unit: .units - ) - + static func enactedBolus(dose: DoseEntry) -> NewPumpEvent { return self.init( - date: date, + date: dose.startDate, dose: dose, isMutable: true, raw: Data(), // This can be empty, as mutable events aren't persisted diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index 53517c7da8..1bc7d8f584 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -253,6 +253,14 @@ extension DeviceDataManager: PumpManagerDelegate { } func pumpManager(_ pumpManager: PumpManager, didReadPumpEvents events: [NewPumpEvent], completion: @escaping (_ error: Error?) -> Void) { + for event in events { + if let dose = event.dose { + if dose.type == .bolus && dose.startDate != dose.endDate { + print("square?!?!") + } + } + } + loopManager.addPumpEvents(events) { (error) in if let error = error { self.log.error("Failed to addPumpEvents to DoseStore: \(error)") @@ -346,15 +354,17 @@ extension DeviceDataManager { return } - pumpManager.enactBolus(units: units, at: startDate, willRequest: { (units, date) in - self.loopManager.addRequestedBolus(units: units, at: date, completion: nil) + var requestedDose: DoseEntry? + pumpManager.enactBolus(units: units, at: startDate, willRequest: { (dose) in + self.loopManager.addRequestedBolus(dose: dose, completion: nil) + requestedDose = dose }) { (error) in if let error = error { self.log.error(error) NotificationManager.sendBolusFailureNotification(for: error, units: units, at: startDate) completion(error) - } else { - self.loopManager.addConfirmedBolus(units: units, at: Date()) { + } else if let dose = requestedDose { + self.loopManager.addConfirmedBolus(dose) { completion(nil) } } diff --git a/Loop/Managers/LoopDataManager.swift b/Loop/Managers/LoopDataManager.swift index ee1a6ab118..7a426b16ff 100644 --- a/Loop/Managers/LoopDataManager.swift +++ b/Loop/Managers/LoopDataManager.swift @@ -172,7 +172,7 @@ final class LoopDataManager { fileprivate var carbsOnBoard: CarbValue? fileprivate var lastTempBasal: DoseEntry? - fileprivate var lastRequestedBolus: (units: Double, date: Date)? + fileprivate var lastRequestedBolus: DoseEntry? /// The last date at which a loop completed, from prediction to dose (if dosing is enabled) var lastLoopCompleted: Date? { @@ -451,11 +451,10 @@ extension LoopDataManager { /// Adds a bolus requested of the pump, but not confirmed. /// /// - Parameters: - /// - units: The bolus amount, in units - /// - date: The date the bolus was requested - func addRequestedBolus(units: Double, at date: Date, completion: (() -> Void)?) { + /// - dose: The DoseEntry representing the requested bolus + func addRequestedBolus(dose: DoseEntry, completion: (() -> Void)?) { dataAccessQueue.async { - self.lastRequestedBolus = (units: units, date: date) + self.lastRequestedBolus = dose self.notify(forChange: .bolus) completion?() @@ -465,10 +464,9 @@ extension LoopDataManager { /// Adds a bolus enacted by the pump, but not fully delivered. /// /// - Parameters: - /// - units: The bolus amount, in units - /// - date: The date the bolus was enacted - func addConfirmedBolus(units: Double, at date: Date, completion: (() -> Void)?) { - self.doseStore.addPendingPumpEvent(.enactedBolus(units: units, at: date)) { + /// - dose: The DoseEntry representing the confirmed bolus + func addConfirmedBolus(_ dose: DoseEntry, completion: (() -> Void)?) { + self.doseStore.addPendingPumpEvent(.enactedBolus(dose: dose)) { self.dataAccessQueue.async { self.lastRequestedBolus = nil self.insulinEffect = nil @@ -491,7 +489,8 @@ extension LoopDataManager { if error == nil { self.insulinEffect = nil // Expire any bolus values now represented in the insulin data - if let bolusDate = self.lastRequestedBolus?.date, bolusDate.timeIntervalSinceNow < TimeInterval(minutes: -5) { + // TODO: Ask pumpManager if dose represented in data + if let bolusDate = self.lastRequestedBolus?.startDate, bolusDate.timeIntervalSinceNow < TimeInterval(minutes: -5) { self.lastRequestedBolus = nil } } @@ -519,7 +518,8 @@ extension LoopDataManager { self.dataAccessQueue.async { self.insulinEffect = nil // Expire any bolus values now represented in the insulin data - if areStoredValuesContinuous, let bolusDate = self.lastRequestedBolus?.date, bolusDate.timeIntervalSinceNow < TimeInterval(minutes: -5) { + // TODO: Ask pumpManager if dose represented in data + if areStoredValuesContinuous, let bolusDate = self.lastRequestedBolus?.startDate, bolusDate.timeIntervalSinceNow < TimeInterval(minutes: -5) { self.lastRequestedBolus = nil } diff --git a/Loop/Managers/StatusChartsManager+LoopKit.swift b/Loop/Managers/StatusChartsManager+LoopKit.swift index ef54bd9361..46b4cd0fe6 100644 --- a/Loop/Managers/StatusChartsManager+LoopKit.swift +++ b/Loop/Managers/StatusChartsManager+LoopKit.swift @@ -83,7 +83,7 @@ extension StatusChartsManager { for entry in doseEntries { let time = entry.endDate.timeIntervalSince(entry.startDate) - if entry.type == .bolus && entry.units > 0 { + if entry.type == .bolus && entry.netBasalUnits > 0 && time < .minutes(10) { let x = ChartAxisValueDate(date: entry.startDate, formatter: dateFormatter) let y = ChartAxisValueDoubleLog(actualDouble: entry.units, unitString: "U", formatter: doseFormatter) diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index bc0252f498..ef66365317 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -349,6 +349,11 @@ final class StatusTableViewController: ChartsTableViewController { retryContext.update(with: .insulin) doseEntries = [] case .success(let doses): + for dose in doses { + if dose.type == .bolus && dose.startDate != dose.endDate { + print("square?!?!") + } + } doseEntries = doses } reloadGroup.leave() From bdaea1d9be86b66a4e5cb2f9b40a20a359c945dd Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 5 Nov 2018 16:58:48 -0800 Subject: [PATCH 21/56] Example jumpstart --- Loop/Managers/DeviceDataManager.swift | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index 1bc7d8f584..63e19e3c7f 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -9,7 +9,8 @@ import HealthKit import LoopKit import LoopKitUI - +//import OmniKit +//import OmniKitUI final class DeviceDataManager { @@ -138,6 +139,12 @@ final class DeviceDataManager { init() { pumpManager = UserDefaults.appGroup.pumpManager as? PumpManagerUI + +// if pumpManager == nil { +// pumpManager = OmnipodPumpManager.jumpStartPod(address: 520595206, lot: 43461, tid: 940516) +// UserDefaults.appGroup.pumpManager = pumpManager +// } + if let cgmManager = UserDefaults.appGroup.cgmManager { self.cgmManager = cgmManager } else if UserDefaults.appGroup.isCGMManagerValidPumpManager { From b535cfcbba143dde140515925ed493a277f48a74 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 20 Nov 2018 15:38:34 -0600 Subject: [PATCH 22/56] Suspend/Resume with new PumpManager status updates --- Loop/Managers/DeviceDataManager.swift | 22 +---- Loop/Managers/NightscoutDataManager.swift | 11 ++- .../SettingsTableViewController.swift | 90 ------------------- .../StatusTableViewController.swift | 31 ++++--- 4 files changed, 28 insertions(+), 126 deletions(-) diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index 63e19e3c7f..98abb9bb04 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -17,7 +17,9 @@ final class DeviceDataManager { private let queue = DispatchQueue(label: "com.loopkit.DeviceManagerQueue", qos: .utility) var pumpManager: PumpManagerUI? { + didSet { + // If the current CGMManager is a PumpManager, we clear it out. if cgmManager is PumpManagerUI { cgmManager = nil @@ -87,10 +89,6 @@ final class DeviceDataManager { } } - if oldValue?.isSuspended != status.isSuspended { - NotificationCenter.default.post(name: .PumpSuspendStateChanged, object: self, userInfo: [DeviceDataManager.pumpSuspendStateKey: status.isSuspended]) - } - // Update the pump-schedule based settings loopManager.setScheduleTimeZone(status.timeZone) @@ -260,14 +258,7 @@ extension DeviceDataManager: PumpManagerDelegate { } func pumpManager(_ pumpManager: PumpManager, didReadPumpEvents events: [NewPumpEvent], completion: @escaping (_ error: Error?) -> Void) { - for event in events { - if let dose = event.dose { - if dose.type == .bolus && dose.startDate != dose.endDate { - print("square?!?!") - } - } - } - + loopManager.addPumpEvents(events) { (error) in if let error = error { self.log.error("Failed to addPumpEvents to DoseStore: \(error)") @@ -406,7 +397,7 @@ extension DeviceDataManager: LoopDataManagerDelegate { } -extension DeviceDataManager: CustomDebugStringConvertible { +extension DeviceDataManager { var debugDescription: String { return [ Bundle.main.localizedNameAndVersion, @@ -427,10 +418,5 @@ extension DeviceDataManager: CustomDebugStringConvertible { } extension Notification.Name { - static let PumpSuspendStateChanged = Notification.Name(rawValue: "com.loopKit.notification.PumpSuspendStateChanged") static let PumpManagerChanged = Notification.Name(rawValue: "com.loopKit.notification.PumpManagerChanged") } - -extension DeviceDataManager { - public static let pumpSuspendStateKey = "com.loopkit.PumpSuspendState" -} diff --git a/Loop/Managers/NightscoutDataManager.swift b/Loop/Managers/NightscoutDataManager.swift index 67ee491022..6b3ce1b027 100644 --- a/Loop/Managers/NightscoutDataManager.swift +++ b/Loop/Managers/NightscoutDataManager.swift @@ -145,13 +145,20 @@ final class NightscoutDataManager { battery = nil } + let bolusing: Bool + if case .bolusing = pumpManagerStatus.bolusState { + bolusing = true + } else { + bolusing = false + } + pumpStatus = NightscoutUploadKit.PumpStatus( clock: Date(), pumpID: pumpManagerStatus.device.localIdentifier ?? "Unknown", iob: nil, battery: battery, - suspended: pumpManagerStatus.isSuspended, - bolusing: pumpManagerStatus.isBolusing, + suspended: pumpManagerStatus.suspendState == .suspended, + bolusing: bolusing, reservoir: deviceManager.loopManager.doseStore.lastReservoirValue?.unitVolume, secondsFromGMT: pumpManagerStatus.timeZone.secondsFromGMT()) } else { diff --git a/Loop/View Controllers/SettingsTableViewController.swift b/Loop/View Controllers/SettingsTableViewController.swift index c5c0e368b3..c0bdcaec70 100644 --- a/Loop/View Controllers/SettingsTableViewController.swift +++ b/Loop/View Controllers/SettingsTableViewController.swift @@ -25,7 +25,6 @@ final class SettingsTableViewController: UITableViewController { tableView.register(SettingsTableViewCell.self, forCellReuseIdentifier: SettingsTableViewCell.className) tableView.register(SettingsImageTableViewCell.self, forCellReuseIdentifier: SettingsImageTableViewCell.className) tableView.register(TextButtonTableViewCell.self, forCellReuseIdentifier: TextButtonTableViewCell.className) - tableView.register(SuspendResumeTableViewCell.self, forCellReuseIdentifier: SuspendResumeTableViewCell.className) } override func viewWillAppear(_ animated: Bool) { @@ -63,7 +62,6 @@ final class SettingsTableViewController: UITableViewController { fileprivate enum PumpRow: Int, CaseCountable { case pumpSettings = 0 - case suspendResume } fileprivate enum CGMRow: Int, CaseCountable { @@ -183,11 +181,6 @@ final class SettingsTableViewController: UITableViewController { cell.textLabel?.text = NSLocalizedString("Add Pump", comment: "Title text for button to set up a new pump") return cell } - case .suspendResume: - let pumpManager = dataManager.pumpManager! - let cell = tableView.dequeueReusableCell(withIdentifier: SuspendResumeTableViewCell.className, for: indexPath) as! SuspendResumeTableViewCell - cell.option = pumpManager.status.isSuspended ? .resume : .suspend - return cell } case .cgm: if let cgmManager = dataManager.cgmManager { @@ -369,42 +362,6 @@ final class SettingsTableViewController: UITableViewController { break } } - case .suspendResume: - if let cell = tableView.cellForRow(at: indexPath) as? SuspendResumeTableViewCell, - let pumpManager = dataManager.pumpManager - { - cell.isLoading = true - cell.isEnabled = false - switch cell.option { - case .resume: - pumpManager.resumeDelivery { (result) in - DispatchQueue.main.async { - cell.isEnabled = true - cell.isLoading = false - if case .failure(let error) = result { - let alert = UIAlertController(title: NSLocalizedString("Error Resuming", comment: "The alert title for a resume error"), error: error) - self.present(alert, animated: true, completion: nil) - } else { - self.tableView.reloadRows(at: [indexPath], with: .none) - } - } - } - case .suspend: - pumpManager.suspendDelivery { (result) in - DispatchQueue.main.async { - cell.isEnabled = true - cell.isLoading = false - if case .failure(let error) = result { - let alert = UIAlertController(title: NSLocalizedString("Error Suspending", comment: "The alert title for a suspend error"), error: error) - self.present(alert, animated: true, completion: nil) - } else { - self.tableView.reloadRows(at: [indexPath], with: .none) - } - } - } - } - tableView.deselectRow(at: indexPath, animated: true) - } } case .cgm: if let cgmManager = dataManager.cgmManager as? CGMManagerUI { @@ -794,50 +751,3 @@ extension SettingsTableViewController: DeliveryLimitSettingsTableViewControllerD tableView.reloadRows(at: [[Section.configuration.rawValue, ConfigurationRow.deliveryLimits.rawValue]], with: .none) } } - -extension UIAlertController { - fileprivate convenience init(title: String, error: Error) { - - let message: String - - if let localizedError = error as? LocalizedError { - let sentenceFormat = NSLocalizedString("%@.", comment: "Appends a full-stop to a statement") - message = [localizedError.failureReason, localizedError.recoverySuggestion].compactMap({ $0 }).map({ - String(format: sentenceFormat, $0) - }).joined(separator: "\n") - } else { - message = String(describing: error) - } - - self.init( - title: title, - message: message, - preferredStyle: .alert - ) - - addAction(UIAlertAction( - title: NSLocalizedString("OK", comment: "Button title to acknowledge error"), - style: .default, - handler: nil - )) - } -} - -class SuspendResumeTableViewCell: TextButtonTableViewCell { - - enum Option { - case suspend - case resume - } - - var option: Option = .suspend { - didSet { - switch option { - case .suspend: - textLabel?.text = NSLocalizedString("Suspend Delivery", comment: "Title text for button to suspend insulin delivery") - case .resume: - textLabel?.text = NSLocalizedString("Resume Delivery", comment: "Title text for button to resume insulin delivery") - } - } - } -} diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index ef66365317..8c6f39429b 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -43,7 +43,8 @@ final class StatusTableViewController: ChartsTableViewController { ) if let pumpManager = deviceManager.pumpManager { - self.pumpIsSuspended = pumpManager.status.isSuspended + self.suspendState = pumpManager.status.suspendState + pumpManager.addStatusObserver(self) } let notificationCenter = NotificationCenter.default @@ -76,14 +77,6 @@ final class StatusTableViewController: ChartsTableViewController { self?.hudView?.loopCompletionHUD.loopInProgress = true } }, - notificationCenter.addObserver(forName: .PumpSuspendStateChanged, object: deviceManager, queue: OperationQueue.main) { [weak self] (notification: Notification) in - DispatchQueue.main.async { - if let isPumpSuspended = notification.userInfo?[DeviceDataManager.pumpSuspendStateKey] as? Bool, let self = self { - self.pumpIsSuspended = isPumpSuspended - self.reloadData(animated: true) - } - } - }, notificationCenter.addObserver(forName: .PumpManagerChanged, object: deviceManager, queue: OperationQueue.main) { [weak self] (notification: Notification) in DispatchQueue.main.async { self?.configurePumpManagerHUDViews() @@ -184,7 +177,7 @@ final class StatusTableViewController: ChartsTableViewController { } } - public var pumpIsSuspended: Bool = false { + public var suspendState: PumpManagerStatus.SuspendState = .none { didSet { refreshContext.update(with: .status) } @@ -349,11 +342,6 @@ final class StatusTableViewController: ChartsTableViewController { retryContext.update(with: .insulin) doseEntries = [] case .success(let doses): - for dose in doses { - if dose.type == .bolus && dose.startDate != dose.endDate { - print("square?!?!") - } - } doseEntries = doses } reloadGroup.leave() @@ -438,8 +426,10 @@ final class StatusTableViewController: ChartsTableViewController { // Show/hide the table view rows let statusRowMode: StatusRowMode? - if self.pumpIsSuspended { + if self.suspendState == .suspended { statusRowMode = .pumpSuspended(resuming: false) + } else if self.suspendState == .resuming { + statusRowMode = .pumpSuspended(resuming: true) } else { switch bolusState { case .recommended?, .enacting?: @@ -1124,6 +1114,15 @@ final class StatusTableViewController: ChartsTableViewController { } } +extension StatusTableViewController: PumpManagerStatusObserver { + func pumpManager(_ pumpManager: PumpManager, didUpdateStatus status: PumpManagerStatus) { + DispatchQueue.main.async { + self.suspendState = status.suspendState + self.reloadData(animated: true) + } + } +} + extension StatusTableViewController: HUDProviderDelegate { func newHUDViewsAvailable(_ views: [BaseHUDView]) { DispatchQueue.main.async { From 3a12b02de5a79ab8e8e6dcc88b7d7a7d442972fb Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sun, 25 Nov 2018 22:20:58 -0600 Subject: [PATCH 23/56] Fix issue with DeviceDataManager missing from issue report --- Loop/Managers/DeviceDataManager.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index 98abb9bb04..5224d352a4 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -397,7 +397,7 @@ extension DeviceDataManager: LoopDataManagerDelegate { } -extension DeviceDataManager { +extension DeviceDataManager: CustomDebugStringConvertible { var debugDescription: String { return [ Bundle.main.localizedNameAndVersion, From b4276a1b637975e5f5c773ad15908e276b8845aa Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sun, 2 Dec 2018 11:35:27 -0600 Subject: [PATCH 24/56] Handle LoopKit and rileylink_ios updates --- Loop.xcodeproj/project.pbxproj | 12 ++++++++ Loop/Managers/DeviceDataManager.swift | 3 +- Loop/Managers/NightscoutDataManager.swift | 2 +- .../StatusTableViewController.swift | 29 ++++++++++++++----- 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj index 7a2c91a36e..5254f2514d 100644 --- a/Loop.xcodeproj/project.pbxproj +++ b/Loop.xcodeproj/project.pbxproj @@ -289,6 +289,10 @@ C12F21A71DFA79CB00748193 /* recommend_temp_basal_very_low_end_in_range.json in Resources */ = {isa = PBXBuildFile; fileRef = C12F21A61DFA79CB00748193 /* recommend_temp_basal_very_low_end_in_range.json */; }; C13BAD941E8009B000050CB5 /* NumberFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43BFF0B31E45C1BE00FF19A9 /* NumberFormatter.swift */; }; C15713821DAC6983005BC4D2 /* MealBolusNightscoutTreatment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C15713811DAC6983005BC4D2 /* MealBolusNightscoutTreatment.swift */; }; + C168C40621B0D53E00ADE90E /* MinimedKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C168C40521B0D53E00ADE90E /* MinimedKit.framework */; }; + C168C40821B0D53E00ADE90E /* MinimedKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C168C40721B0D53E00ADE90E /* MinimedKitUI.framework */; }; + C168C40921B0D53E00ADE90E /* OmniKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1CB13A8213EE35800F9EEDA /* OmniKit.framework */; }; + C168C40A21B0D53E00ADE90E /* OmniKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1CB13AA213EE35800F9EEDA /* OmniKitUI.framework */; }; C178249A1E1999FA00D9D25C /* CaseCountable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C17824991E1999FA00D9D25C /* CaseCountable.swift */; }; C17824A01E19CF9800D9D25C /* GlucoseThresholdTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C178249F1E19CF9800D9D25C /* GlucoseThresholdTableViewController.swift */; }; C17824A31E19EAB600D9D25C /* recommend_temp_basal_start_very_low_end_high.json in Resources */ = {isa = PBXBuildFile; fileRef = C17824A21E19EAB600D9D25C /* recommend_temp_basal_start_very_low_end_high.json */; }; @@ -820,6 +824,8 @@ C10B28451EA9BA5E006EA1FC /* far_future_high_bg_forecast.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = far_future_high_bg_forecast.json; sourceTree = ""; }; C12F21A61DFA79CB00748193 /* recommend_temp_basal_very_low_end_in_range.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = recommend_temp_basal_very_low_end_in_range.json; sourceTree = ""; }; C15713811DAC6983005BC4D2 /* MealBolusNightscoutTreatment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MealBolusNightscoutTreatment.swift; sourceTree = ""; }; + C168C40521B0D53E00ADE90E /* MinimedKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MinimedKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C168C40721B0D53E00ADE90E /* MinimedKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MinimedKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C17824991E1999FA00D9D25C /* CaseCountable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaseCountable.swift; sourceTree = ""; }; C178249F1E19CF9800D9D25C /* GlucoseThresholdTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlucoseThresholdTableViewController.swift; sourceTree = ""; }; C17824A21E19EAB600D9D25C /* recommend_temp_basal_start_very_low_end_high.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = recommend_temp_basal_start_very_low_end_high.json; sourceTree = ""; }; @@ -900,6 +906,10 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + C168C40621B0D53E00ADE90E /* MinimedKit.framework in Frameworks */, + C168C40821B0D53E00ADE90E /* MinimedKitUI.framework in Frameworks */, + C168C40921B0D53E00ADE90E /* OmniKit.framework in Frameworks */, + C168C40A21B0D53E00ADE90E /* OmniKitUI.framework in Frameworks */, 4F7528951DFE1E9B00C322D6 /* LoopUI.framework in Frameworks */, 437AFEE520352591008C4892 /* NotificationCenter.framework in Frameworks */, ); @@ -1370,6 +1380,8 @@ 968DCD53F724DE56FFE51920 /* Frameworks */ = { isa = PBXGroup; children = ( + C168C40521B0D53E00ADE90E /* MinimedKit.framework */, + C168C40721B0D53E00ADE90E /* MinimedKitUI.framework */, C1C108C22152F46D00EA5165 /* CGMBLEKitUI.framework */, 434FB6451D68F1CD007B9C70 /* Amplitude.framework */, C1CB13A8213EE35800F9EEDA /* OmniKit.framework */, diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index 5224d352a4..624028c1ad 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -139,7 +139,8 @@ final class DeviceDataManager { pumpManager = UserDefaults.appGroup.pumpManager as? PumpManagerUI // if pumpManager == nil { -// pumpManager = OmnipodPumpManager.jumpStartPod(address: 520595206, lot: 43461, tid: 940516) +// let basalSchedule = BasalSchedule(entries: [BasalScheduleEntry(rate: 1.0, startTime: 0)]) +// pumpManager = OmnipodPumpManager.jumpStartPod(address: 520344533, lot: 40505, tid: 6882, schedule: basalSchedule) // UserDefaults.appGroup.pumpManager = pumpManager // } diff --git a/Loop/Managers/NightscoutDataManager.swift b/Loop/Managers/NightscoutDataManager.swift index 6b3ce1b027..6c1488fb50 100644 --- a/Loop/Managers/NightscoutDataManager.swift +++ b/Loop/Managers/NightscoutDataManager.swift @@ -146,7 +146,7 @@ final class NightscoutDataManager { } let bolusing: Bool - if case .bolusing = pumpManagerStatus.bolusState { + if case .inProgress = pumpManagerStatus.bolusState { bolusing = true } else { bolusing = false diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index 8c6f39429b..5d99e561e0 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -134,6 +134,8 @@ final class StatusTableViewController: ChartsTableViewController { } } } + + deviceManager.pumpManagerHUDProvider?.hudDidAppear() AnalyticsManager.shared.didDisplayStatusScreen() } @@ -849,17 +851,14 @@ final class StatusTableViewController: ChartsTableViewController { case .pumpSuspended(let resuming): if !resuming { self.updateHUDandStatusRows(statusRowMode: .pumpSuspended(resuming: true) , newSize: nil, animated: true) - self.deviceManager.pumpManager?.resumeDelivery(completion: { (result) in + self.deviceManager.pumpManager?.resumeDelivery() { (error) in DispatchQueue.main.async { - switch result { - case .failure(let error): + if let error = error { let alert = UIAlertController(title: NSLocalizedString("Error Resuming", comment: "The alert title for a resume error"), error: error) self.present(alert, animated: true, completion: nil) - case .success: - break } } - }) + } } default: break @@ -1107,6 +1106,8 @@ final class StatusTableViewController: ChartsTableViewController { switch action { case .showViewController(let vc): self.navigationController?.pushViewController(vc, animated: true) + case .presentViewController(let vc): + self.present(vc, animated: true, completion: nil) case .openAppURL(let url): UIApplication.shared.open(url) } @@ -1124,7 +1125,7 @@ extension StatusTableViewController: PumpManagerStatusObserver { } extension StatusTableViewController: HUDProviderDelegate { - func newHUDViewsAvailable(_ views: [BaseHUDView]) { + func addHudViews(_ views: [BaseHUDView]) { DispatchQueue.main.async { for view in views { view.isHidden = true @@ -1139,6 +1140,20 @@ extension StatusTableViewController: HUDProviderDelegate { }) } } + + func removeHudViews(_ views: [BaseHUDView]) { + DispatchQueue.main.async { + UIView.animate(withDuration: 1, animations: { + for view in views { + view.alpha = 0 + } + }, completion: { (didFinish) in + for view in views { + view.removeFromSuperview() + } + }) + } + } } extension UIAlertController { From 511f0c205084ca0512037c4a35b3769bc073d8b5 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 4 Dec 2018 23:33:20 -0600 Subject: [PATCH 25/56] Cleanup testing code --- Loop/Managers/DeviceDataManager.swift | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index 624028c1ad..06d76f915b 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -9,8 +9,6 @@ import HealthKit import LoopKit import LoopKitUI -//import OmniKit -//import OmniKitUI final class DeviceDataManager { @@ -138,12 +136,6 @@ final class DeviceDataManager { init() { pumpManager = UserDefaults.appGroup.pumpManager as? PumpManagerUI -// if pumpManager == nil { -// let basalSchedule = BasalSchedule(entries: [BasalScheduleEntry(rate: 1.0, startTime: 0)]) -// pumpManager = OmnipodPumpManager.jumpStartPod(address: 520344533, lot: 40505, tid: 6882, schedule: basalSchedule) -// UserDefaults.appGroup.pumpManager = pumpManager -// } - if let cgmManager = UserDefaults.appGroup.cgmManager { self.cgmManager = cgmManager } else if UserDefaults.appGroup.isCGMManagerValidPumpManager { From fb006e5aa502a98b85aa461cd935d97b006f3f68 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 8 Dec 2018 19:00:30 -0600 Subject: [PATCH 26/56] Update Loop today widget when HUD views change --- Loop/Managers/DeviceDataManager.swift | 1 + Loop/Managers/StatusExtensionDataManager.swift | 1 + Loop/View Controllers/StatusTableViewController.swift | 6 ++++++ 3 files changed, 8 insertions(+) diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index 06d76f915b..5ecf18742a 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -413,3 +413,4 @@ extension DeviceDataManager: CustomDebugStringConvertible { extension Notification.Name { static let PumpManagerChanged = Notification.Name(rawValue: "com.loopKit.notification.PumpManagerChanged") } + diff --git a/Loop/Managers/StatusExtensionDataManager.swift b/Loop/Managers/StatusExtensionDataManager.swift index e72aedaee0..d598c8c9a1 100644 --- a/Loop/Managers/StatusExtensionDataManager.swift +++ b/Loop/Managers/StatusExtensionDataManager.swift @@ -18,6 +18,7 @@ final class StatusExtensionDataManager { self.deviceManager = deviceDataManager NotificationCenter.default.addObserver(self, selector: #selector(update(_:)), name: .LoopDataUpdated, object: deviceDataManager.loopManager) + NotificationCenter.default.addObserver(self, selector: #selector(update(_:)), name: .HUDViewsChanged, object: nil) } fileprivate var defaults: UserDefaults? { diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index 5d99e561e0..6ea01dcee8 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -1069,6 +1069,7 @@ final class StatusTableViewController: ChartsTableViewController { } pumpManagerHUDProvider.delegate = self } + NotificationCenter.default.post(name: .HUDViewsChanged, object: self) } } @@ -1138,6 +1139,7 @@ extension StatusTableViewController: HUDProviderDelegate { view.alpha = 1 } }) + NotificationCenter.default.post(name: .HUDViewsChanged, object: self) } } @@ -1152,6 +1154,7 @@ extension StatusTableViewController: HUDProviderDelegate { view.removeFromSuperview() } }) + NotificationCenter.default.post(name: .HUDViewsChanged, object: self) } } } @@ -1184,3 +1187,6 @@ extension UIAlertController { } } +extension Notification.Name { + static let HUDViewsChanged = Notification.Name(rawValue: "com.loopKit.notification.HUDViewsChanged") +} From 3624d1a70f6df3b16c6d9104411101f50ad5a4c9 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Fri, 11 Jan 2019 15:06:33 -0600 Subject: [PATCH 27/56] Renaming updates from LoopKit --- Loop.xcodeproj/project.pbxproj | 16 ++++++++-------- Loop/Extensions/NightscoutUploader.swift | 3 ++- Loop/Managers/DeviceDataManager.swift | 2 +- Loop/Managers/NightscoutDataManager.swift | 2 +- .../StatusTableViewController.swift | 17 +++++++++-------- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj index 5254f2514d..146131f1d2 100644 --- a/Loop.xcodeproj/project.pbxproj +++ b/Loop.xcodeproj/project.pbxproj @@ -2627,7 +2627,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Loop/Loop.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; INFOPLIST_FILE = Loop/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; "OTHER_SWIFT_FLAGS[sdk=iphonesimulator*]" = "-D IOS_SIMULATOR"; @@ -2644,7 +2644,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Loop/Loop.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; INFOPLIST_FILE = Loop/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER)"; @@ -2660,7 +2660,7 @@ CODE_SIGN_ENTITLEMENTS = "WatchApp Extension/WatchApp Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/watchOS"; INFOPLIST_FILE = "WatchApp Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; @@ -2680,7 +2680,7 @@ CODE_SIGN_ENTITLEMENTS = "WatchApp Extension/WatchApp Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/watchOS"; INFOPLIST_FILE = "WatchApp Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; @@ -2700,7 +2700,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; FRAMEWORK_SEARCH_PATHS = ""; IBSC_MODULE = WatchApp_Extension; INFOPLIST_FILE = WatchApp/Info.plist; @@ -2721,7 +2721,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; FRAMEWORK_SEARCH_PATHS = ""; IBSC_MODULE = WatchApp_Extension; INFOPLIST_FILE = WatchApp/Info.plist; @@ -2800,7 +2800,7 @@ CODE_SIGN_ENTITLEMENTS = "Loop Status Extension/Loop Status Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; INFOPLIST_FILE = "Loop Status Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).statuswidget"; @@ -2819,7 +2819,7 @@ CODE_SIGN_ENTITLEMENTS = "Loop Status Extension/Loop Status Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; INFOPLIST_FILE = "Loop Status Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).statuswidget"; diff --git a/Loop/Extensions/NightscoutUploader.swift b/Loop/Extensions/NightscoutUploader.swift index ab81c2f85f..212a1d0fb7 100644 --- a/Loop/Extensions/NightscoutUploader.swift +++ b/Loop/Extensions/NightscoutUploader.swift @@ -75,11 +75,12 @@ extension NightscoutUploader { var treatments = [NightscoutTreatment]() for event in events { + objectIDURLs.append(event.objectIDURL) + guard let treatment = event.treatment(enteredBy: source) else { continue } - objectIDURLs.append(event.objectIDURL) treatments.append(treatment) } diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index 5ecf18742a..d9f3e0b9fa 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -232,7 +232,7 @@ extension DeviceDataManager: PumpManagerDelegate { return !(cgmManager?.providesBLEHeartbeat == true) } - func pumpManager(_ pumpManager: PumpManager, didUpdateStatus status: PumpManagerStatus) { + func pumpManager(_ pumpManager: PumpManager, didUpdate status: PumpManagerStatus) { self.pumpManagerStatus = status } diff --git a/Loop/Managers/NightscoutDataManager.swift b/Loop/Managers/NightscoutDataManager.swift index 6c1488fb50..9e74600a4f 100644 --- a/Loop/Managers/NightscoutDataManager.swift +++ b/Loop/Managers/NightscoutDataManager.swift @@ -157,7 +157,7 @@ final class NightscoutDataManager { pumpID: pumpManagerStatus.device.localIdentifier ?? "Unknown", iob: nil, battery: battery, - suspended: pumpManagerStatus.suspendState == .suspended, + suspended: pumpManagerStatus.basalDeliveryState == .suspended, bolusing: bolusing, reservoir: deviceManager.loopManager.doseStore.lastReservoirValue?.unitVolume, secondsFromGMT: pumpManagerStatus.timeZone.secondsFromGMT()) diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index 6ea01dcee8..e40a829b99 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -43,7 +43,7 @@ final class StatusTableViewController: ChartsTableViewController { ) if let pumpManager = deviceManager.pumpManager { - self.suspendState = pumpManager.status.suspendState + self.basalDeliveryState = pumpManager.status.basalDeliveryState pumpManager.addStatusObserver(self) } @@ -179,7 +179,7 @@ final class StatusTableViewController: ChartsTableViewController { } } - public var suspendState: PumpManagerStatus.SuspendState = .none { + public var basalDeliveryState: PumpManagerStatus.BasalDeliveryState = .none { didSet { refreshContext.update(with: .status) } @@ -428,9 +428,9 @@ final class StatusTableViewController: ChartsTableViewController { // Show/hide the table view rows let statusRowMode: StatusRowMode? - if self.suspendState == .suspended { + if self.basalDeliveryState == .suspended { statusRowMode = .pumpSuspended(resuming: false) - } else if self.suspendState == .resuming { + } else if self.basalDeliveryState == .resuming { statusRowMode = .pumpSuspended(resuming: true) } else { switch bolusState { @@ -1117,16 +1117,17 @@ final class StatusTableViewController: ChartsTableViewController { } extension StatusTableViewController: PumpManagerStatusObserver { - func pumpManager(_ pumpManager: PumpManager, didUpdateStatus status: PumpManagerStatus) { + func pumpManager(_ pumpManager: PumpManager, didUpdate status: PumpManagerStatus) { DispatchQueue.main.async { - self.suspendState = status.suspendState + self.basalDeliveryState = status.basalDeliveryState self.reloadData(animated: true) } } } extension StatusTableViewController: HUDProviderDelegate { - func addHudViews(_ views: [BaseHUDView]) { + + func hudProvider(_ provider: HUDProvider, didAddHudViews views: [BaseHUDView]) { DispatchQueue.main.async { for view in views { view.isHidden = true @@ -1143,7 +1144,7 @@ extension StatusTableViewController: HUDProviderDelegate { } } - func removeHudViews(_ views: [BaseHUDView]) { + func hudProvider(_ provider: HUDProvider, didRemoveHudViews views: [BaseHUDView]) { DispatchQueue.main.async { UIView.animate(withDuration: 1, animations: { for view in views { From 8598af6f9f12278c6f3fccdc2438ee4aaadd82c8 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 22 Jan 2019 13:15:19 -0600 Subject: [PATCH 28/56] Updates for recent LoopKit pumpmanager-changes branch --- Loop/Extensions/UIAlertController.swift | 10 ++-- .../BolusViewController.swift | 6 ++- .../CarbAbsorptionViewController.swift | 4 +- .../StatusTableViewController.swift | 52 +++++++------------ 4 files changed, 30 insertions(+), 42 deletions(-) diff --git a/Loop/Extensions/UIAlertController.swift b/Loop/Extensions/UIAlertController.swift index 0e352f9794..b841b08e4b 100644 --- a/Loop/Extensions/UIAlertController.swift +++ b/Loop/Extensions/UIAlertController.swift @@ -18,7 +18,7 @@ extension UIAlertController { - parameter handler: A closure to execute when the sheet is dismissed after selection. The closure has a single argument: - endDate: The date at which the user selected the workout to end */ - convenience init(workoutDurationSelectionHandler handler: @escaping (_ endDate: Date) -> Void) { + internal convenience init(workoutDurationSelectionHandler handler: @escaping (_ endDate: Date) -> Void) { self.init( title: NSLocalizedString("Use Workout Glucose Targets", comment: "The title of the alert controller used to select a duration for workout targets"), message: nil, @@ -51,7 +51,7 @@ extension UIAlertController { /// - cgmManagers: An array of PumpManagers /// - selectionHandler: A closure to execute when a manager is selected /// - manager: The selected manager - convenience init(pumpManagers: [PumpManagerUI.Type], selectionHandler: @escaping (_ manager: PumpManagerUI.Type) -> Void) { + internal convenience init(pumpManagers: [PumpManagerUI.Type], selectionHandler: @escaping (_ manager: PumpManagerUI.Type) -> Void) { self.init( title: NSLocalizedString("Add Pump", comment: "Action sheet title selecting Pump"), message: nil, @@ -77,7 +77,7 @@ extension UIAlertController { /// - selectionHandler: A closure to execute when either a new CGMManager or the current PumpManager is selected /// - cgmManager: The selected CGMManager type /// - pumpManager: The selected PumpManager instance - convenience init(cgmManagers: [CGMManagerUI.Type], pumpManager: CGMManager?, selectionHandler: @escaping (_ cgmManager: CGMManagerUI.Type?, _ pumpManager: CGMManager?) -> Void) { + internal convenience init(cgmManagers: [CGMManagerUI.Type], pumpManager: CGMManager?, selectionHandler: @escaping (_ cgmManager: CGMManagerUI.Type?, _ pumpManager: CGMManager?) -> Void) { self.init( title: NSLocalizedString("Add CGM", comment: "Action sheet title selecting CGM"), message: nil, @@ -105,7 +105,7 @@ extension UIAlertController { } } - convenience init(deleteCGMManagerHandler handler: @escaping (_ isDeleted: Bool) -> Void) { + internal convenience init(deleteCGMManagerHandler handler: @escaping (_ isDeleted: Bool) -> Void) { self.init( title: nil, message: NSLocalizedString("Are you sure you want to delete this CGM?", comment: "Confirmation message for deleting a CGM"), @@ -125,7 +125,7 @@ extension UIAlertController { } } - func addCancelAction(handler: ((UIAlertAction) -> Void)? = nil) { + internal func addCancelAction(handler: ((UIAlertAction) -> Void)? = nil) { let cancel = NSLocalizedString("Cancel", comment: "The title of the cancel action in an action sheet") addAction(UIAlertAction(title: cancel, style: .cancel, handler: handler)) } diff --git a/Loop/View Controllers/BolusViewController.swift b/Loop/View Controllers/BolusViewController.swift index 793bf5b747..3a58b7f3be 100644 --- a/Loop/View Controllers/BolusViewController.swift +++ b/Loop/View Controllers/BolusViewController.swift @@ -182,7 +182,11 @@ final class BolusViewController: UITableViewController, IdentifiableClass, UITex } guard bolus <= maxBolus else { - presentAlertController(withTitle: NSLocalizedString("Exceeds Maximum Bolus", comment: "The title of the alert describing a maximum bolus validation error"), message: String(format: NSLocalizedString("The maximum bolus amount is %@ Units", comment: "Body of the alert describing a maximum bolus validation error. (1: The localized max bolus value)"), bolusUnitsFormatter.string(from: maxBolus) ?? "")) + let alert = UIAlertController( + title: NSLocalizedString("Exceeds Maximum Bolus", comment: "The title of the alert describing a maximum bolus validation error"), + message: String(format: NSLocalizedString("The maximum bolus amount is %@ Units", comment: "Body of the alert describing a maximum bolus validation error. (1: The localized max bolus value)"), bolusUnitsFormatter.string(from: maxBolus) ?? ""), + preferredStyle: .alert) + present(alert, animated: true) return } diff --git a/Loop/View Controllers/CarbAbsorptionViewController.swift b/Loop/View Controllers/CarbAbsorptionViewController.swift index b6398ab177..afab2f835f 100644 --- a/Loop/View Controllers/CarbAbsorptionViewController.swift +++ b/Loop/View Controllers/CarbAbsorptionViewController.swift @@ -436,7 +436,7 @@ final class CarbAbsorptionViewController: ChartsTableViewController, Identifiabl break // Notification will trigger update case .failure(let error): self.refreshContext.update(with: .carbs) - self.presentAlertController(with: error) + self.present(UIAlertController(with: error), animated: true) } } } @@ -535,7 +535,7 @@ final class CarbAbsorptionViewController: ChartsTableViewController, Identifiabl case .failure(let error): // Ignore bolus wizard errors if error is CarbStore.CarbStoreError { - self.presentAlertController(with: error) + self.present(UIAlertController(with: error), animated: true) } } } diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index e40a829b99..3ddc4a4d0d 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -179,7 +179,7 @@ final class StatusTableViewController: ChartsTableViewController { } } - public var basalDeliveryState: PumpManagerStatus.BasalDeliveryState = .none { + public var basalDeliveryState: PumpManagerStatus.BasalDeliveryState = .active { didSet { refreshContext.update(with: .status) } @@ -839,7 +839,7 @@ final class StatusTableViewController: ChartsTableViewController { if let error = error { self.deviceManager.logger.addError(error, fromSource: "TempBasal") - self.presentAlertController(with: error) + self.present(UIAlertController(with: error), animated: true) } else { self.refreshContext.update(with: .status) self.log.debug("[reloadData] after manually enacting temp basal") @@ -854,7 +854,7 @@ final class StatusTableViewController: ChartsTableViewController { self.deviceManager.pumpManager?.resumeDelivery() { (error) in DispatchQueue.main.async { if let error = error { - let alert = UIAlertController(title: NSLocalizedString("Error Resuming", comment: "The alert title for a resume error"), error: error) + let alert = UIAlertController(with: error, title: NSLocalizedString("Error Resuming", comment: "The alert title for a resume error")) self.present(alert, animated: true, completion: nil) } } @@ -947,7 +947,7 @@ final class StatusTableViewController: ChartsTableViewController { case .failure(let error): // Ignore bolus wizard errors if error is CarbStore.CarbStoreError { - self.presentAlertController(with: error) + self.present(UIAlertController(with: error), animated: true) } else { self.deviceManager.logger.addError(error, fromSource: "Bolus") } @@ -1087,9 +1087,9 @@ final class StatusTableViewController: ChartsTableViewController { if let deviceError = deviceManager.lastError, deviceError.date > (hudView?.loopCompletionHUD.lastLoopCompleted ?? .distantPast) { - self.presentAlertController(with: deviceError.error) + self.present(UIAlertController(with: deviceError.error), animated: true) } else if let lastLoopError = lastLoopError { - self.presentAlertController(with: lastLoopError) + self.present(UIAlertController(with: lastLoopError), animated: true) } } @@ -1102,7 +1102,7 @@ final class StatusTableViewController: ChartsTableViewController { @objc private func hudViewTapped(_ sender: UIGestureRecognizer) { if let hudSubView = sender.view as? BaseHUDView, let pumpManagerHUDProvider = deviceManager.pumpManagerHUDProvider, - let action = pumpManagerHUDProvider.didTapOnHudView(hudSubView) + let action = pumpManagerHUDProvider.didTapOnHUDView(hudSubView) { switch action { case .showViewController(let vc): @@ -1127,7 +1127,7 @@ extension StatusTableViewController: PumpManagerStatusObserver { extension StatusTableViewController: HUDProviderDelegate { - func hudProvider(_ provider: HUDProvider, didAddHudViews views: [BaseHUDView]) { + func hudProvider(_ provider: HUDProvider, didAddViews views: [BaseHUDView]) { DispatchQueue.main.async { for view in views { view.isHidden = true @@ -1144,7 +1144,7 @@ extension StatusTableViewController: HUDProviderDelegate { } } - func hudProvider(_ provider: HUDProvider, didRemoveHudViews views: [BaseHUDView]) { + func hudProvider(_ provider: HUDProvider, didRemoveViews views: [BaseHUDView]) { DispatchQueue.main.async { UIView.animate(withDuration: 1, animations: { for view in views { @@ -1158,33 +1158,17 @@ extension StatusTableViewController: HUDProviderDelegate { NotificationCenter.default.post(name: .HUDViewsChanged, object: self) } } -} -extension UIAlertController { - fileprivate convenience init(title: String, error: Error) { - - let message: String - - if let localizedError = error as? LocalizedError { - let sentenceFormat = NSLocalizedString("%@.", comment: "Appends a full-stop to a statement") - message = [localizedError.failureReason, localizedError.recoverySuggestion].compactMap({ $0 }).map({ - String(format: sentenceFormat, $0) - }).joined(separator: "\n") - } else { - message = String(describing: error) + func hudProvider(_ provider: HUDProvider, didReplaceViews views: [BaseHUDView]) { + DispatchQueue.main.async { + self.hudView?.removeNonStandardHUDViews() + for view in views { + view.isHidden = true + view.alpha = 0 + self.addViewToHUD(view) + } + NotificationCenter.default.post(name: .HUDViewsChanged, object: self) } - - self.init( - title: title, - message: message, - preferredStyle: .alert - ) - - addAction(UIAlertAction( - title: NSLocalizedString("OK", comment: "Button title to acknowledge error"), - style: .default, - handler: nil - )) } } From 6a9ce730e772d6841ee77bca93cbd8baeb240b15 Mon Sep 17 00:00:00 2001 From: katie disimone Date: Tue, 22 Jan 2019 13:38:52 -0800 Subject: [PATCH 29/56] update prep script for CGMBLEKit branch change --- prep_workspace.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prep_workspace.sh b/prep_workspace.sh index 6e3f409cf8..63a1e69f84 100644 --- a/prep_workspace.sh +++ b/prep_workspace.sh @@ -17,7 +17,7 @@ git reset HEAD cd Carthage/Checkouts cd LoopKit; git fetch; git checkout pumpmanager-updates; git pull; cd .. cd rileylink_ios; git fetch; git checkout omnipod-testing; git pull; cd .. -cd CGMBLEKit; git fetch; git checkout dev; git pull; cd .. +cd CGMBLEKit; git fetch; git checkout omnikit-testing; git pull; cd .. cd dexcom-share-client-swift; git fetch; git checkout carthage-recursive; git pull; cd .. cd G4ShareSpy; git fetch; git checkout fix-cartfile; git pull; cd .. cd ../.. From 849916da01e6dd06c1b8579a6ef8222cfe51eec5 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 29 Jan 2019 06:58:42 -0600 Subject: [PATCH 30/56] Updates for hud provider delegate change --- Loop/View Controllers/StatusTableViewController.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index 3ddc4a4d0d..833c3b58be 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -1105,8 +1105,6 @@ final class StatusTableViewController: ChartsTableViewController { let action = pumpManagerHUDProvider.didTapOnHUDView(hudSubView) { switch action { - case .showViewController(let vc): - self.navigationController?.pushViewController(vc, animated: true) case .presentViewController(let vc): self.present(vc, animated: true, completion: nil) case .openAppURL(let url): From 8a152ee80f77d669df0ee1d8b0400d1da20efe90 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 29 Jan 2019 23:31:39 -0600 Subject: [PATCH 31/56] Pumpmanager updates --- .../SettingsTableViewController.swift | 28 +++++++++++++------ .../StatusTableViewController.swift | 10 +++++++ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/Loop/View Controllers/SettingsTableViewController.swift b/Loop/View Controllers/SettingsTableViewController.swift index c0bdcaec70..6c5103212c 100644 --- a/Loop/View Controllers/SettingsTableViewController.swift +++ b/Loop/View Controllers/SettingsTableViewController.swift @@ -174,7 +174,6 @@ final class SettingsTableViewController: UITableViewController { cell.imageView?.image = pumpManager.smallImage cell.textLabel?.text = pumpManager.localizedTitle cell.detailTextLabel?.text = nil - cell.accessoryType = .disclosureIndicator return cell } else { let cell = tableView.dequeueReusableCell(withIdentifier: TextButtonTableViewCell.className, for: indexPath) @@ -193,9 +192,6 @@ final class SettingsTableViewController: UITableViewController { } cell.textLabel?.text = cgmManager.localizedTitle cell.detailTextLabel?.text = nil - if cgmManagerUI != nil { - cell.accessoryType = .disclosureIndicator - } return cell } else { let cell = tableView.dequeueReusableCell(withIdentifier: TextButtonTableViewCell.className, for: indexPath) @@ -333,7 +329,8 @@ final class SettingsTableViewController: UITableViewController { case .pump: switch PumpRow(rawValue: indexPath.row)! { case .pumpSettings: - if let settings = dataManager.pumpManager?.settingsViewController() { + if var settings = dataManager.pumpManager?.settingsViewController() { + settings.completionDelegate = self show(settings, sender: sender) } else { // Add new pump @@ -366,7 +363,9 @@ final class SettingsTableViewController: UITableViewController { case .cgm: if let cgmManager = dataManager.cgmManager as? CGMManagerUI { if let unit = dataManager.loopManager.glucoseStore.preferredUnit { - show(cgmManager.settingsViewController(for: unit), sender: sender) + var settings = cgmManager.settingsViewController(for: unit) + settings.completionDelegate = self + show(settings, sender: sender) } } else if dataManager.cgmManager is PumpManagerUI { // The pump manager is providing glucose, but allow reverting the CGM @@ -582,6 +581,14 @@ final class SettingsTableViewController: UITableViewController { } } +extension SettingsTableViewController: CompletionDelegate { + func completionNotifyingDidComplete(_ object: CompletionNotifying) { + if let vc = object as? UIViewController { + vc.dismiss(animated: true, completion: nil) + } + } +} + extension SettingsTableViewController: PumpManagerSetupViewControllerDelegate { func pumpManagerSetupViewController(_ pumpManagerSetupViewController: PumpManagerSetupViewController, didSetUpPumpManager pumpManager: PumpManagerUI) { @@ -603,8 +610,9 @@ extension SettingsTableViewController: PumpManagerSetupViewControllerDelegate { dataManager.loopManager.settings.maximumBolus = maxBolusUnits tableView.reloadRows(at: [[Section.configuration.rawValue, ConfigurationRow.deliveryLimits.rawValue]], with: .none) } - - show(pumpManager.settingsViewController(), sender: nil) + var settingsViewController = pumpManager.settingsViewController() + settingsViewController.completionDelegate = self + show(settingsViewController, sender: nil) dismiss(animated: true, completion: nil) } @@ -633,7 +641,9 @@ extension SettingsTableViewController: CGMManagerSetupViewControllerDelegate { func cgmManagerSetupViewController(_ cgmManagerSetupViewController: CGMManagerSetupViewController, didSetUpCGMManager cgmManager: CGMManagerUI) { dataManager.cgmManager = cgmManager tableView.selectRow(at: IndexPath(row: CGMRow.cgmSettings.rawValue, section: Section.cgm.rawValue), animated: false, scrollPosition: .none) - show(cgmManager.settingsViewController(for: dataManager.loopManager.glucoseStore.preferredUnit ?? .milligramsPerDeciliter), sender: nil) + var settings = cgmManager.settingsViewController(for: dataManager.loopManager.glucoseStore.preferredUnit ?? .milligramsPerDeciliter) + settings.completionDelegate = self + show(settings, sender: nil) dismiss(animated: true, completion: nil) } diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index 833c3b58be..5623e1df2a 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -1106,6 +1106,8 @@ final class StatusTableViewController: ChartsTableViewController { { switch action { case .presentViewController(let vc): + var completionNotifyingVC = vc + completionNotifyingVC.completionDelegate = self self.present(vc, animated: true, completion: nil) case .openAppURL(let url): UIApplication.shared.open(url) @@ -1114,6 +1116,14 @@ final class StatusTableViewController: ChartsTableViewController { } } +extension StatusTableViewController: CompletionDelegate { + func completionNotifyingDidComplete(_ object: CompletionNotifying) { + if let vc = object as? UIViewController { + vc.dismiss(animated: true, completion: nil) + } + } +} + extension StatusTableViewController: PumpManagerStatusObserver { func pumpManager(_ pumpManager: PumpManager, didUpdate status: PumpManagerStatus) { DispatchQueue.main.async { From dd2e2c3866eebcae42237f8cd3754c3583e659a5 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 29 Jan 2019 23:33:17 -0600 Subject: [PATCH 32/56] Update prep script --- prep_workspace.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/prep_workspace.sh b/prep_workspace.sh index 63a1e69f84..85c4d3d625 100644 --- a/prep_workspace.sh +++ b/prep_workspace.sh @@ -17,9 +17,9 @@ git reset HEAD cd Carthage/Checkouts cd LoopKit; git fetch; git checkout pumpmanager-updates; git pull; cd .. cd rileylink_ios; git fetch; git checkout omnipod-testing; git pull; cd .. -cd CGMBLEKit; git fetch; git checkout omnikit-testing; git pull; cd .. -cd dexcom-share-client-swift; git fetch; git checkout carthage-recursive; git pull; cd .. -cd G4ShareSpy; git fetch; git checkout fix-cartfile; git pull; cd .. +cd CGMBLEKit; git fetch; git checkout omnikit; git pull; cd .. +cd dexcom-share-client-swift; git fetch; git checkout omnikit; git pull; cd .. +cd G4ShareSpy; git fetch; git checkout omnikit; git pull; cd .. cd ../.. carthage build From a18cfb4505b2e61b09f336198b461a20c07a1fe7 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 29 Jan 2019 21:43:21 -0800 Subject: [PATCH 33/56] Fix permissions on prep workspace script --- prep_workspace.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 prep_workspace.sh diff --git a/prep_workspace.sh b/prep_workspace.sh old mode 100644 new mode 100755 From e22f4b047937dd852cca4b0d7b06ad16b7da380f Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 2 Feb 2019 15:49:52 -0800 Subject: [PATCH 34/56] Pumpmanager changes --- Common/Models/PumpManagerUI.swift | 3 --- Common/Models/StatusExtensionContext.swift | 9 +++++++++ Loop Status Extension/StatusViewController.swift | 5 +++-- Loop.xcodeproj/project.pbxproj | 12 ------------ Loop/Managers/PumpManager.swift | 2 -- .../View Controllers/StatusTableViewController.swift | 10 ++++++++-- LoopUI/Views/HUDView.swift | 6 +++--- 7 files changed, 23 insertions(+), 24 deletions(-) diff --git a/Common/Models/PumpManagerUI.swift b/Common/Models/PumpManagerUI.swift index 32b54f003f..a7b85eb5cb 100644 --- a/Common/Models/PumpManagerUI.swift +++ b/Common/Models/PumpManagerUI.swift @@ -8,13 +8,10 @@ import Foundation import LoopKitUI -import OmniKit -import OmniKitUI import MinimedKit import MinimedKitUI let allPumpManagerUIs: [PumpManagerUI.Type] = [ - OmnipodPumpManager.self, MinimedPumpManager.self ] diff --git a/Common/Models/StatusExtensionContext.swift b/Common/Models/StatusExtensionContext.swift index a02f5a33b4..2a5721b772 100644 --- a/Common/Models/StatusExtensionContext.swift +++ b/Common/Models/StatusExtensionContext.swift @@ -162,6 +162,11 @@ struct PumpManagerHUDViewsContext: RawRepresentable { self.pumpManagerHUDProvider = pumpManagerHUDProvider self.hudViews = nil } + + init(hudViews: [BaseHUDView]) { + self.hudViews = hudViews + pumpManagerHUDProvider = nil + } init?(rawValue: [String : Any]) { pumpManagerHUDProvider = nil @@ -218,6 +223,10 @@ struct StatusExtensionContext: RawRepresentable { if let rawPumpManagerHUDViewsContext = rawValue["pumpManagerHUDViewsContext"] as? PumpManagerHUDViewsContext.RawValue { pumpManagerHUDViewsContext = PumpManagerHUDViewsContext(rawValue: rawPumpManagerHUDViewsContext) + } else { + let reservoirView = ReservoirVolumeHUDView.instantiate() + let batteryView = BatteryLevelHUDView.instantiate() + pumpManagerHUDViewsContext = PumpManagerHUDViewsContext(hudViews: [reservoirView, batteryView]) } } diff --git a/Loop Status Extension/StatusViewController.swift b/Loop Status Extension/StatusViewController.swift index d59d38b673..663df1862f 100644 --- a/Loop Status Extension/StatusViewController.swift +++ b/Loop Status Extension/StatusViewController.swift @@ -189,8 +189,9 @@ class StatusViewController: UIViewController, NCWidgetProviding { } if let hudViewsContext = context.pumpManagerHUDViewsContext, - let hudViews = hudViewsContext.hudViews { - self.hudView.removeNonStandardHUDViews() + let hudViews = hudViewsContext.hudViews + { + self.hudView.removePumpManagerProvidedViews() for view in hudViews { view.stateColors = .pumpStatus self.hudView.addHUDView(view) diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj index 70b613486b..e6ec3fc837 100644 --- a/Loop.xcodeproj/project.pbxproj +++ b/Loop.xcodeproj/project.pbxproj @@ -296,8 +296,6 @@ C15713821DAC6983005BC4D2 /* MealBolusNightscoutTreatment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C15713811DAC6983005BC4D2 /* MealBolusNightscoutTreatment.swift */; }; C168C40621B0D53E00ADE90E /* MinimedKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C168C40521B0D53E00ADE90E /* MinimedKit.framework */; }; C168C40821B0D53E00ADE90E /* MinimedKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C168C40721B0D53E00ADE90E /* MinimedKitUI.framework */; }; - C168C40921B0D53E00ADE90E /* OmniKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1CB13A8213EE35800F9EEDA /* OmniKit.framework */; }; - C168C40A21B0D53E00ADE90E /* OmniKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1CB13AA213EE35800F9EEDA /* OmniKitUI.framework */; }; C178249A1E1999FA00D9D25C /* CaseCountable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C17824991E1999FA00D9D25C /* CaseCountable.swift */; }; C17824A01E19CF9800D9D25C /* GlucoseThresholdTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C178249F1E19CF9800D9D25C /* GlucoseThresholdTableViewController.swift */; }; C17824A31E19EAB600D9D25C /* recommend_temp_basal_start_very_low_end_high.json in Resources */ = {isa = PBXBuildFile; fileRef = C17824A21E19EAB600D9D25C /* recommend_temp_basal_start_very_low_end_high.json */; }; @@ -307,13 +305,10 @@ C18C8C511D5A351900E043FB /* NightscoutDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C18C8C501D5A351900E043FB /* NightscoutDataManager.swift */; }; C1C6591C1E1B1FDA0025CC58 /* recommend_temp_basal_dropping_then_rising.json in Resources */ = {isa = PBXBuildFile; fileRef = C1C6591B1E1B1FDA0025CC58 /* recommend_temp_basal_dropping_then_rising.json */; }; C1C73F0D1DE3D0270022FC89 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = C1C73F0F1DE3D0270022FC89 /* InfoPlist.strings */; }; - C1CB13A9213EE35800F9EEDA /* OmniKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1CB13A8213EE35800F9EEDA /* OmniKit.framework */; }; - C1CB13AB213EE35800F9EEDA /* OmniKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1CB13AA213EE35800F9EEDA /* OmniKitUI.framework */; }; C1FB428C217806A400FAB378 /* StateColorPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1FB428B217806A300FAB378 /* StateColorPalette.swift */; }; C1FB428D21791D2500FAB378 /* PumpManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C3B6F620BBCAA30026CAFA /* PumpManager.swift */; }; C1FB428F217921D600FAB378 /* PumpManagerUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1FB428E217921D600FAB378 /* PumpManagerUI.swift */; }; C1FB4290217922A100FAB378 /* PumpManagerUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1FB428E217921D600FAB378 /* PumpManagerUI.swift */; }; - C9886AE51E5B2FAD00473BB8 /* gallery.ckcomplication in Resources */ = {isa = PBXBuildFile; fileRef = C9886AE41E5B2FAD00473BB8 /* gallery.ckcomplication */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -850,7 +845,6 @@ C1CB13AA213EE35800F9EEDA /* OmniKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = OmniKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C1FB428B217806A300FAB378 /* StateColorPalette.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StateColorPalette.swift; sourceTree = ""; }; C1FB428E217921D600FAB378 /* PumpManagerUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PumpManagerUI.swift; sourceTree = ""; }; - C9886AE41E5B2FAD00473BB8 /* gallery.ckcomplication */ = {isa = PBXFileReference; lastKnownFileType = folder; path = gallery.ckcomplication; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -865,8 +859,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - C1CB13A9213EE35800F9EEDA /* OmniKit.framework in Frameworks */, - C1CB13AB213EE35800F9EEDA /* OmniKitUI.framework in Frameworks */, 4F7528941DFE1E9500C322D6 /* LoopUI.framework in Frameworks */, 434FB6461D68F1CD007B9C70 /* Amplitude.framework in Frameworks */, 43A8EC6F210E622700A81379 /* CGMBLEKitUI.framework in Frameworks */, @@ -920,8 +912,6 @@ files = ( C168C40621B0D53E00ADE90E /* MinimedKit.framework in Frameworks */, C168C40821B0D53E00ADE90E /* MinimedKitUI.framework in Frameworks */, - C168C40921B0D53E00ADE90E /* OmniKit.framework in Frameworks */, - C168C40A21B0D53E00ADE90E /* OmniKitUI.framework in Frameworks */, 4F7528951DFE1E9B00C322D6 /* LoopUI.framework in Frameworks */, 437AFEE520352591008C4892 /* NotificationCenter.framework in Frameworks */, ); @@ -1851,8 +1841,6 @@ "$(SRCROOT)/Carthage/Build/iOS/RileyLinkKitUI.framework", "$(SRCROOT)/Carthage/Build/iOS/LoopKitUI.framework", "$(SRCROOT)/Carthage/Build/iOS/MinimedKitUI.framework", - "$(SRCROOT)/Carthage/Build/iOS/OmniKit.framework", - "$(SRCROOT)/Carthage/Build/iOS/OmniKitUI.framework", "$(SRCROOT)/Carthage/Build/iOS/CGMBLEKitUI.framework", "$(SRCROOT)/Carthage/Build/iOS/ShareClientUI.framework", ); diff --git a/Loop/Managers/PumpManager.swift b/Loop/Managers/PumpManager.swift index a663ca71e2..60e172b4a6 100644 --- a/Loop/Managers/PumpManager.swift +++ b/Loop/Managers/PumpManager.swift @@ -8,11 +8,9 @@ import Foundation import LoopKit import MinimedKit -import OmniKit let allPumpManagers: [PumpManager.Type] = [ - OmnipodPumpManager.self, MinimedPumpManager.self ] diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index 5623e1df2a..97295c1a78 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -1060,7 +1060,7 @@ final class StatusTableViewController: ChartsTableViewController { private func configurePumpManagerHUDViews() { if let hudView = hudView { - hudView.removeNonStandardHUDViews() + hudView.removePumpManagerProvidedViews() if var pumpManagerHUDProvider = deviceManager.pumpManagerHUDProvider { let views = pumpManagerHUDProvider.createHUDViews() @@ -1068,6 +1068,12 @@ final class StatusTableViewController: ChartsTableViewController { addViewToHUD(view) } pumpManagerHUDProvider.delegate = self + } else { + let reservoirView = ReservoirVolumeHUDView.instantiate() + let batteryView = BatteryLevelHUDView.instantiate() + for view in [ reservoirView, batteryView] { + addViewToHUD(view) + } } NotificationCenter.default.post(name: .HUDViewsChanged, object: self) } @@ -1169,7 +1175,7 @@ extension StatusTableViewController: HUDProviderDelegate { func hudProvider(_ provider: HUDProvider, didReplaceViews views: [BaseHUDView]) { DispatchQueue.main.async { - self.hudView?.removeNonStandardHUDViews() + self.hudView?.removePumpManagerProvidedViews() for view in views { view.isHidden = true view.alpha = 0 diff --git a/LoopUI/Views/HUDView.swift b/LoopUI/Views/HUDView.swift index b874fb6eb1..03ad9b4812 100644 --- a/LoopUI/Views/HUDView.swift +++ b/LoopUI/Views/HUDView.swift @@ -28,10 +28,10 @@ public class HUDView: UIView, NibLoadable { self.addConstraints([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint]) } - public func removeNonStandardHUDViews() { + public func removePumpManagerProvidedViews() { let standardViews: [UIView] = [loopCompletionHUD, glucoseHUD, basalRateHUD] - let nonStandardHudViews = stackView.subviews.filter { !standardViews.contains($0) } - for view in nonStandardHudViews { + let pumpManagerViews = stackView.subviews.filter { !standardViews.contains($0) } + for view in pumpManagerViews { view.removeFromSuperview() } } From c0c2242bfbc3dbd4c28ad0cb639bec3e2b80f859 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 2 Feb 2019 16:15:01 -0800 Subject: [PATCH 35/56] Update to pumpmanager-updates --- Cartfile | 10 +++++----- Cartfile.resolved | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Cartfile b/Cartfile index b6a079cde4..0c66afc258 100644 --- a/Cartfile +++ b/Cartfile @@ -1,7 +1,7 @@ -github "LoopKit/LoopKit" "dev" -github "LoopKit/CGMBLEKit" "dev" +github "LoopKit/LoopKit" "pumpmanager-updates" +github "LoopKit/CGMBLEKit" "omnikit" github "i-schuetz/SwiftCharts" == 0.6.2 -github "LoopKit/dexcom-share-client-swift" == 1.0 -github "LoopKit/G4ShareSpy" == 1.0 -github "ps2/rileylink_ios" == 2.1.0 +github "LoopKit/dexcom-share-client-swift" "omnikit" +github "LoopKit/G4ShareSpy" "omnikit" +github "ps2/rileylink_ios" "pumpmanager-changes" github "LoopKit/Amplitude-iOS" "decreepify" diff --git a/Cartfile.resolved b/Cartfile.resolved index 59e713fb71..26707cb6b1 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,7 +1,7 @@ github "LoopKit/Amplitude-iOS" "2137d5fd44bf630ed33e1e72d7af6d8f8612f270" -github "LoopKit/CGMBLEKit" "894492e64d405188e09573f9f74adce8995369fa" -github "LoopKit/G4ShareSpy" "7479d0a269a1984eb6716a14293ceb148d6e9165" -github "LoopKit/LoopKit" "f130260f76d5e58a5984045484331a363e1b7080" -github "LoopKit/dexcom-share-client-swift" "7af726cb6c24a25abc9c056294578cff6cd9c245" +github "LoopKit/CGMBLEKit" "99ae2e08b0d209bf2887bf1a3b37903d15c6d1fc" +github "LoopKit/G4ShareSpy" "3842110ddb9405928e9d33adbaaed9382efe4469" +github "LoopKit/LoopKit" "cc38f544fab3be7845945c5a4105f785e0dfa703" +github "LoopKit/dexcom-share-client-swift" "e7f398a0b41aba35e3ebb04a4f5290d69d0e007f" github "i-schuetz/SwiftCharts" "0.6.2" -github "ps2/rileylink_ios" "72590877d063ef6fc2a5a564210ea679fa9bebf6" +github "ps2/rileylink_ios" "25d41ae7c49e51a4ca8ead096446cb9dbcc2f001" From 7cff7b459ff14f327cbc01776f40f9e0390b57a6 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 5 Feb 2019 08:18:26 -0600 Subject: [PATCH 36/56] Back out DEVELOPMENT_TEAM settings --- Loop.xcodeproj/project.pbxproj | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj index e6ec3fc837..6ca7fcfb73 100644 --- a/Loop.xcodeproj/project.pbxproj +++ b/Loop.xcodeproj/project.pbxproj @@ -2645,7 +2645,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Loop/Loop.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = Loop/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; "OTHER_SWIFT_FLAGS[sdk=iphonesimulator*]" = "-D IOS_SIMULATOR"; @@ -2662,7 +2662,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Loop/Loop.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = Loop/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER)"; @@ -2679,7 +2679,7 @@ CODE_SIGN_ENTITLEMENTS = "WatchApp Extension/WatchApp Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/watchOS"; INFOPLIST_FILE = "WatchApp Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; @@ -2703,7 +2703,7 @@ CODE_SIGN_ENTITLEMENTS = "WatchApp Extension/WatchApp Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/watchOS"; INFOPLIST_FILE = "WatchApp Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; @@ -2725,7 +2725,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = ""; IBSC_MODULE = WatchApp_Extension; INFOPLIST_FILE = WatchApp/Info.plist; @@ -2746,7 +2746,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = ""; IBSC_MODULE = WatchApp_Extension; INFOPLIST_FILE = WatchApp/Info.plist; @@ -2825,7 +2825,7 @@ CODE_SIGN_ENTITLEMENTS = "Loop Status Extension/Loop Status Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = "Loop Status Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).statuswidget"; @@ -2844,7 +2844,7 @@ CODE_SIGN_ENTITLEMENTS = "Loop Status Extension/Loop Status Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = "Loop Status Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).statuswidget"; From ebd1e2b2834a00a622726039fed1fe0feaff5a42 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 5 Feb 2019 13:40:37 -0600 Subject: [PATCH 37/56] Context object does not need HUDProvider reference --- .../Models}/PumpManager.swift | 0 Common/Models/PumpManagerUI.swift | 36 ++++++------------ Common/Models/StatusExtensionContext.swift | 37 ++++++------------- .../StatusViewController.swift | 18 ++++++--- Loop.xcodeproj/project.pbxproj | 2 +- .../Managers/StatusExtensionDataManager.swift | 2 +- 6 files changed, 38 insertions(+), 57 deletions(-) rename {Loop/Managers => Common/Models}/PumpManager.swift (100%) diff --git a/Loop/Managers/PumpManager.swift b/Common/Models/PumpManager.swift similarity index 100% rename from Loop/Managers/PumpManager.swift rename to Common/Models/PumpManager.swift diff --git a/Common/Models/PumpManagerUI.swift b/Common/Models/PumpManagerUI.swift index a7b85eb5cb..085af7eaf5 100644 --- a/Common/Models/PumpManagerUI.swift +++ b/Common/Models/PumpManagerUI.swift @@ -7,43 +7,31 @@ // import Foundation +import LoopKit import LoopKitUI import MinimedKit import MinimedKitUI -let allPumpManagerUIs: [PumpManagerUI.Type] = [ - MinimedPumpManager.self -] - -private let managersByIdentifier: [String: PumpManagerUI.Type] = allPumpManagerUIs.reduce(into: [:]) { (map, Type) in +private let managersByIdentifier: [String: PumpManagerUI.Type] = allPumpManagers.compactMap{ $0 as? PumpManagerUI.Type}.reduce(into: [:]) { (map, Type) in map[Type.managerIdentifier] = Type } -func PumpManagerUITypeFromRawValue(_ rawValue: [String: Any]) -> PumpManagerUI.Type? { - guard let managerIdentifier = rawValue["managerIdentifier"] as? String else { - return nil - } - - return managersByIdentifier[managerIdentifier] -} +typealias PumpManagerHUDViewsRawValue = [String: Any] -func PumpManagerHUDViewsFromRawValue(_ rawValue: [String: Any]) -> [BaseHUDView]? { +func PumpManagerHUDViewsFromRawValue(_ rawValue: PumpManagerHUDViewsRawValue) -> [BaseHUDView]? { guard let rawState = rawValue["hudProviderViews"] as? HUDProvider.HUDViewsRawState, - let Manager = PumpManagerUITypeFromRawValue(rawValue) + let managerIdentifier = rawValue["managerIdentifier"] as? String, + let manager = managersByIdentifier[managerIdentifier] else { return nil } - return Manager.createHUDViews(rawValue: rawState) + return manager.createHUDViews(rawValue: rawState) } -extension HUDProvider { - var rawHUDProviderViewsValue: [String: Any] { - return [ - "managerIdentifier": self.managerIdentifier, - "hudProviderViews": self.hudViewsRawState - ] - } +func PumpManagerHUDViewsRawValueFromHudProvider(_ hudProvider: HUDProvider) -> PumpManagerHUDViewsRawValue { + return [ + "managerIdentifier": hudProvider.managerIdentifier, + "hudProviderViews": hudProvider.hudViewsRawState + ] } - - diff --git a/Common/Models/StatusExtensionContext.swift b/Common/Models/StatusExtensionContext.swift index 2a5721b772..c838e258eb 100644 --- a/Common/Models/StatusExtensionContext.swift +++ b/Common/Models/StatusExtensionContext.swift @@ -154,35 +154,27 @@ extension PredictedGlucoseContext: RawRepresentable { struct PumpManagerHUDViewsContext: RawRepresentable { typealias RawValue = [String: Any] - - let hudViews: [BaseHUDView]? - let pumpManagerHUDProvider: HUDProvider? - - init(pumpManagerHUDProvider: HUDProvider) { - self.pumpManagerHUDProvider = pumpManagerHUDProvider - self.hudViews = nil + + let pumpManagerHUDViewsRawValue: PumpManagerHUDViewsRawValue + + var hudViews: [BaseHUDView]? { + return PumpManagerHUDViewsFromRawValue(pumpManagerHUDViewsRawValue) } - init(hudViews: [BaseHUDView]) { - self.hudViews = hudViews - pumpManagerHUDProvider = nil + init(pumpManagerHUDViewsRawValue: PumpManagerHUDViewsRawValue) { + self.pumpManagerHUDViewsRawValue = pumpManagerHUDViewsRawValue } - init?(rawValue: [String : Any]) { - pumpManagerHUDProvider = nil - if let hudViews = PumpManagerHUDViewsFromRawValue(rawValue) { - self.hudViews = hudViews + init?(rawValue: RawValue) { + if let pumpManagerHUDViewsRawValue = rawValue["pumpManagerHUDViewsRawValue"] as? PumpManagerHUDViewsRawValue { + self.pumpManagerHUDViewsRawValue = pumpManagerHUDViewsRawValue } else { return nil } } - var rawValue: [String : Any] { - if let pumpManagerHUDProvider = pumpManagerHUDProvider { - return pumpManagerHUDProvider.rawHUDProviderViewsValue - } else { - return [:] - } + var rawValue: RawValue { + return ["pumpManagerHUDViewsRawValue": pumpManagerHUDViewsRawValue] } } @@ -223,12 +215,7 @@ struct StatusExtensionContext: RawRepresentable { if let rawPumpManagerHUDViewsContext = rawValue["pumpManagerHUDViewsContext"] as? PumpManagerHUDViewsContext.RawValue { pumpManagerHUDViewsContext = PumpManagerHUDViewsContext(rawValue: rawPumpManagerHUDViewsContext) - } else { - let reservoirView = ReservoirVolumeHUDView.instantiate() - let batteryView = BatteryLevelHUDView.instantiate() - pumpManagerHUDViewsContext = PumpManagerHUDViewsContext(hudViews: [reservoirView, batteryView]) } - } var rawValue: RawValue { diff --git a/Loop Status Extension/StatusViewController.swift b/Loop Status Extension/StatusViewController.swift index 663df1862f..29176c2a2a 100644 --- a/Loop Status Extension/StatusViewController.swift +++ b/Loop Status Extension/StatusViewController.swift @@ -188,14 +188,20 @@ class StatusViewController: UIViewController, NCWidgetProviding { return } + let hudViews: [BaseHUDView] + if let hudViewsContext = context.pumpManagerHUDViewsContext, - let hudViews = hudViewsContext.hudViews + let contextHUDViews = hudViewsContext.hudViews { - self.hudView.removePumpManagerProvidedViews() - for view in hudViews { - view.stateColors = .pumpStatus - self.hudView.addHUDView(view) - } + hudViews = contextHUDViews + } else { + hudViews = [ReservoirVolumeHUDView.instantiate(), BatteryLevelHUDView.instantiate()] + } + + self.hudView.removePumpManagerProvidedViews() + for view in hudViews { + view.stateColors = .pumpStatus + self.hudView.addHUDView(view) } if let netBasal = context.netBasal { diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj index 6ca7fcfb73..58d69bbdf1 100644 --- a/Loop.xcodeproj/project.pbxproj +++ b/Loop.xcodeproj/project.pbxproj @@ -1205,7 +1205,6 @@ 43A567681C94880B00334FAC /* LoopDataManager.swift */, C18C8C501D5A351900E043FB /* NightscoutDataManager.swift */, 43C094491CACCC73001F6403 /* NotificationManager.swift */, - 43C3B6F620BBCAA30026CAFA /* PumpManager.swift */, 432E73CA1D24B3D6009AD15D /* RemoteDataManager.swift */, 430C1ABC1E5568A80067F1AE /* StatusChartsManager+LoopKit.swift */, 4F70C20F1DE8FAC5006380B7 /* StatusExtensionDataManager.swift */, @@ -1346,6 +1345,7 @@ 4FF4D0FF1E18374700846527 /* WatchContext.swift */, 4F11D3C120DD80B3006E072C /* WatchHistoricalGlucose.swift */, 4F7E8AC620E2AC0300AEA65E /* WatchPredictedGlucose.swift */, + 43C3B6F620BBCAA30026CAFA /* PumpManager.swift */, C1FB428E217921D600FAB378 /* PumpManagerUI.swift */, ); path = Models; diff --git a/Loop/Managers/StatusExtensionDataManager.swift b/Loop/Managers/StatusExtensionDataManager.swift index d598c8c9a1..e9a42cd6d2 100644 --- a/Loop/Managers/StatusExtensionDataManager.swift +++ b/Loop/Managers/StatusExtensionDataManager.swift @@ -114,7 +114,7 @@ final class StatusExtensionDataManager { } if let pumpManagerHUDProvider = dataManager.pumpManagerHUDProvider { - context.pumpManagerHUDViewsContext = PumpManagerHUDViewsContext(pumpManagerHUDProvider: pumpManagerHUDProvider) + context.pumpManagerHUDViewsContext = PumpManagerHUDViewsContext(pumpManagerHUDViewsRawValue: PumpManagerHUDViewsRawValueFromHudProvider(pumpManagerHUDProvider)) } completionHandler(context) From ba571a71fa376db3a441173d644c15176e54eac9 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 5 Feb 2019 14:06:24 -0600 Subject: [PATCH 38/56] Include dose in enactBolus completion --- Loop/Managers/DeviceDataManager.swift | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index 4f1f857a6e..08aef1c23d 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -364,16 +364,15 @@ extension DeviceDataManager { return } - var requestedDose: DoseEntry? pumpManager.enactBolus(units: units, at: startDate, willRequest: { (dose) in self.loopManager.addRequestedBolus(dose: dose, completion: nil) - requestedDose = dose - }) { (error) in - if let error = error { + }) { (result) in + switch result { + case .failure(let error): self.log.error(error) NotificationManager.sendBolusFailureNotification(for: error, units: units, at: startDate) completion(error) - } else if let dose = requestedDose { + case .success(let dose): self.loopManager.addConfirmedBolus(dose) { completion(nil) } From e54617a049ae45758858d8c364244de72a6913dd Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 5 Feb 2019 19:47:19 -0600 Subject: [PATCH 39/56] Bump dependency revisions --- Cartfile.resolved | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cartfile.resolved b/Cartfile.resolved index 26707cb6b1..fcc71bbc40 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,7 +1,7 @@ github "LoopKit/Amplitude-iOS" "2137d5fd44bf630ed33e1e72d7af6d8f8612f270" github "LoopKit/CGMBLEKit" "99ae2e08b0d209bf2887bf1a3b37903d15c6d1fc" github "LoopKit/G4ShareSpy" "3842110ddb9405928e9d33adbaaed9382efe4469" -github "LoopKit/LoopKit" "cc38f544fab3be7845945c5a4105f785e0dfa703" +github "LoopKit/LoopKit" "faf381f76583a56b30541f1c63814bf68347fa48" github "LoopKit/dexcom-share-client-swift" "e7f398a0b41aba35e3ebb04a4f5290d69d0e007f" github "i-schuetz/SwiftCharts" "0.6.2" -github "ps2/rileylink_ios" "25d41ae7c49e51a4ca8ead096446cb9dbcc2f001" +github "ps2/rileylink_ios" "2f1454d0fa0e319daf5db5d55781b5c24c76ee71" From 6a24216e27e3749ad62c9e36e9878137fa6b5d60 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Thu, 7 Feb 2019 16:58:46 -0600 Subject: [PATCH 40/56] Update HUD set of views only on PumpManager change --- .../Managers/StatusExtensionDataManager.swift | 2 +- .../SettingsTableViewController.swift | 19 +------ .../StatusTableViewController.swift | 55 +------------------ 3 files changed, 5 insertions(+), 71 deletions(-) diff --git a/Loop/Managers/StatusExtensionDataManager.swift b/Loop/Managers/StatusExtensionDataManager.swift index e9a42cd6d2..f22b350059 100644 --- a/Loop/Managers/StatusExtensionDataManager.swift +++ b/Loop/Managers/StatusExtensionDataManager.swift @@ -18,7 +18,7 @@ final class StatusExtensionDataManager { self.deviceManager = deviceDataManager NotificationCenter.default.addObserver(self, selector: #selector(update(_:)), name: .LoopDataUpdated, object: deviceDataManager.loopManager) - NotificationCenter.default.addObserver(self, selector: #selector(update(_:)), name: .HUDViewsChanged, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(update(_:)), name: .PumpManagerChanged, object: nil) } fileprivate var defaults: UserDefaults? { diff --git a/Loop/View Controllers/SettingsTableViewController.swift b/Loop/View Controllers/SettingsTableViewController.swift index 6c5103212c..80b54d7117 100644 --- a/Loop/View Controllers/SettingsTableViewController.swift +++ b/Loop/View Controllers/SettingsTableViewController.swift @@ -110,9 +110,10 @@ final class SettingsTableViewController: UITableViewController { } } - func configuredSetupViewController(for pumpManager: PumpManagerUI.Type) -> (UIViewController & PumpManagerSetupViewController) { + func configuredSetupViewController(for pumpManager: PumpManagerUI.Type) -> (UIViewController & PumpManagerSetupViewController & CompletionNotifying) { var setupViewController = pumpManager.setupViewController() setupViewController.setupDelegate = self + setupViewController.completionDelegate = self setupViewController.basalSchedule = dataManager.loopManager.basalRateSchedule setupViewController.maxBolusUnits = dataManager.loopManager.settings.maximumBolus setupViewController.maxBasalRateUnitsPerHour = dataManager.loopManager.settings.maximumBasalRatePerHour @@ -610,14 +611,6 @@ extension SettingsTableViewController: PumpManagerSetupViewControllerDelegate { dataManager.loopManager.settings.maximumBolus = maxBolusUnits tableView.reloadRows(at: [[Section.configuration.rawValue, ConfigurationRow.deliveryLimits.rawValue]], with: .none) } - var settingsViewController = pumpManager.settingsViewController() - settingsViewController.completionDelegate = self - show(settingsViewController, sender: nil) - dismiss(animated: true, completion: nil) - } - - func pumpManagerSetupViewControllerDidCancel(_ pumpManagerSetupViewController: PumpManagerSetupViewController) { - dismiss(animated: true, completion: nil) } } @@ -626,6 +619,7 @@ extension SettingsTableViewController: CGMManagerSetupViewControllerDelegate { fileprivate func setupCGMManager(_ CGMManagerType: CGMManagerUI.Type, indexPath: IndexPath) { if var setupViewController = CGMManagerType.setupViewController() { setupViewController.setupDelegate = self + setupViewController.completionDelegate = self present(setupViewController, animated: true, completion: nil) } else { completeCGMManagerSetup(CGMManagerType.init(rawState: [:]), indexPath: indexPath) @@ -641,13 +635,6 @@ extension SettingsTableViewController: CGMManagerSetupViewControllerDelegate { func cgmManagerSetupViewController(_ cgmManagerSetupViewController: CGMManagerSetupViewController, didSetUpCGMManager cgmManager: CGMManagerUI) { dataManager.cgmManager = cgmManager tableView.selectRow(at: IndexPath(row: CGMRow.cgmSettings.rawValue, section: Section.cgm.rawValue), animated: false, scrollPosition: .none) - var settings = cgmManager.settingsViewController(for: dataManager.loopManager.glucoseStore.preferredUnit ?? .milligramsPerDeciliter) - settings.completionDelegate = self - show(settings, sender: nil) - dismiss(animated: true, completion: nil) - } - - func cgmManagerSetupViewControllerDidCancel(_ cgmManagerSetupViewController: CGMManagerSetupViewController) { dismiss(animated: true, completion: nil) } } diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index 97295c1a78..20628654e6 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -1061,13 +1061,12 @@ final class StatusTableViewController: ChartsTableViewController { private func configurePumpManagerHUDViews() { if let hudView = hudView { hudView.removePumpManagerProvidedViews() - if var pumpManagerHUDProvider = deviceManager.pumpManagerHUDProvider + if let pumpManagerHUDProvider = deviceManager.pumpManagerHUDProvider { let views = pumpManagerHUDProvider.createHUDViews() for view in views { addViewToHUD(view) } - pumpManagerHUDProvider.delegate = self } else { let reservoirView = ReservoirVolumeHUDView.instantiate() let batteryView = BatteryLevelHUDView.instantiate() @@ -1075,7 +1074,6 @@ final class StatusTableViewController: ChartsTableViewController { addViewToHUD(view) } } - NotificationCenter.default.post(name: .HUDViewsChanged, object: self) } } @@ -1138,54 +1136,3 @@ extension StatusTableViewController: PumpManagerStatusObserver { } } } - -extension StatusTableViewController: HUDProviderDelegate { - - func hudProvider(_ provider: HUDProvider, didAddViews views: [BaseHUDView]) { - DispatchQueue.main.async { - for view in views { - view.isHidden = true - view.alpha = 0 - self.addViewToHUD(view) - } - UIView.animate(withDuration: 1, animations: { - for view in views { - view.isHidden = false - view.alpha = 1 - } - }) - NotificationCenter.default.post(name: .HUDViewsChanged, object: self) - } - } - - func hudProvider(_ provider: HUDProvider, didRemoveViews views: [BaseHUDView]) { - DispatchQueue.main.async { - UIView.animate(withDuration: 1, animations: { - for view in views { - view.alpha = 0 - } - }, completion: { (didFinish) in - for view in views { - view.removeFromSuperview() - } - }) - NotificationCenter.default.post(name: .HUDViewsChanged, object: self) - } - } - - func hudProvider(_ provider: HUDProvider, didReplaceViews views: [BaseHUDView]) { - DispatchQueue.main.async { - self.hudView?.removePumpManagerProvidedViews() - for view in views { - view.isHidden = true - view.alpha = 0 - self.addViewToHUD(view) - } - NotificationCenter.default.post(name: .HUDViewsChanged, object: self) - } - } -} - -extension Notification.Name { - static let HUDViewsChanged = Notification.Name(rawValue: "com.loopKit.notification.HUDViewsChanged") -} From 8a893b64051bb749c0ade9ee5272d755a12d9e49 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Thu, 7 Feb 2019 17:02:58 -0600 Subject: [PATCH 41/56] Remove unused file --- Loop/Managers/PumpManagerState.swift | 38 ---------------------------- 1 file changed, 38 deletions(-) delete mode 100644 Loop/Managers/PumpManagerState.swift diff --git a/Loop/Managers/PumpManagerState.swift b/Loop/Managers/PumpManagerState.swift deleted file mode 100644 index 20342edb09..0000000000 --- a/Loop/Managers/PumpManagerState.swift +++ /dev/null @@ -1,38 +0,0 @@ -// -// PumpManagerState.swift -// Loop -// -// Copyright © 2018 LoopKit Authors. All rights reserved. -// - -import Foundation -import LoopKit -import MinimedKit -import OmniKit - - -let allPumpManagers: [String: PumpManager.Type] = [ - OmnipodPumpManager.managerIdentifier: OmnipodPumpManager.self - //MinimedPumpManager.managerIdentifier: MinimedPumpManager.self -] - - -func PumpManagerFromRawValue(_ rawValue: [String: Any]) -> PumpManager? { - guard let managerIdentifier = rawValue["managerIdentifier"] as? String, - let rawState = rawValue["state"] as? PumpManager.RawStateValue, - let Manager = allPumpManagers[managerIdentifier] - else { - return nil - } - - return Manager.init(rawState: rawState) -} - -extension PumpManager { - var rawValue: [String: Any] { - return [ - "managerIdentifier": type(of: self).managerIdentifier, - "state": self.rawState - ] - } -} From 23842de14de1a824066f5003e00efc1c807085f4 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Thu, 7 Feb 2019 18:06:54 -0600 Subject: [PATCH 42/56] synchronize deviceDataManager.pumpManagerStatus access --- Loop/Managers/DeviceDataManager.swift | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index 08aef1c23d..9d9427cc01 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -68,10 +68,18 @@ final class DeviceDataManager { UserDefaults.appGroup.cgmManager = cgmManager } } + + private let lockedPumpManagerStatus: Locked = Locked(nil) var pumpManagerStatus: PumpManagerStatus? { - didSet { - if let status = pumpManagerStatus { + get { + return lockedPumpManagerStatus.value + } + set { + let oldValue = lockedPumpManagerStatus.value + lockedPumpManagerStatus.value = newValue + + if let status = newValue { loopManager.doseStore.device = status.device From 9a729c6d2aaa45266a556dfe1ed17dfc7614e688 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Thu, 7 Feb 2019 18:07:30 -0600 Subject: [PATCH 43/56] Bump dep revisions --- Cartfile.resolved | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cartfile.resolved b/Cartfile.resolved index fcc71bbc40..109144f12e 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,7 +1,7 @@ github "LoopKit/Amplitude-iOS" "2137d5fd44bf630ed33e1e72d7af6d8f8612f270" -github "LoopKit/CGMBLEKit" "99ae2e08b0d209bf2887bf1a3b37903d15c6d1fc" -github "LoopKit/G4ShareSpy" "3842110ddb9405928e9d33adbaaed9382efe4469" -github "LoopKit/LoopKit" "faf381f76583a56b30541f1c63814bf68347fa48" -github "LoopKit/dexcom-share-client-swift" "e7f398a0b41aba35e3ebb04a4f5290d69d0e007f" +github "LoopKit/CGMBLEKit" "3c8a3b0e919fbfa5e95f16c6c0ca02557571b6a6" +github "LoopKit/G4ShareSpy" "e5161f7a3c3307a935980b37220f0e3e4ebeefb1" +github "LoopKit/LoopKit" "59e1db1ec893de44cbbc7895540f1d0056dad68b" +github "LoopKit/dexcom-share-client-swift" "690414cd39c9b7a3e5074fc86c4dd0cfe85c6bb3" github "i-schuetz/SwiftCharts" "0.6.2" -github "ps2/rileylink_ios" "2f1454d0fa0e319daf5db5d55781b5c24c76ee71" +github "ps2/rileylink_ios" "d7db293ead3606cd0890c5523697b0e398dd553a" From 509573c3b1c85a333d925e5e3611cf4f0ad79d43 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Thu, 7 Feb 2019 18:14:29 -0600 Subject: [PATCH 44/56] Remove unused files --- Loop.xcodeproj/project.pbxproj | 4 ---- prep_workspace.sh | 30 ------------------------------ 2 files changed, 34 deletions(-) delete mode 100755 prep_workspace.sh diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj index 58d69bbdf1..019ce29f00 100644 --- a/Loop.xcodeproj/project.pbxproj +++ b/Loop.xcodeproj/project.pbxproj @@ -841,8 +841,6 @@ C18C8C501D5A351900E043FB /* NightscoutDataManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NightscoutDataManager.swift; sourceTree = ""; }; C1C108C22152F46D00EA5165 /* CGMBLEKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CGMBLEKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C1C6591B1E1B1FDA0025CC58 /* recommend_temp_basal_dropping_then_rising.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = recommend_temp_basal_dropping_then_rising.json; sourceTree = ""; }; - C1CB13A8213EE35800F9EEDA /* OmniKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = OmniKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - C1CB13AA213EE35800F9EEDA /* OmniKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = OmniKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C1FB428B217806A300FAB378 /* StateColorPalette.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StateColorPalette.swift; sourceTree = ""; }; C1FB428E217921D600FAB378 /* PumpManagerUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PumpManagerUI.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -1400,8 +1398,6 @@ C168C40721B0D53E00ADE90E /* MinimedKitUI.framework */, C1C108C22152F46D00EA5165 /* CGMBLEKitUI.framework */, 434FB6451D68F1CD007B9C70 /* Amplitude.framework */, - C1CB13A8213EE35800F9EEDA /* OmniKit.framework */, - C1CB13AA213EE35800F9EEDA /* OmniKitUI.framework */, 4344628420A7A3BE00C4BE6F /* CGMBLEKit.framework */, 438A95A71D8B9B24009D12E1 /* CGMBLEKit.framework */, 43A8EC6E210E622600A81379 /* CGMBLEKitUI.framework */, diff --git a/prep_workspace.sh b/prep_workspace.sh deleted file mode 100755 index 85c4d3d625..0000000000 --- a/prep_workspace.sh +++ /dev/null @@ -1,30 +0,0 @@ -set -x -set -u -set -e - -echo "RUN WITH: sh prep_workspace.sh, in the loop-priv folder." - -# Uncomment if you have not already cloned the repo: -# git clone https://github.com/ps2/loop-priv.git -# cd loop-priv - -git checkout omnikit - -carthage bootstrap --use-submodules --no-build - -git reset HEAD - -cd Carthage/Checkouts -cd LoopKit; git fetch; git checkout pumpmanager-updates; git pull; cd .. -cd rileylink_ios; git fetch; git checkout omnipod-testing; git pull; cd .. -cd CGMBLEKit; git fetch; git checkout omnikit; git pull; cd .. -cd dexcom-share-client-swift; git fetch; git checkout omnikit; git pull; cd .. -cd G4ShareSpy; git fetch; git checkout omnikit; git pull; cd .. -cd ../.. -carthage build - -echo "Open Xcode, and select File -> New -> Workspace and create "Loop.xcworkspace" in the loop-priv directory just created. -Select File -> Add Files to "Loop"... to add the Loop.xcodeproj project. -Repeatedly select File -> Add Files to "Loop"... to add the .xcodeproj file for each project within the Carthage/Checkouts directory. -run 'carthage build' at the top level Loop directory -Build Loop in Xcode!" From 26e0ea54703153880a4d0667df77666ca7ed8fa1 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Thu, 7 Feb 2019 22:20:27 -0600 Subject: [PATCH 45/56] Remove unneeded reloadSections calls --- Loop/View Controllers/SettingsTableViewController.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/Loop/View Controllers/SettingsTableViewController.swift b/Loop/View Controllers/SettingsTableViewController.swift index 80b54d7117..9388a4b6ae 100644 --- a/Loop/View Controllers/SettingsTableViewController.swift +++ b/Loop/View Controllers/SettingsTableViewController.swift @@ -34,7 +34,6 @@ final class SettingsTableViewController: UITableViewController { _ = tableView(tableView, willDeselectRowAt: indexPath) } } - tableView.reloadSections([Section.pump.rawValue], with: .none) super.viewWillAppear(animated) } @@ -594,7 +593,6 @@ extension SettingsTableViewController: CompletionDelegate { extension SettingsTableViewController: PumpManagerSetupViewControllerDelegate { func pumpManagerSetupViewController(_ pumpManagerSetupViewController: PumpManagerSetupViewController, didSetUpPumpManager pumpManager: PumpManagerUI) { dataManager.pumpManager = pumpManager - tableView.reloadSections([Section.pump.rawValue], with: .none) tableView.selectRow(at: IndexPath(row: PumpRow.pumpSettings.rawValue, section: Section.pump.rawValue), animated: false, scrollPosition: .none) if let basalRateSchedule = pumpManagerSetupViewController.basalSchedule { From 14ae518f785de8421e4f0db828b19ad711bc219d Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Fri, 8 Feb 2019 12:01:13 -0600 Subject: [PATCH 46/56] Fix build issue when carthage is run from Xcode --- Loop.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj index 019ce29f00..4422013483 100644 --- a/Loop.xcodeproj/project.pbxproj +++ b/Loop.xcodeproj/project.pbxproj @@ -1801,7 +1801,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ -f $PROJECT_DIR/.gitmodules ]; then\n echo \"Skipping checkout due to presence of .gitmodules file\"\n if [ $ACTION = \"install\" ]; then\n echo \"You're installing: Make sure to keep all submodules up-to-date and run carthage build after changes.\"\n fi\nelse\n echo \"Bootstrapping carthage dependencies\"\n /usr/local/bin/carthage bootstrap --project-directory \"$SRCROOT\" --cache-builds\nfi"; + shellScript = "if [ -f $PROJECT_DIR/.gitmodules ]; then\n echo \"Skipping checkout due to presence of .gitmodules file\"\n if [ $ACTION = \"install\" ]; then\n echo \"You're installing: Make sure to keep all submodules up-to-date and run carthage build after changes.\"\n fi\nelse\n echo \"Bootstrapping carthage dependencies\"\n unset LLVM_TARGET_TRIPLE_SUFFIX\n /usr/local/bin/carthage bootstrap --project-directory \"$SRCROOT\" --cache-builds\nfi\n"; }; 432CF88220D8BCD90066B889 /* Homebrew & Carthage Setup */ = { isa = PBXShellScriptBuildPhase; From 995c3e271901850f6f8c7cd252571c0db5765714 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 11 Feb 2019 13:28:58 -0600 Subject: [PATCH 47/56] Use bolus end date to clear lastRequestedBolus --- Loop/Managers/LoopDataManager.swift | 4 ++-- Loop/View Controllers/SettingsTableViewController.swift | 2 +- Loop/View Controllers/StatusTableViewController.swift | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Loop/Managers/LoopDataManager.swift b/Loop/Managers/LoopDataManager.swift index a05e91a441..8e4602317c 100644 --- a/Loop/Managers/LoopDataManager.swift +++ b/Loop/Managers/LoopDataManager.swift @@ -490,7 +490,7 @@ extension LoopDataManager { self.insulinEffect = nil // Expire any bolus values now represented in the insulin data // TODO: Ask pumpManager if dose represented in data - if let bolusDate = self.lastRequestedBolus?.startDate, bolusDate.timeIntervalSinceNow < TimeInterval(minutes: -5) { + if let bolusEndDate = self.lastRequestedBolus?.endDate, bolusEndDate < Date() { self.lastRequestedBolus = nil } } @@ -519,7 +519,7 @@ extension LoopDataManager { self.insulinEffect = nil // Expire any bolus values now represented in the insulin data // TODO: Ask pumpManager if dose represented in data - if areStoredValuesContinuous, let bolusDate = self.lastRequestedBolus?.startDate, bolusDate.timeIntervalSinceNow < TimeInterval(minutes: -5) { + if areStoredValuesContinuous, let bolusEndDate = self.lastRequestedBolus?.endDate, bolusEndDate < Date() { self.lastRequestedBolus = nil } diff --git a/Loop/View Controllers/SettingsTableViewController.swift b/Loop/View Controllers/SettingsTableViewController.swift index 9388a4b6ae..7f054a3b48 100644 --- a/Loop/View Controllers/SettingsTableViewController.swift +++ b/Loop/View Controllers/SettingsTableViewController.swift @@ -563,7 +563,7 @@ final class SettingsTableViewController: UITableViewController { case .loop: break case .pump: - tableView.reloadSections([Section.pump.rawValue], with: .none) + tableView.reloadSections([Section.pump.rawValue], with: .fade) tableView.reloadRows(at: [[Section.cgm.rawValue, CGMRow.cgmSettings.rawValue]], with: .fade) case .cgm: tableView.reloadRows(at: [indexPath], with: .fade) diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index 20628654e6..0e8a04a90f 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -77,7 +77,7 @@ final class StatusTableViewController: ChartsTableViewController { self?.hudView?.loopCompletionHUD.loopInProgress = true } }, - notificationCenter.addObserver(forName: .PumpManagerChanged, object: deviceManager, queue: OperationQueue.main) { [weak self] (notification: Notification) in + notificationCenter.addObserver(forName: .PumpManagerChanged, object: deviceManager, queue: nil) { [weak self] (notification: Notification) in DispatchQueue.main.async { self?.configurePumpManagerHUDViews() } From 83b1e2e9613b5d55ea406e2015deb1d5d6f39252 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 11 Feb 2019 13:44:18 -0600 Subject: [PATCH 48/56] present instead of show settings vc --- Loop/View Controllers/SettingsTableViewController.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Loop/View Controllers/SettingsTableViewController.swift b/Loop/View Controllers/SettingsTableViewController.swift index 7f054a3b48..c7cadabe14 100644 --- a/Loop/View Controllers/SettingsTableViewController.swift +++ b/Loop/View Controllers/SettingsTableViewController.swift @@ -331,7 +331,7 @@ final class SettingsTableViewController: UITableViewController { case .pumpSettings: if var settings = dataManager.pumpManager?.settingsViewController() { settings.completionDelegate = self - show(settings, sender: sender) + present(settings, animated: true) } else { // Add new pump let pumpManagers = allPumpManagers.compactMap({ $0 as? PumpManagerUI.Type }) @@ -365,7 +365,7 @@ final class SettingsTableViewController: UITableViewController { if let unit = dataManager.loopManager.glucoseStore.preferredUnit { var settings = cgmManager.settingsViewController(for: unit) settings.completionDelegate = self - show(settings, sender: sender) + present(settings, animated: true) } } else if dataManager.cgmManager is PumpManagerUI { // The pump manager is providing glucose, but allow reverting the CGM From 82e66f061a5de4b378c93b350f9d41d412b56747 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 11 Feb 2019 13:58:48 -0600 Subject: [PATCH 49/56] small refactorings --- Loop.xcodeproj/project.pbxproj | 16 ++++++++-------- Loop/Managers/DeviceDataManager.swift | 2 +- Loop/Managers/LoopDataManager.swift | 2 +- .../SettingsTableViewController.swift | 8 ++------ LoopUI/Views/HUDView.swift | 14 ++++++-------- 5 files changed, 18 insertions(+), 24 deletions(-) diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj index 4422013483..319083d9c4 100644 --- a/Loop.xcodeproj/project.pbxproj +++ b/Loop.xcodeproj/project.pbxproj @@ -2641,7 +2641,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Loop/Loop.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; INFOPLIST_FILE = Loop/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; "OTHER_SWIFT_FLAGS[sdk=iphonesimulator*]" = "-D IOS_SIMULATOR"; @@ -2658,7 +2658,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Loop/Loop.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; INFOPLIST_FILE = Loop/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER)"; @@ -2675,7 +2675,7 @@ CODE_SIGN_ENTITLEMENTS = "WatchApp Extension/WatchApp Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/watchOS"; INFOPLIST_FILE = "WatchApp Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; @@ -2699,7 +2699,7 @@ CODE_SIGN_ENTITLEMENTS = "WatchApp Extension/WatchApp Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/watchOS"; INFOPLIST_FILE = "WatchApp Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; @@ -2721,7 +2721,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; FRAMEWORK_SEARCH_PATHS = ""; IBSC_MODULE = WatchApp_Extension; INFOPLIST_FILE = WatchApp/Info.plist; @@ -2742,7 +2742,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; FRAMEWORK_SEARCH_PATHS = ""; IBSC_MODULE = WatchApp_Extension; INFOPLIST_FILE = WatchApp/Info.plist; @@ -2821,7 +2821,7 @@ CODE_SIGN_ENTITLEMENTS = "Loop Status Extension/Loop Status Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; INFOPLIST_FILE = "Loop Status Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).statuswidget"; @@ -2840,7 +2840,7 @@ CODE_SIGN_ENTITLEMENTS = "Loop Status Extension/Loop Status Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = UY678SP37Q; INFOPLIST_FILE = "Loop Status Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).statuswidget"; diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index 9d9427cc01..c615e01e2b 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -373,7 +373,7 @@ extension DeviceDataManager { } pumpManager.enactBolus(units: units, at: startDate, willRequest: { (dose) in - self.loopManager.addRequestedBolus(dose: dose, completion: nil) + self.loopManager.addRequestedBolus(dose, completion: nil) }) { (result) in switch result { case .failure(let error): diff --git a/Loop/Managers/LoopDataManager.swift b/Loop/Managers/LoopDataManager.swift index 8e4602317c..8e2c60c512 100644 --- a/Loop/Managers/LoopDataManager.swift +++ b/Loop/Managers/LoopDataManager.swift @@ -452,7 +452,7 @@ extension LoopDataManager { /// /// - Parameters: /// - dose: The DoseEntry representing the requested bolus - func addRequestedBolus(dose: DoseEntry, completion: (() -> Void)?) { + func addRequestedBolus(_ dose: DoseEntry, completion: (() -> Void)?) { dataAccessQueue.async { self.lastRequestedBolus = dose self.notify(forChange: .bolus) diff --git a/Loop/View Controllers/SettingsTableViewController.swift b/Loop/View Controllers/SettingsTableViewController.swift index c7cadabe14..d60733f335 100644 --- a/Loop/View Controllers/SettingsTableViewController.swift +++ b/Loop/View Controllers/SettingsTableViewController.swift @@ -130,13 +130,9 @@ final class SettingsTableViewController: UITableViewController { case .loop: return LoopRow.count case .pump: - if dataManager.pumpManager != nil { - return PumpRow.count - } else { - return 1 - } + return PumpRow.count case .cgm: - return 1 + return CGMRow.count case .configuration: return ConfigurationRow.count case .services: diff --git a/LoopUI/Views/HUDView.swift b/LoopUI/Views/HUDView.swift index 03ad9b4812..3dc832c4a8 100644 --- a/LoopUI/Views/HUDView.swift +++ b/LoopUI/Views/HUDView.swift @@ -37,16 +37,14 @@ public class HUDView: UIView, NibLoadable { } public func addHUDView(_ viewToAdd: BaseHUDView) { - var insertIndex = 0 - for view in stackView.arrangedSubviews { - if let hudView = view as? BaseHUDView { - if viewToAdd.orderPriority <= hudView.orderPriority { - break - } + let insertIndex = stackView.arrangedSubviews.firstIndex { (view) -> Bool in + guard let hudView = view as? BaseHUDView else { + return false } - insertIndex += 1 + return viewToAdd.orderPriority <= hudView.orderPriority } - stackView.insertArrangedSubview(viewToAdd, at: insertIndex) + + stackView.insertArrangedSubview(viewToAdd, at: insertIndex ?? stackView.arrangedSubviews.count) } public override init(frame: CGRect) { From 4f652a8d56e2ce2e055154188d56d3b239e1565e Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Wed, 13 Feb 2019 10:52:49 -0600 Subject: [PATCH 50/56] Improvements from @mpangburn's review --- Loop/Managers/DeviceDataManager.swift | 8 +--- .../StatusTableViewController.swift | 48 +++++++++---------- 2 files changed, 24 insertions(+), 32 deletions(-) diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index c615e01e2b..00fc6321ae 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -22,12 +22,8 @@ final class DeviceDataManager { if cgmManager is PumpManagerUI { cgmManager = nil } - - if let pumpManager = pumpManager { - pumpManagerHUDProvider = pumpManager.hudProvider() - } else { - pumpManagerHUDProvider = nil - } + + pumpManagerHUDProvider = pumpManager?.hudProvider() setupPump() diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index 0e8a04a90f..ff30f0a533 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -829,34 +829,30 @@ final class StatusTableViewController: ChartsTableViewController { tableView.deselectRow(at: indexPath, animated: true) switch statusRowMode { - case .recommendedTempBasal(tempBasal: let tempBasal, at: let date, enacting: let enacting): - if !enacting { - self.updateHUDandStatusRows(statusRowMode: .recommendedTempBasal(tempBasal: tempBasal, at: date, enacting: true), newSize: nil, animated: true) - - self.deviceManager.loopManager.enactRecommendedTempBasal { (error) in - DispatchQueue.main.async { - self.updateHUDandStatusRows(statusRowMode: .hidden, newSize: nil, animated: true) - - if let error = error { - self.deviceManager.logger.addError(error, fromSource: "TempBasal") - self.present(UIAlertController(with: error), animated: true) - } else { - self.refreshContext.update(with: .status) - self.log.debug("[reloadData] after manually enacting temp basal") - self.reloadData() - } + case .recommendedTempBasal(tempBasal: let tempBasal, at: let date, enacting: let enacting) where !enacting: + self.updateHUDandStatusRows(statusRowMode: .recommendedTempBasal(tempBasal: tempBasal, at: date, enacting: true), newSize: nil, animated: true) + + self.deviceManager.loopManager.enactRecommendedTempBasal { (error) in + DispatchQueue.main.async { + self.updateHUDandStatusRows(statusRowMode: .hidden, newSize: nil, animated: true) + + if let error = error { + self.deviceManager.logger.addError(error, fromSource: "TempBasal") + self.present(UIAlertController(with: error), animated: true) + } else { + self.refreshContext.update(with: .status) + self.log.debug("[reloadData] after manually enacting temp basal") + self.reloadData() } } } - case .pumpSuspended(let resuming): - if !resuming { - self.updateHUDandStatusRows(statusRowMode: .pumpSuspended(resuming: true) , newSize: nil, animated: true) - self.deviceManager.pumpManager?.resumeDelivery() { (error) in - DispatchQueue.main.async { - if let error = error { - let alert = UIAlertController(with: error, title: NSLocalizedString("Error Resuming", comment: "The alert title for a resume error")) - self.present(alert, animated: true, completion: nil) - } + case .pumpSuspended(let resuming) where !resuming: + self.updateHUDandStatusRows(statusRowMode: .pumpSuspended(resuming: true) , newSize: nil, animated: true) + self.deviceManager.pumpManager?.resumeDelivery() { (error) in + DispatchQueue.main.async { + if let error = error { + let alert = UIAlertController(with: error, title: NSLocalizedString("Error Resuming", comment: "The alert title for a resume error")) + self.present(alert, animated: true, completion: nil) } } } @@ -1070,7 +1066,7 @@ final class StatusTableViewController: ChartsTableViewController { } else { let reservoirView = ReservoirVolumeHUDView.instantiate() let batteryView = BatteryLevelHUDView.instantiate() - for view in [ reservoirView, batteryView] { + for view in [reservoirView, batteryView] { addViewToHUD(view) } } From 298542425643b140ce03171eafab24173f916523 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Fri, 15 Feb 2019 15:27:35 -0600 Subject: [PATCH 51/56] Update active flag on HUDProvider when hud is visible and app is active --- .../ChartsTableViewController.swift | 9 +++-- .../StatusTableViewController.swift | 36 ++++++++++++++----- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/Loop/View Controllers/ChartsTableViewController.swift b/Loop/View Controllers/ChartsTableViewController.swift index 3e519b2b0b..3642a25628 100644 --- a/Loop/View Controllers/ChartsTableViewController.swift +++ b/Loop/View Controllers/ChartsTableViewController.swift @@ -94,6 +94,8 @@ class ChartsTableViewController: UITableViewController, UIGestureRecognizerDeleg } ] + active = UIApplication.shared.applicationState == .active + let gestureRecognizer = UILongPressGestureRecognizer() gestureRecognizer.delegate = self gestureRecognizer.minimumPressDuration = 0.1 @@ -166,11 +168,8 @@ class ChartsTableViewController: UITableViewController, UIGestureRecognizerDeleg // References to registered notification center observers var notificationObservers: [Any] = [] - var active: Bool { - get { - return UIApplication.shared.applicationState == .active - } - set { + var active: Bool = false { + didSet { log.debug("[reloadData] for app change to active: %d", active) reloadData() } diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index ff30f0a533..58aa709a2b 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -134,8 +134,8 @@ final class StatusTableViewController: ChartsTableViewController { } } } - - deviceManager.pumpManagerHUDProvider?.hudDidAppear() + + hudVisible = true AnalyticsManager.shared.didDisplayStatusScreen() } @@ -143,6 +143,8 @@ final class StatusTableViewController: ChartsTableViewController { override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) + hudVisible = false + if presentedViewController == nil { navigationController?.setNavigationBarHidden(false, animated: animated) } @@ -157,12 +159,15 @@ final class StatusTableViewController: ChartsTableViewController { // MARK: - State override var active: Bool { - get { - return super.active - } - set { - super.active = newValue + didSet { hudView?.loopCompletionHUD.assertTimer(active) + updateHUDActive() + } + } + + var hudVisible: Bool = false { + didSet { + updateHUDActive() } } @@ -178,6 +183,20 @@ final class StatusTableViewController: ChartsTableViewController { refreshContext.update(with: .status) } } + + private var hudActive: Bool = false { + didSet { + print("didSet hudActive = \(hudActive)") + if oldValue != hudActive { + deviceManager.pumpManagerHUDProvider?.active = hudActive + } + } + } + + private func updateHUDActive() { + print("active = \(active), hudVisible = \(hudVisible)") + hudActive = active && hudVisible + } public var basalDeliveryState: PumpManagerStatus.BasalDeliveryState = .active { didSet { @@ -1057,12 +1076,13 @@ final class StatusTableViewController: ChartsTableViewController { private func configurePumpManagerHUDViews() { if let hudView = hudView { hudView.removePumpManagerProvidedViews() - if let pumpManagerHUDProvider = deviceManager.pumpManagerHUDProvider + if var pumpManagerHUDProvider = deviceManager.pumpManagerHUDProvider { let views = pumpManagerHUDProvider.createHUDViews() for view in views { addViewToHUD(view) } + pumpManagerHUDProvider.active = hudActive } else { let reservoirView = ReservoirVolumeHUDView.instantiate() let batteryView = BatteryLevelHUDView.instantiate() From be5f84316f26dc4e8c84d9d37f136ade3bb0ae42 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Fri, 15 Feb 2019 15:50:16 -0600 Subject: [PATCH 52/56] Remove signing team changes --- Loop.xcodeproj/project.pbxproj | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj index 319083d9c4..4422013483 100644 --- a/Loop.xcodeproj/project.pbxproj +++ b/Loop.xcodeproj/project.pbxproj @@ -2641,7 +2641,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Loop/Loop.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = Loop/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; "OTHER_SWIFT_FLAGS[sdk=iphonesimulator*]" = "-D IOS_SIMULATOR"; @@ -2658,7 +2658,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Loop/Loop.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = Loop/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER)"; @@ -2675,7 +2675,7 @@ CODE_SIGN_ENTITLEMENTS = "WatchApp Extension/WatchApp Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/watchOS"; INFOPLIST_FILE = "WatchApp Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; @@ -2699,7 +2699,7 @@ CODE_SIGN_ENTITLEMENTS = "WatchApp Extension/WatchApp Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/watchOS"; INFOPLIST_FILE = "WatchApp Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; @@ -2721,7 +2721,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = ""; IBSC_MODULE = WatchApp_Extension; INFOPLIST_FILE = WatchApp/Info.plist; @@ -2742,7 +2742,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = ""; IBSC_MODULE = WatchApp_Extension; INFOPLIST_FILE = WatchApp/Info.plist; @@ -2821,7 +2821,7 @@ CODE_SIGN_ENTITLEMENTS = "Loop Status Extension/Loop Status Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = "Loop Status Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).statuswidget"; @@ -2840,7 +2840,7 @@ CODE_SIGN_ENTITLEMENTS = "Loop Status Extension/Loop Status Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = UY678SP37Q; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = "Loop Status Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).statuswidget"; From 9e27c6b0c2ffc8f5d58b858a6593f29efda8900d Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 16 Feb 2019 09:34:59 -0600 Subject: [PATCH 53/56] HUDProvider active -> visible --- .../StatusTableViewController.swift | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index 58aa709a2b..ed29d842c5 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -135,7 +135,7 @@ final class StatusTableViewController: ChartsTableViewController { } } - hudVisible = true + onscreen = true AnalyticsManager.shared.didDisplayStatusScreen() } @@ -143,7 +143,7 @@ final class StatusTableViewController: ChartsTableViewController { override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - hudVisible = false + onscreen = false if presentedViewController == nil { navigationController?.setNavigationBarHidden(false, animated: animated) @@ -165,7 +165,9 @@ final class StatusTableViewController: ChartsTableViewController { } } - var hudVisible: Bool = false { + // This is similar to the visible property, but is set later, on viewDidAppear, to be + // suitable for animations that should be seen in their entirety. + var onscreen: Bool = false { didSet { updateHUDActive() } @@ -184,18 +186,8 @@ final class StatusTableViewController: ChartsTableViewController { } } - private var hudActive: Bool = false { - didSet { - print("didSet hudActive = \(hudActive)") - if oldValue != hudActive { - deviceManager.pumpManagerHUDProvider?.active = hudActive - } - } - } - private func updateHUDActive() { - print("active = \(active), hudVisible = \(hudVisible)") - hudActive = active && hudVisible + deviceManager.pumpManagerHUDProvider?.visible = active && onscreen } public var basalDeliveryState: PumpManagerStatus.BasalDeliveryState = .active { @@ -1082,7 +1074,7 @@ final class StatusTableViewController: ChartsTableViewController { for view in views { addViewToHUD(view) } - pumpManagerHUDProvider.active = hudActive + pumpManagerHUDProvider.visible = active && onscreen } else { let reservoirView = ReservoirVolumeHUDView.instantiate() let batteryView = BatteryLevelHUDView.instantiate() From 7f4fd58456d983284b8056b3b1cb22e696931489 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 18 Feb 2019 22:28:14 -0600 Subject: [PATCH 54/56] Use LoopKit dev --- Cartfile | 10 +++++----- Cartfile.resolved | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Cartfile b/Cartfile index 0c66afc258..caac804a02 100644 --- a/Cartfile +++ b/Cartfile @@ -1,7 +1,7 @@ -github "LoopKit/LoopKit" "pumpmanager-updates" -github "LoopKit/CGMBLEKit" "omnikit" +github "LoopKit/LoopKit" "dev" +github "LoopKit/CGMBLEKit" "dev" github "i-schuetz/SwiftCharts" == 0.6.2 -github "LoopKit/dexcom-share-client-swift" "omnikit" -github "LoopKit/G4ShareSpy" "omnikit" -github "ps2/rileylink_ios" "pumpmanager-changes" +github "LoopKit/dexcom-share-client-swift" "dev" +github "LoopKit/G4ShareSpy" "dev" +github "ps2/rileylink_ios" "dev" github "LoopKit/Amplitude-iOS" "decreepify" diff --git a/Cartfile.resolved b/Cartfile.resolved index 109144f12e..1ded1a366c 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,7 +1,7 @@ github "LoopKit/Amplitude-iOS" "2137d5fd44bf630ed33e1e72d7af6d8f8612f270" -github "LoopKit/CGMBLEKit" "3c8a3b0e919fbfa5e95f16c6c0ca02557571b6a6" -github "LoopKit/G4ShareSpy" "e5161f7a3c3307a935980b37220f0e3e4ebeefb1" -github "LoopKit/LoopKit" "59e1db1ec893de44cbbc7895540f1d0056dad68b" -github "LoopKit/dexcom-share-client-swift" "690414cd39c9b7a3e5074fc86c4dd0cfe85c6bb3" +github "LoopKit/CGMBLEKit" "ea1267791c66e884f1013fffd36faf4555cc6eaf" +github "LoopKit/G4ShareSpy" "fed5a389e3e47e3a1953878dd21852aa5f44b360" +github "LoopKit/LoopKit" "bf4166bc77f89e22971f2030ad006967881ff082" +github "LoopKit/dexcom-share-client-swift" "b0419edf55c7f389b36cb47dd5c376bbd3d03d69" github "i-schuetz/SwiftCharts" "0.6.2" -github "ps2/rileylink_ios" "d7db293ead3606cd0890c5523697b0e398dd553a" +github "ps2/rileylink_ios" "46ed2c845e7c4b88c721994d8e8432e86be4c699" From f8e4f58e361e0855c912bf9022960fddadc980a6 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 19 Feb 2019 13:48:15 -0600 Subject: [PATCH 55/56] Use constant for battery replacement detection threshold --- Loop/Managers/DeviceDataManager.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index 00fc6321ae..b7cb3408a5 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -66,6 +66,8 @@ final class DeviceDataManager { } private let lockedPumpManagerStatus: Locked = Locked(nil) + + static let batteryReplacementDetectionThreshold = 0.5 var pumpManagerStatus: PumpManagerStatus? { get { @@ -86,7 +88,7 @@ final class DeviceDataManager { NotificationManager.clearPumpBatteryLowNotification() } - if let oldBatteryValue = oldValue?.pumpBatteryChargeRemaining, newBatteryValue - oldBatteryValue >= 0.5 { + if let oldBatteryValue = oldValue?.pumpBatteryChargeRemaining, newBatteryValue - oldBatteryValue >= DeviceDataManager.batteryReplacementDetectionThreshold { AnalyticsManager.shared.pumpBatteryWasReplaced() } } From ee07fcf26101fe27ae49abc71bb8a16ec67f8cee Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 19 Feb 2019 13:53:47 -0600 Subject: [PATCH 56/56] Force git protocol 1 to fix travis builds --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index d695f5dfe4..ae15c2a041 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ osx_image: xcode10 # xcode_project: Loop.xcodeproj # xcode_scheme: Loop before_script: + - git config --global protocol.version 1 - set -o pipefail && xcodebuild -project Loop.xcodeproj -target Cartfile script: # Build the app target