diff --git a/Extensions/HKUnit.swift b/Extensions/HKUnit.swift deleted file mode 100644 index 4bdb2a0..0000000 --- a/Extensions/HKUnit.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// HKUnit.swift -// LoopOnboarding -// -// Created by Pete Schwamb on 3/3/22. -// - -import HealthKit - -extension HKUnit { - public static let milligramsPerDeciliter: HKUnit = { - return HKUnit.gramUnit(with: .milli).unitDivided(by: .literUnit(with: .deci)) - }() -} diff --git a/LoopOnboarding.xcodeproj/project.pbxproj b/LoopOnboarding.xcodeproj/project.pbxproj index 08c4431..88c57dd 100644 --- a/LoopOnboarding.xcodeproj/project.pbxproj +++ b/LoopOnboarding.xcodeproj/project.pbxproj @@ -39,9 +39,6 @@ C1C134A327DD38310097B5AD /* NightscoutServiceKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1C134A227DD38310097B5AD /* NightscoutServiceKit.framework */; }; C1C134A427DD38310097B5AD /* NightscoutServiceKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C1C134A227DD38310097B5AD /* NightscoutServiceKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; C1D0B62E2986C8730098D215 /* TimeZone.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1D0B62D2986C8730098D215 /* TimeZone.swift */; }; - C1D936DB27D166BF00926313 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1D936DA27D166BF00926313 /* HKUnit.swift */; }; - C1D936DC27D166BF00926313 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1D936DA27D166BF00926313 /* HKUnit.swift */; }; - C1D936DD27D166BF00926313 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1D936DA27D166BF00926313 /* HKUnit.swift */; }; C1D936E027D264D600926313 /* AppleHealthAuthView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1D936DE27D264D600926313 /* AppleHealthAuthView.swift */; }; /* End PBXBuildFile section */ @@ -131,7 +128,6 @@ C1C1349927DD37C80097B5AD /* NightscoutServiceKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = NightscoutServiceKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C1C134A227DD38310097B5AD /* NightscoutServiceKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = NightscoutServiceKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C1D0B62D2986C8730098D215 /* TimeZone.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeZone.swift; sourceTree = ""; }; - C1D936DA27D166BF00926313 /* HKUnit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = ""; }; C1D936DE27D264D600926313 /* AppleHealthAuthView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleHealthAuthView.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -267,7 +263,6 @@ isa = PBXGroup; children = ( A9CE7D9625BC9BF400C04F9B /* OSLog.swift */, - C1D936DA27D166BF00926313 /* HKUnit.swift */, ); path = Extensions; sourceTree = ""; @@ -478,7 +473,6 @@ files = ( A9CE7D9725BC9BF400C04F9B /* OSLog.swift in Sources */, A9CE7D7525BC9B2B00C04F9B /* LocalizedString.swift in Sources */, - C1D936DB27D166BF00926313 /* HKUnit.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -488,7 +482,6 @@ files = ( C1D0B62E2986C8730098D215 /* TimeZone.swift in Sources */, C1D936E027D264D600926313 /* AppleHealthAuthView.swift in Sources */, - C1D936DC27D166BF00926313 /* HKUnit.swift in Sources */, C16121EB27C457C400BCDE2A /* ImportSettingsView.swift in Sources */, A9B3CE8125BCBD85002D9E92 /* Image.swift in Sources */, A9B3CE8F25BCBE7D002D9E92 /* Bundle.swift in Sources */, @@ -507,7 +500,6 @@ files = ( A9CE7FF325BCAC1800C04F9B /* LoopOnboardingPlugin.swift in Sources */, A9CE7D9925BC9BF400C04F9B /* OSLog.swift in Sources */, - C1D936DD27D166BF00926313 /* HKUnit.swift in Sources */, A9CE7D7725BC9B2B00C04F9B /* LocalizedString.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -636,7 +628,7 @@ GCC_WARN_UNUSED_LABEL = YES; GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.1; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; LOCALIZATION_PREFERS_STRING_CATALOGS = YES; LOCALIZED_STRING_MACRO_NAMES = ( NSLocalizedString, @@ -742,7 +734,7 @@ GCC_WARN_UNUSED_LABEL = YES; GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.1; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; LOCALIZATION_PREFERS_STRING_CATALOGS = YES; LOCALIZED_STRING_MACRO_NAMES = ( NSLocalizedString, diff --git a/LoopOnboardingKitUI/LoopOnboardingUI.swift b/LoopOnboardingKitUI/LoopOnboardingUI.swift index b2fe4b2..031e4df 100644 --- a/LoopOnboardingKitUI/LoopOnboardingUI.swift +++ b/LoopOnboardingKitUI/LoopOnboardingUI.swift @@ -7,19 +7,19 @@ // import SwiftUI -import HealthKit import LoopKit import LoopKitUI import LoopOnboardingKit public final class LoopOnboardingUI: OnboardingUI { + public static func createOnboarding() -> OnboardingUI { return Self() } public weak var onboardingDelegate: OnboardingDelegate? - public static let pluginIdentifier = "LoopOnboarding" + public let pluginIdentifier = "LoopOnboarding" public var isOnboarded: Bool { didSet { @@ -53,8 +53,8 @@ public final class LoopOnboardingUI: OnboardingUI { ] } - public func onboardingViewController(onboardingProvider: OnboardingProvider, displayGlucosePreference: DisplayGlucosePreference, colorPalette: LoopUIColorPalette) -> (UIViewController & OnboardingViewController) { - return OnboardingUICoordinator(onboarding: self, onboardingProvider: onboardingProvider, initialTherapySettings: onboardingProvider.onboardingTherapySettings, displayGlucosePreference: displayGlucosePreference, colorPalette: colorPalette) + public func onboardingViewController(onboardingProvider: OnboardingProvider, displayGlucosePreference: DisplayGlucosePreference, colorPalette: LoopUIColorPalette, dosingStrategySelectionEnabled: Bool) -> (UIViewController & OnboardingViewController) { + return OnboardingUICoordinator(onboarding: self, onboardingProvider: onboardingProvider, initialTherapySettings: onboardingProvider.onboardingTherapySettings, displayGlucosePreference: displayGlucosePreference, colorPalette: colorPalette, dosingStrategySelectionEnabled: dosingStrategySelectionEnabled) } private func notifyDidUpdateState() { diff --git a/LoopOnboardingKitUI/View Controllers/OnboardingUICoordinator.swift b/LoopOnboardingKitUI/View Controllers/OnboardingUICoordinator.swift index cc61f2d..1ddc82b 100644 --- a/LoopOnboardingKitUI/View Controllers/OnboardingUICoordinator.swift +++ b/LoopOnboardingKitUI/View Controllers/OnboardingUICoordinator.swift @@ -8,12 +8,13 @@ import os.log import Foundation -import HealthKit import SwiftUI import LoopKit import LoopKitUI import NightscoutServiceKit +import NightscoutServiceKitUI import LoopSupportKitUI +import LoopAlgorithm enum OnboardingScreen: CaseIterable { case welcome @@ -66,6 +67,7 @@ class OnboardingUICoordinator: UINavigationController, CGMManagerOnboarding, Pum private let displayGlucosePreference: DisplayGlucosePreference private let colorPalette: LoopUIColorPalette + private let dosingStrategySelectionEnabled: Bool private var screenStack = [OnboardingScreen]() private var currentScreen: OnboardingScreen { return screenStack.last! } @@ -78,12 +80,13 @@ class OnboardingUICoordinator: UINavigationController, CGMManagerOnboarding, Pum private static let serviceIdentifier = "NightscoutService" - init(onboarding: LoopOnboardingUI, onboardingProvider: OnboardingProvider, initialTherapySettings: TherapySettings, displayGlucosePreference: DisplayGlucosePreference, colorPalette: LoopUIColorPalette) { + init(onboarding: LoopOnboardingUI, onboardingProvider: OnboardingProvider, initialTherapySettings: TherapySettings, displayGlucosePreference: DisplayGlucosePreference, colorPalette: LoopUIColorPalette, dosingStrategySelectionEnabled: Bool) { self.onboarding = onboarding self.onboardingProvider = onboardingProvider self.initialTherapySettings = initialTherapySettings self.displayGlucosePreference = displayGlucosePreference self.colorPalette = colorPalette + self.dosingStrategySelectionEnabled = dosingStrategySelectionEnabled self.service = onboardingProvider.activeServices.first(where: { $0.pluginIdentifier == OnboardingUICoordinator.serviceIdentifier }) super.init(navigationBarClass: UINavigationBar.self, toolbarClass: UIToolbar.self) @@ -184,7 +187,7 @@ class OnboardingUICoordinator: UINavigationController, CGMManagerOnboarding, Pum let view = CorrectionRangeOverrideInformationView(preset: .preMeal, onExit: { [weak self] in self?.stepFinished() }) return hostingController(rootView: view) case .correctionRangePreMealOverrideEditor: - let view = CorrectionRangeOverridesEditor(mode: .acceptanceFlow, therapySettingsViewModel: therapySettingsViewModel!, preset: .preMeal) + let view = CorrectionRangeOverridesEditor(therapySettingsViewModel: therapySettingsViewModel!, preset: .preMeal) return hostingController(rootView: view) case .basalRatesInfo: let view = BasalRatesInformationView(onExit: { [weak self] in self?.stepFinished() }) @@ -229,6 +232,7 @@ class OnboardingUICoordinator: UINavigationController, CGMManagerOnboarding, Pum let rootView = rootView .environmentObject(displayGlucosePreference) .environment(\.appName, Bundle.main.bundleDisplayName) + .environment(\.dosingStrategySelectionEnabled, dosingStrategySelectionEnabled) let hostingController = DismissibleHostingController(content: rootView, colorPalette: colorPalette) return hostingController } @@ -271,20 +275,16 @@ class OnboardingUICoordinator: UINavigationController, CGMManagerOnboarding, Pum private func setupWithNightscout() { LoopKitAnalytics.shared.recordAnalyticsEvent("Onboarding With Nightscout", withProperties: nil, outOfSession: false) - switch onboardingProvider.onboardService(withIdentifier: OnboardingUICoordinator.serviceIdentifier) { - case .failure(let error): - log.debug("Failure to create and setup service with identifier '%{public}@': %{public}@", OnboardingUICoordinator.serviceIdentifier, String(describing: error)) - case .success(let success): - switch success { - case .userInteractionRequired(var setupViewController): - nightscoutOnboardingViewController = setupViewController - setupViewController.serviceOnboardingDelegate = self - setupViewController.completionDelegate = self - show(setupViewController, sender: self) - case .createdAndOnboarded(let service): - self.service = service - checkForAvailableSettingsImport() - } + let result = NightscoutService.setupViewController(colorPalette: colorPalette, pluginHost: onboardingProvider, allowDebugFeatures: onboardingProvider.allowDebugFeatures) + switch result { + case .userInteractionRequired(var setupViewController): + nightscoutOnboardingViewController = setupViewController + setupViewController.serviceOnboardingDelegate = self + setupViewController.completionDelegate = self + show(setupViewController, sender: self) + case .createdAndOnboarded(let service): + self.service = service + checkForAvailableSettingsImport() } } @@ -304,7 +304,7 @@ class OnboardingUICoordinator: UINavigationController, CGMManagerOnboarding, Pum dailyItems: [.init(startTime: 0, value: 50)], timeZone: .currentFixed), carbRatioSchedule: CarbRatioSchedule( - unit: .gram(), + unit: .gram, dailyItems: [.init(startTime: 0, value: 15)], timeZone: .currentFixed), basalRateSchedule: BasalRateSchedule( @@ -344,21 +344,23 @@ class OnboardingUICoordinator: UINavigationController, CGMManagerOnboarding, Pum private func constructTherapySettingsViewModel(therapySettings: TherapySettings) -> TherapySettingsViewModel? { - return TherapySettingsViewModel(therapySettings: therapySettings, pumpSupportedIncrements: nil, sensitivityOverridesEnabled: true, prescription: nil, delegate: self) + return TherapySettingsViewModel(therapySettings: therapySettings, pumpSupportedIncrements: nil, prescription: nil, delegate: self) } } extension OnboardingUICoordinator: TherapySettingsViewModelDelegate { + func syncBasalRateSchedule(items: [RepeatingScheduleValue], completion: @escaping (Result) -> Void) { // Since pump isn't set up, this syncing shouldn't do anything assertionFailure() } - func syncDeliveryLimits(deliveryLimits: DeliveryLimits, completion: @escaping (Result) -> Void) { + func syncDeliveryLimits(deliveryLimits: LoopKit.DeliveryLimits) async throws -> LoopKit.DeliveryLimits { // Since pump isn't set up, this syncing shouldn't do anything assertionFailure() + return deliveryLimits } - + func saveCompletion(therapySettings: TherapySettings) { stepFinished() } @@ -462,8 +464,5 @@ extension TherapySettings { { correctionRangeOverrides?.ranges[.preMeal] = nil } - - // workout mode obviated in DIY by overrides - correctionRangeOverrides?.ranges[.workout] = nil } } diff --git a/LoopOnboardingKitUI/Views/AppleHealthAuthView.swift b/LoopOnboardingKitUI/Views/AppleHealthAuthView.swift index 2d44be5..8e9a195 100644 --- a/LoopOnboardingKitUI/Views/AppleHealthAuthView.swift +++ b/LoopOnboardingKitUI/Views/AppleHealthAuthView.swift @@ -6,7 +6,6 @@ // import SwiftUI -import HealthKit import LoopKitUI struct AppleHealthAuthView: View { diff --git a/LoopOnboardingKitUI/Views/WelcomeView.swift b/LoopOnboardingKitUI/Views/WelcomeView.swift index 4c2d89f..5936d8b 100644 --- a/LoopOnboardingKitUI/Views/WelcomeView.swift +++ b/LoopOnboardingKitUI/Views/WelcomeView.swift @@ -19,10 +19,13 @@ struct WelcomeView: View { Text(LocalizedString("Welcome to Loop", comment: "Title on WelcomeView")) .font(.largeTitle) .fontWeight(.semibold) + Image(frameworkImage: "Loop", decorative: true) .onLongPressGesture(minimumDuration: 2) { didLongPressOnLogo?() } + .accessibilityHidden(false) + .accessibilityIdentifier("loopLogo") Text(LocalizedString("Before using Loop you need to configure a few settings. These settings should be entered with precision and care; they are a critical part of how Loop determines the right amount of insulin to deliver.\n\nIf you are new to Loop, work with your diabetes support team to determine the settings that work best for you.", comment: "Descriptive text on WelcomeView")) .foregroundColor(.secondary)