Skip to content

Commit fee85e0

Browse files
authored
Merge pull request #1998 from LoopKit/tidepool-sync
Tidepool Sync
2 parents eb8ccd6 + 866ebf6 commit fee85e0

18 files changed

+472
-344
lines changed

Loop.xcodeproj/project.pbxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@
5656
1DB1065124467E18005542BD /* AlertManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DB1065024467E18005542BD /* AlertManager.swift */; };
5757
1DB1CA4D24A55F0000B3B94C /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DB1CA4C24A55F0000B3B94C /* Image.swift */; };
5858
1DB619AC270BAD3D006C9D07 /* VersionUpdateViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DB619AB270BAD3D006C9D07 /* VersionUpdateViewModel.swift */; };
59-
1DD0B76724EC77AC008A2DC3 /* SupportScreenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DD0B76624EC77AC008A2DC3 /* SupportScreenView.swift */; };
6059
1DDE273D24AEA4B000796622 /* SettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DB1CA4E24A56D7600B3B94C /* SettingsViewModel.swift */; };
6160
1DDE273E24AEA4B000796622 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DE09BA824A3E23F009EE9F9 /* SettingsView.swift */; };
6261
1DDE274024AEA4F200796622 /* NotificationsCriticalAlertPermissionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DA46B5F2492E2E300D71A63 /* NotificationsCriticalAlertPermissionsView.swift */; };
@@ -270,6 +269,7 @@
270269
7D7076591FE06EE2004AC8EA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7D70765B1FE06EE2004AC8EA /* Localizable.strings */; };
271270
7D70765E1FE06EE3004AC8EA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7D7076601FE06EE3004AC8EA /* Localizable.strings */; };
272271
7D7076631FE06EE4004AC8EA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7D7076651FE06EE4004AC8EA /* Localizable.strings */; };
272+
7E69CFFC2A16A77E00203CBD /* ResetLoopManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E69CFFB2A16A77E00203CBD /* ResetLoopManager.swift */; };
273273
891B508524342BE1005DA578 /* CarbAndBolusFlowViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 891B508424342BE1005DA578 /* CarbAndBolusFlowViewModel.swift */; };
274274
892A5D59222F0A27008961AB /* Debug.swift in Sources */ = {isa = PBXBuildFile; fileRef = 892A5D58222F0A27008961AB /* Debug.swift */; };
275275
892A5D692230C41D008961AB /* RangeReplaceableCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 892A5D682230C41D008961AB /* RangeReplaceableCollection.swift */; };
@@ -817,7 +817,6 @@
817817
1DB1CA4E24A56D7600B3B94C /* SettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewModel.swift; sourceTree = "<group>"; };
818818
1DB619AB270BAD3D006C9D07 /* VersionUpdateViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionUpdateViewModel.swift; sourceTree = "<group>"; };
819819
1DC63E7325351BDF004605DA /* TrueTime.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TrueTime.framework; path = Carthage/Build/iOS/TrueTime.framework; sourceTree = "<group>"; };
820-
1DD0B76624EC77AC008A2DC3 /* SupportScreenView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupportScreenView.swift; sourceTree = "<group>"; };
821820
1DE09BA824A3E23F009EE9F9 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
822821
1DFE9E162447B6270082C280 /* UserNotificationAlertSchedulerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationAlertSchedulerTests.swift; sourceTree = "<group>"; };
823822
4302F4E01D4E9C8900F0FCAF /* TextFieldTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldTableViewController.swift; sourceTree = "<group>"; };
@@ -1250,6 +1249,7 @@
12501249
7DD382771F8DBFC60071272B /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Main.strings; sourceTree = "<group>"; };
12511250
7DD382781F8DBFC60071272B /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/MainInterface.strings; sourceTree = "<group>"; };
12521251
7DD382791F8DBFC60071272B /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Interface.strings; sourceTree = "<group>"; };
1252+
7E69CFFB2A16A77E00203CBD /* ResetLoopManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResetLoopManager.swift; sourceTree = "<group>"; };
12531253
80F864E52433BF5D0026EC26 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/InfoPlist.strings; sourceTree = "<group>"; };
12541254
891B508424342BE1005DA578 /* CarbAndBolusFlowViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarbAndBolusFlowViewModel.swift; sourceTree = "<group>"; };
12551255
892A5D29222EF60A008961AB /* MockKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; name = MockKit.framework; path = Carthage/Build/iOS/MockKit.framework; sourceTree = SOURCE_ROOT; };
@@ -2392,7 +2392,6 @@
23922392
439706E522D2E84900C81566 /* PredictionSettingTableViewCell.swift */,
23932393
1DE09BA824A3E23F009EE9F9 /* SettingsView.swift */,
23942394
C1DE5D22251BFC4D00439E49 /* SimpleBolusView.swift */,
2395-
1DD0B76624EC77AC008A2DC3 /* SupportScreenView.swift */,
23962395
43F64DD81D9C92C900D24DC6 /* TitleSubtitleTableViewCell.swift */,
23972396
4311FB9A1F37FE1B00D4C0A7 /* TitleSubtitleTextFieldTableViewCell.swift */,
23982397
C1AF062229426300002C1B19 /* ManualGlucoseEntryRow.swift */,
@@ -2436,6 +2435,7 @@
24362435
E9B355232935906B0076AB04 /* Missed Meal Detection */,
24372436
C1F2075B26D6F9B0007AB7EB /* ProfileExpirationAlerter.swift */,
24382437
A96DAC2B2838F31200D94E38 /* SharedLogging.swift */,
2438+
7E69CFFB2A16A77E00203CBD /* ResetLoopManager.swift */,
24392439
);
24402440
path = Managers;
24412441
sourceTree = "<group>";
@@ -3964,7 +3964,6 @@
39643964
43DFB62320D4CAE7008A7BAE /* PumpManager.swift in Sources */,
39653965
A9FB75F1252BE320004C7D3F /* BolusDosingDecision.swift in Sources */,
39663966
892A5D59222F0A27008961AB /* Debug.swift in Sources */,
3967-
1DD0B76724EC77AC008A2DC3 /* SupportScreenView.swift in Sources */,
39683967
431A8C401EC6E8AB00823B9C /* CircleMaskView.swift in Sources */,
39693968
1D05219D2469F1F5000EBBDE /* AlertStore.swift in Sources */,
39703969
439897371CD2F80600223065 /* AnalyticsServicesManager.swift in Sources */,
@@ -3982,6 +3981,7 @@
39823981
C1C660D1252E4DD5009B5C32 /* LoopConstants.swift in Sources */,
39833982
432E73CB1D24B3D6009AD15D /* RemoteDataServicesManager.swift in Sources */,
39843983
C18913B52524F24C007B0683 /* DeviceDataManager+SimpleBolusViewModelDelegate.swift in Sources */,
3984+
7E69CFFC2A16A77E00203CBD /* ResetLoopManager.swift in Sources */,
39853985
B40D07C7251A89D500C1C6D7 /* GlucoseDisplay.swift in Sources */,
39863986
43C2FAE11EB656A500364AFF /* GlucoseEffectVelocity.swift in Sources */,
39873987
);

