Skip to content

Commit 689d0d8

Browse files
authored
Generalize service implementations (#26)
* Generalize service implementations - Implement general ServicesManager and service serialization/restoration - Move GlucoseThreshold and TempBasalRecommendation to LoopKit - Move NightscoutUploader to NightscoutService - Move Amplitude, Loggly, and Nightscout service implementations to respective repos - Implement generalized LoggingServicesManager, AnalyticsServicesManager, and RemoteDataServicesManager to connect to specific services - Refactor Analytics singleton to injectable implementation - Remove unused MLabService KeyChain extension - Refactor SettingsTableViewController to generalize service setup
1 parent c622769 commit 689d0d8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+821
-1878
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//
2+
// UserDefaults+Services.swift
3+
// Loop
4+
//
5+
// Created by Darin Krauss on 5/20/19.
6+
// Copyright © 2019 LoopKit Authors. All rights reserved.
7+
//
8+
9+
import LoopKit
10+
11+
extension UserDefaults {
12+
13+
private enum Key: String {
14+
case servicesState = "com.loopkit.Loop.ServicesState"
15+
}
16+
17+
var servicesState: [Service.RawStateValue] {
18+
get {
19+
return array(forKey: Key.servicesState.rawValue) as? [[String: Any]] ?? []
20+
}
21+
set {
22+
set(newValue, forKey: Key.servicesState.rawValue)
23+
}
24+
}
25+
26+
}

Loop.xcodeproj/project.pbxproj

Lines changed: 73 additions & 71 deletions
Large diffs are not rendered by default.

Loop/AppDelegate.swift

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,37 @@
88

99
import UIKit
1010
import Intents
11+
import LoopCore
1112
import LoopKit
1213
import UserNotifications
1314

1415
@UIApplicationMain
1516
final class AppDelegate: UIResponder, UIApplicationDelegate {
1617

17-
private lazy var log = DiagnosticLogger.shared.forCategory("AppDelegate")
18+
private lazy var log = DiagnosticLog(category: "AppDelegate")
1819

19-
var window: UIWindow?
20+
private lazy var servicesManager = ServicesManager()
21+
22+
private lazy var analyticsServicesManager = AnalyticsServicesManager(servicesManager: servicesManager)
23+
24+
private lazy var loggingServicesManager = LoggingServicesManager(servicesManager: servicesManager)
2025

21-
private(set) lazy var deviceManager = DeviceDataManager()
26+
private lazy var deviceManager = DeviceDataManager(servicesManager: servicesManager, analyticsServicesManager: analyticsServicesManager)
27+
28+
var window: UIWindow?
2229

2330
private var rootViewController: RootNavigationController! {
2431
return window?.rootViewController as? RootNavigationController
2532
}
2633

2734
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
35+
SharedLoggingService.instance = loggingServicesManager
36+
2837
NotificationManager.authorize(delegate: self)
2938

3039
log.info(#function)
3140

32-
AnalyticsManager.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
41+
analyticsServicesManager.application(application, didFinishLaunchingWithOptions: launchOptions)
3342

3443
rootViewController.rootViewController.deviceManager = deviceManager
3544

@@ -58,7 +67,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
5867

5968
if #available(iOS 12.0, *) {
6069
if userActivity.activityType == NewCarbEntryIntent.className {
61-
log.default("Restoring \(userActivity.activityType) intent")
70+
log.default("Restoring %{public}@ intent", userActivity.activityType)
6271
rootViewController.restoreUserActivityState(.forNewCarbEntry())
6372
return true
6473
}
@@ -67,7 +76,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
6776
switch userActivity.activityType {
6877
case NSUserActivity.newCarbEntryActivityType,
6978
NSUserActivity.viewLoopStatusActivityType:
70-
log.default("Restoring \(userActivity.activityType) activity")
79+
log.default("Restoring %{public}@ activity", userActivity.activityType)
7180
restorationHandler([rootViewController])
7281
return true
7382
default:
@@ -85,7 +94,7 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
8594
let startDate = response.notification.request.content.userInfo[NotificationManager.UserInfoKey.bolusStartDate.rawValue] as? Date,
8695
startDate.timeIntervalSinceNow >= TimeInterval(minutes: -5)
8796
{
88-
AnalyticsManager.shared.didRetryBolus()
97+
analyticsServicesManager.didRetryBolus()
8998

9099
deviceManager.enactBolus(units: units, at: startDate) { (_) in
91100
completionHandler()

Loop/Base.lproj/Localizable.strings

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,21 @@
7373
/* Title text for button to set up a new pump */
7474
"Add Pump" = "Add Pump";
7575

76+
/* Title text for button to set up a service */
77+
"Add Service" = "Add Service";
78+
79+
/* Button title to delete a service */
80+
"Delete Service" = "Delete Service";
81+
82+
/* Confirmation message for deleting a service */
83+
"Are you sure you want to delete this service?" = "Are you sure you want to delete this service?";
84+
7685
/* The title of the section containing algorithm settings */
7786
"Algorithm Settings" = "Algorithm Settings";
7887

79-
/* The title of the Amplitude service */
80-
"Amplitude" = "Amplitude";
81-
8288
/* Subtitle of Rapid-Acting – Children preset */
8389
"An adjustment to the adult model based on empirical effects in children." = "An adjustment to the adult model based on empirical effects in children.";
8490

85-
/* The title of the amplitude API key credential */
86-
"API Key" = "API Key";
87-
88-
/* The title of the nightscout API secret credential */
89-
"API Secret" = "API Secret";
90-
9191
/* Format fragment for a specific time */
9292
"at %@" = "at %@";
9393

@@ -155,9 +155,6 @@
155155
/* Message when offering bolus recommendation even though bg is below range. (1: glucose value) */
156156
"Current glucose of %1$@ is below correction range." = " Current glucose of %1$@ is below correction range.";
157157

158-
/* The title of the Loggly customer token credential */
159-
"Customer Token" = "Customer Token";
160-
161158
/* The short unit display string for decibles */
162159
"dB" = "dB";
163160

@@ -215,9 +212,6 @@
215212
/* Title of the prediction input effect for glucose momentum */
216213
"Glucose Momentum" = "Glucose Momentum";
217214

218-
/* The placeholder text for the nightscout site URL credential */
219-
"https://mysite.herokuapp.com" = "https://mysite.herokuapp.com";
220-
221215
/* The title of a target alert action specifying an indefinitely long workout targets duration */
222216
"Indefinitely" = "Indefinitely";
223217

@@ -256,9 +250,6 @@
256250
/* The loading message for the diagnostic report screen */
257251
"Loading..." = "Loading...";
258252

259-
/* The title of the loggly service */
260-
"Loggly" = "Loggly";
261-
262253
/* The notification title for a loop failure */
263254
"Loop Failure" = "Loop Failure";
264255

@@ -280,9 +271,6 @@
280271
/* Sensor state description for the non-valid state */
281272
"Needs Attention" = "Needs Attention";
282273

283-
/* The title of the Nightscout service */
284-
"Nightscout" = "Nightscout";
285-
286274
/* The error message displayed for device connection errors. */
287275
"No connected devices, or failure during device connection" = "No connected devices, or failure during device connection";
288276

@@ -349,9 +337,6 @@
349337
/* Format fragment for a start time */
350338
"since %@" = "since %@";
351339

352-
/* The title of the nightscout site URL credential */
353-
"Site URL" = "Site URL";
354-
355340
/* The title text for the Medtronic sensor switch cell */
356341
"Sof-Sensor / Enlite" = "Sof-Sensor / Enlite";
357342

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//
2+
// DiagnosticLog+Subsystem.swift
3+
// Loop
4+
//
5+
// Created by Darin Krauss on 6/12/19.
6+
// Copyright © 2019 LoopKit Authors. All rights reserved.
7+
//
8+
9+
import LoopKit
10+
11+
extension DiagnosticLog {
12+
13+
convenience init(category: String) {
14+
self.init(subsystem: "com.loopkit.Loop", category: category)
15+
}
16+
17+
}

Loop/Extensions/MealBolusNightscoutTreatment.swift

Lines changed: 0 additions & 19 deletions
This file was deleted.

Loop/Extensions/NightscoutUploader.swift

Lines changed: 0 additions & 97 deletions
This file was deleted.

Loop/Extensions/PersistedPumpEvent.swift

Lines changed: 0 additions & 55 deletions
This file was deleted.

Loop/Extensions/UIAlertController.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,30 @@ extension UIAlertController {
125125
}
126126
}
127127

128+
/// Initializes an action sheet-styled controller for selecting a service UI.
129+
///
130+
/// - Parameters:
131+
/// - serviceUITypes: An array of service UI types.
132+
/// - selectionHandler: A closure to execute when a service UI is selected.
133+
/// - service: The selected service UI type.
134+
internal convenience init(serviceUITypes: [ServiceUI.Type], selectionHandler: @escaping (_ serviceUIType: ServiceUI.Type) -> Void) {
135+
self.init(
136+
title: NSLocalizedString("Add Service", comment: "Action sheet title selecting service"),
137+
message: nil,
138+
preferredStyle: .actionSheet
139+
)
140+
141+
for serviceUIType in serviceUITypes {
142+
addAction(UIAlertAction(
143+
title: serviceUIType.localizedTitle,
144+
style: .default,
145+
handler: { (_) in
146+
selectionHandler(serviceUIType)
147+
}
148+
))
149+
}
150+
}
151+
128152
internal func addCancelAction(handler: ((UIAlertAction) -> Void)? = nil) {
129153
let cancel = NSLocalizedString("Cancel", comment: "The title of the cancel action in an action sheet")
130154
addAction(UIAlertAction(title: cancel, style: .cancel, handler: handler))

0 commit comments

Comments
 (0)