Loop/AppDelegate.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate, WindowProvider {
4646
func applicationWillEnterForeground(_ application: UIApplication) {
4747
log.default(#function)
4848

49-
loopAppManager.askUserToConfirmCrashIfNecessary()
49+
loopAppManager.askUserToConfirmLoopReset()
5050
}
5151

5252
func applicationWillTerminate(_ application: UIApplication) {

Loop/Managers/Alerts/AlertManager.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -784,14 +784,16 @@ extension AlertManager: AlertPermissionsCheckerDelegate {
784784
}
785785

786786
extension AlertManager {
787-
func presentConfirmCrashAlert(confirmAction: @escaping (@escaping () -> Void) -> Void) {
788-
let alert = UIAlertController(title: "New Study Product Detected", message: "We've detected a new study product is selected. In order to show use this study product, Loop will need to restart.", preferredStyle: .alert)
787+
func presentLoopResetConfirmationAlert(confirmAction: @escaping (@escaping () -> Void) -> Void, cancelAction: @escaping () -> Void) {
788+
let alert = UIAlertController(title: "Loop Reset Requested", message: "We've detected a Loop reset may be needed. Tapping confirm will reset Loop and quit the app.", preferredStyle: .alert)
789789
alert.addAction(UIAlertAction(title: "Confirm", style: .default, handler: { _ in
790790
confirmAction() {
791791
fatalError("DEBUG: Resetting Loop")
792792
}
793793
}))
794-
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
794+
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in
795+
cancelAction()
796+
}))
795797

796798
alertPresenter.present(alert, animated: true)
797799
}

Loop/Managers/DeviceDataManager.swift

Lines changed: 59 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ final class DeviceDataManager {
2929
/// Remember the launch date of the app for diagnostic reporting
3030
private let launchDate = Date()
3131

32-
private(set) var testingScenariosManager: TestingScenariosManager?
33-
3432
/// The last error recorded by a device manager
3533
/// Should be accessed only on the main queue
3634
private(set) var lastError: (date: Date, error: Error)?
@@ -417,10 +415,6 @@ final class DeviceDataManager {
417415
directory: FileManager.default.exportsDirectoryURL,
418416
historicalDuration: Bundle.main.localCacheDuration)
419417

420-
if FeatureFlags.scenariosEnabled {
421-
testingScenariosManager = LocalTestingScenariosManager(deviceManager: self)
422-
}
423-
424418
loopManager.delegate = self
425419

426420
alertManager.alertStore.delegate = self
@@ -658,64 +652,6 @@ final class DeviceDataManager {
658652
self.getHealthStoreAuthorization(completion)
659653
}
660654
}
661-
662-
func generateDiagnosticReport(_ completion: @escaping (_ report: String) -> Void) {
663-
self.loopManager.generateDiagnosticReport { (loopReport) in
664-
665-
let logDurationHours = 84.0
666-
667-
self.alertManager.getStoredEntries(startDate: Date() - .hours(logDurationHours)) { (alertReport) in
668-
self.deviceLog.getLogEntries(startDate: Date() - .hours(logDurationHours)) { (result) in
669-
let deviceLogReport: String
670-
switch result {
671-
case .failure(let error):
672-
deviceLogReport = "Error fetching entries: \(error)"
673-
case .success(let entries):
674-
deviceLogReport = entries.map { "* \($0.timestamp) \($0.managerIdentifier) \($0.deviceIdentifier ?? "") \($0.type) \($0.message)" }.joined(separator: "\n")
675-
}
676-
677-
let report = [
678-
"## Build Details",
679-
"* appNameAndVersion: \(Bundle.main.localizedNameAndVersion)",
680-
"* profileExpiration: \(Bundle.main.profileExpirationString)",
681-
"* gitRevision: \(Bundle.main.gitRevision ?? "N/A")",
682-
"* gitBranch: \(Bundle.main.gitBranch ?? "N/A")",
683-
"* workspaceGitRevision: \(Bundle.main.workspaceGitRevision ?? "N/A")",
684-
"* workspaceGitBranch: \(Bundle.main.workspaceGitBranch ?? "N/A")",
685-
"* sourceRoot: \(Bundle.main.sourceRoot ?? "N/A")",
686-
"* buildDateString: \(Bundle.main.buildDateString ?? "N/A")",
687-
"* xcodeVersion: \(Bundle.main.xcodeVersion ?? "N/A")",
688-
"",
689-
"## FeatureFlags",
690-
"\(FeatureFlags)",
691-
"",
692-
alertReport,
693-
"",
694-
"## DeviceDataManager",
695-
"* launchDate: \(self.launchDate)",
696-
"* lastError: \(String(describing: self.lastError))",
697-
"",
698-
"cacheStore: \(String(reflecting: self.cacheStore))",
699-
"",
700-
self.cgmManager != nil ? String(reflecting: self.cgmManager!) : "cgmManager: nil",
701-
"",
702-
self.pumpManager != nil ? String(reflecting: self.pumpManager!) : "pumpManager: nil",
703-
"",
704-
"## Device Communication Log",
705-
deviceLogReport,
706-
"",
707-
String(reflecting: self.watchManager!),
708-
"",
709-
String(reflecting: self.statusExtensionManager!),
710-
"",
711-
loopReport,
712-
].joined(separator: "\n")
713-
714-
completion(report)
715-
}
716-
}
717-
}
718-
}
719655
}
720656

721657
private extension DeviceDataManager {
@@ -1285,9 +1221,6 @@ extension DeviceDataManager {
12851221
}
12861222

12871223
insulinDeliveryStore.purgeAllDoseEntries(healthKitPredicate: devicePredicate) { error in
1288-
if error == nil {
1289-
insulinDeliveryStore.test_lastImmutableBasalEndDate = nil
1290-
}
12911224
completion?(error)
12921225
}
12931226
}
@@ -1658,40 +1591,6 @@ fileprivate extension FileManager {
16581591
extension GlucoseStore : CGMStalenessMonitorDelegate { }
16591592

16601593

1661-
//MARK: - SupportInfoProvider protocol conformance
1662-
1663-
extension DeviceDataManager: SupportInfoProvider {
1664-
1665-
private var branchNameIfNotReleaseBranch: String? {
1666-
return Bundle.main.gitBranch.filter { branch in
1667-
return branch != "" &&
1668-
branch != "main" &&
1669-
branch != "master" &&
1670-
!branch.starts(with: "release/")
1671-
}
1672-
}
1673-
1674-
public var localizedAppNameAndVersion: String {
1675-
if let branch = branchNameIfNotReleaseBranch {
1676-
return Bundle.main.localizedNameAndVersion + " (\(branch))"
1677-
}
1678-
return Bundle.main.localizedNameAndVersion
1679-
}
1680-
1681-
public var pumpStatus: PumpManagerStatus? {
1682-
return pumpManager?.status
1683-
}
1684-
1685-
public var cgmStatus: CGMManagerStatus? {
1686-
return cgmManager?.cgmManagerStatus
1687-
}
1688-
1689-
public func generateIssueReport(completion: @escaping (String) -> Void) {
1690-
generateDiagnosticReport(completion)
1691-
}
1692-
1693-
}
1694-
16951594
//MARK: TherapySettingsViewModelDelegate
16961595
struct CancelTempBasalFailedError: LocalizedError {
16971596
let reason: Error?
@@ -1792,8 +1691,66 @@ extension DeviceDataManager {
17921691
}
17931692
}
17941693

1795-
extension DeviceDataManager {
1694+
extension DeviceDataManager: DeviceSupportDelegate {
17961695
var availableSupports: [SupportUI] { [cgmManager, pumpManager].compactMap { $0 as? SupportUI } }
1696+
1697+
func generateDiagnosticReport(_ completion: @escaping (_ report: String) -> Void) {
1698+
self.loopManager.generateDiagnosticReport { (loopReport) in
1699+
1700+
let logDurationHours = 84.0
1701+
1702+
self.alertManager.getStoredEntries(startDate: Date() - .hours(logDurationHours)) { (alertReport) in
1703+
self.deviceLog.getLogEntries(startDate: Date() - .hours(logDurationHours)) { (result) in
1704+
let deviceLogReport: String
1705+
switch result {
1706+
case .failure(let error):
1707+
deviceLogReport = "Error fetching entries: \(error)"
1708+
case .success(let entries):
1709+
deviceLogReport = entries.map { "* \($0.timestamp) \($0.managerIdentifier) \($0.deviceIdentifier ?? "") \($0.type) \($0.message)" }.joined(separator: "\n")
1710+
}
1711+
1712+
let report = [
1713+
"## Build Details",
1714+
"* appNameAndVersion: \(Bundle.main.localizedNameAndVersion)",
1715+
"* profileExpiration: \(Bundle.main.profileExpirationString)",
1716+
"* gitRevision: \(Bundle.main.gitRevision ?? "N/A")",
1717+
"* gitBranch: \(Bundle.main.gitBranch ?? "N/A")",
1718+
"* workspaceGitRevision: \(Bundle.main.workspaceGitRevision ?? "N/A")",
1719+
"* workspaceGitBranch: \(Bundle.main.workspaceGitBranch ?? "N/A")",
1720+
"* sourceRoot: \(Bundle.main.sourceRoot ?? "N/A")",
1721+
"* buildDateString: \(Bundle.main.buildDateString ?? "N/A")",
1722+
"* xcodeVersion: \(Bundle.main.xcodeVersion ?? "N/A")",
1723+
"",
1724+
"## FeatureFlags",
1725+
"\(FeatureFlags)",
1726+
"",
1727+
alertReport,
1728+
"",
1729+
"## DeviceDataManager",
1730+
"* launchDate: \(self.launchDate)",
1731+
"* lastError: \(String(describing: self.lastError))",
1732+
"",
1733+
"cacheStore: \(String(reflecting: self.cacheStore))",
1734+
"",
1735+
self.cgmManager != nil ? String(reflecting: self.cgmManager!) : "cgmManager: nil",
1736+
"",
1737+
self.pumpManager != nil ? String(reflecting: self.pumpManager!) : "pumpManager: nil",
1738+
"",
1739+
"## Device Communication Log",
1740+
deviceLogReport,
1741+
"",
1742+
String(reflecting: self.watchManager!),
1743+
"",
1744+
String(reflecting: self.statusExtensionManager!),
1745+
"",
1746+
loopReport,
1747+
].joined(separator: "\n")
1748+
1749+
completion(report)
1750+
}
1751+
}
1752+
}
1753+
}
17971754
}
17981755

17991756
extension DeviceDataManager: DeviceStatusProvider {}

Loop/Managers/LocalTestingScenariosManager.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import OSLog
1414
final class LocalTestingScenariosManager: TestingScenariosManagerRequirements, DirectoryObserver {
1515

1616
unowned let deviceManager: DeviceDataManager
17+
unowned let supportManager: SupportManager
1718

1819
let log = DiagnosticLog(category: "LocalTestingScenariosManager")
1920

@@ -35,12 +36,13 @@ final class LocalTestingScenariosManager: TestingScenariosManagerRequirements, D
3536
deviceManager.pluginManager
3637
}
3738

38-
init(deviceManager: DeviceDataManager) {
39+
init(deviceManager: DeviceDataManager, supportManager: SupportManager) {
3940
guard FeatureFlags.scenariosEnabled else {
4041
fatalError("\(#function) should be invoked only when scenarios are enabled")
4142
}
4243

4344
self.deviceManager = deviceManager
45+
self.supportManager = supportManager
4446
self.scenariosSource = Bundle.main.bundleURL.appendingPathComponent("Scenarios")
4547

4648
log.debug("Loading testing scenarios from %{public}@", scenariosSource.path)

0 commit comments

Comments
 (0)