From 342c8e9e07e90559a84722daaa114fd3aee26595 Mon Sep 17 00:00:00 2001 From: Nathaniel Hamming Date: Wed, 30 Oct 2024 16:31:41 -0300 Subject: [PATCH] [PAL-818] plugin dependency (#112) * do not allow deleting of the service when it is a dependency * pass allowDebugFeatures to service --- TidepoolService.xcodeproj/project.pbxproj | 4 ++++ TidepoolServiceKit/TidepoolService.swift | 8 +++++++- .../Extensions/EnvironmentValues.swift | 20 +++++++++++++++++++ TidepoolServiceKitUI/SettingsView.swift | 16 ++++++++++----- TidepoolServiceKitUI/TidepoolService+UI.swift | 12 +++++------ 5 files changed, 48 insertions(+), 12 deletions(-) create mode 100644 TidepoolServiceKitUI/Extensions/EnvironmentValues.swift diff --git a/TidepoolService.xcodeproj/project.pbxproj b/TidepoolService.xcodeproj/project.pbxproj index 76a25dd..ed7e8ac 100644 --- a/TidepoolService.xcodeproj/project.pbxproj +++ b/TidepoolService.xcodeproj/project.pbxproj @@ -63,6 +63,7 @@ A9E8C611272C76A500016E2E /* TimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9E8C610272C76A500016E2E /* TimeInterval.swift */; }; A9F9F317271A046E00D19374 /* StoredCarbEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9F9F316271A046E00D19374 /* StoredCarbEntry.swift */; }; A9F9F319271A05B100D19374 /* IdentifiableHKDatum.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9F9F318271A05B100D19374 /* IdentifiableHKDatum.swift */; }; + B40B20CC2CD2AC600027BF35 /* EnvironmentValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = B40B20CB2CD2AC600027BF35 /* EnvironmentValues.swift */; }; C110888F2A39149100BA4898 /* BuildDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = C110888E2A39149100BA4898 /* BuildDetails.swift */; }; C124239D2A58771A00EAC89E /* TidepoolKit in Frameworks */ = {isa = PBXBuildFile; productRef = C124239C2A58771A00EAC89E /* TidepoolKit */; }; C12E4BBA288F2215009C98A2 /* TidepoolServiceKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A9DAACFF22E7987800E76C9F /* TidepoolServiceKit.framework */; platformFilter = ios; }; @@ -224,6 +225,7 @@ A9E8C610272C76A500016E2E /* TimeInterval.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeInterval.swift; sourceTree = ""; }; A9F9F316271A046E00D19374 /* StoredCarbEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoredCarbEntry.swift; sourceTree = ""; }; A9F9F318271A05B100D19374 /* IdentifiableHKDatum.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentifiableHKDatum.swift; sourceTree = ""; }; + B40B20CB2CD2AC600027BF35 /* EnvironmentValues.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnvironmentValues.swift; sourceTree = ""; }; C110888E2A39149100BA4898 /* BuildDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildDetails.swift; sourceTree = ""; }; C12522E1298309B5006EA1CD /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Localizable.strings; sourceTree = ""; }; C1317D4129830A0800625B94 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = ""; }; @@ -482,6 +484,7 @@ C1D0B62A29848BD90098D215 /* Extensions */ = { isa = PBXGroup; children = ( + B40B20CB2CD2AC600027BF35 /* EnvironmentValues.swift */, C1D0B62B29848BEB0098D215 /* Image.swift */, C1C9414529F0CB21008D3E05 /* UIImage.swift */, ); @@ -806,6 +809,7 @@ A97651762421AA11002EB5D4 /* OSLog.swift in Sources */, A9DAAD3422E7CA1A00E76C9F /* LocalizedString.swift in Sources */, A9DAAD3922E7DEE000E76C9F /* TidepoolService+UI.swift in Sources */, + B40B20CC2CD2AC600027BF35 /* EnvironmentValues.swift in Sources */, A9DAAD6F22E7EA9700E76C9F /* NibLoadable.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/TidepoolServiceKit/TidepoolService.swift b/TidepoolServiceKit/TidepoolService.swift index 5514e85..7da1509 100644 --- a/TidepoolServiceKit/TidepoolService.swift +++ b/TidepoolServiceKit/TidepoolService.swift @@ -60,7 +60,7 @@ public final class TidepoolService: Service, TAPIObserver, ObservableObject { public let tapi: TAPI = TAPI(clientId: BuildDetails.default.tidepoolServiceClientId, redirectURL: BuildDetails.default.tidepoolServiceRedirectURL) - public private (set) var error: Error? + public private(set) var error: Error? private let id: String @@ -77,6 +77,8 @@ public final class TidepoolService: Service, TAPIObserver, ObservableObject { private let tidepoolKitLog = OSLog(category: "TidepoolKit") private var deviceLogUploader: DeviceLogUploader? + + public var isDependency: Bool = false private func setDeviceLogUploaderDelegate() async { await deviceLogUploader?.setDelegate(remoteDataServiceDelegate) @@ -137,6 +139,10 @@ public final class TidepoolService: Service, TAPIObserver, ObservableObject { } public var isOnboarded = false // No distinction between created and onboarded + + public func markAsDepedency(_ isDependency: Bool) { + self.isDependency = isDependency + } @Published public var session: TSession? diff --git a/TidepoolServiceKitUI/Extensions/EnvironmentValues.swift b/TidepoolServiceKitUI/Extensions/EnvironmentValues.swift new file mode 100644 index 0000000..56b465b --- /dev/null +++ b/TidepoolServiceKitUI/Extensions/EnvironmentValues.swift @@ -0,0 +1,20 @@ +// +// EnvironmentValues.swift +// TidepoolService +// +// Created by Nathaniel Hamming on 2024-10-30. +// Copyright © 2024 LoopKit Authors. All rights reserved. +// + +import SwiftUI + +private struct AllowDebugFeaturesKey: EnvironmentKey { + static let defaultValue: Bool = false +} + +public extension EnvironmentValues { + var allowDebugFeatures: Bool { + get { self[AllowDebugFeaturesKey.self] } + set { self[AllowDebugFeaturesKey.self] = newValue } + } +} diff --git a/TidepoolServiceKitUI/SettingsView.swift b/TidepoolServiceKitUI/SettingsView.swift index bacffd3..3a61ac8 100644 --- a/TidepoolServiceKitUI/SettingsView.swift +++ b/TidepoolServiceKitUI/SettingsView.swift @@ -11,7 +11,8 @@ import TidepoolKit import TidepoolServiceKit public struct SettingsView: View { - + @Environment(\.allowDebugFeatures) var allowDebugFeatures + @State private var isEnvironmentActionSheetPresented = false @State private var showingDeletionConfirmation = false @@ -28,7 +29,12 @@ public struct SettingsView: View { private let onboarding: Bool var isLoggedIn: Bool { - return service.session != nil + service.session != nil + } + + var canDeleteService: Bool { + guard !allowDebugFeatures else { return true } + return !service.isDependency } public init(service: TidepoolService, login: ((TEnvironment) async throws -> Void)?, dismiss: (() -> Void)?, onboarding: Bool) @@ -97,11 +103,11 @@ public struct SettingsView: View { .padding() } Spacer() - if isLoggedIn && !onboarding { + if isLoggedIn && !onboarding && canDeleteService { deleteServiceButton - } else if isLoggedIn { + } else if isLoggedIn && onboarding { continueButton - } else { + } else if !isLoggedIn { loginButton } } diff --git a/TidepoolServiceKitUI/TidepoolService+UI.swift b/TidepoolServiceKitUI/TidepoolService+UI.swift index 06e3d2c..39634d7 100644 --- a/TidepoolServiceKitUI/TidepoolService+UI.swift +++ b/TidepoolServiceKitUI/TidepoolService+UI.swift @@ -34,7 +34,7 @@ extension TidepoolService: @retroactive ServiceUI { UIImage(frameworkImage: "Tidepool Logo") } - public static func setupViewController(pluginHost: PluginHost, onboarding: Bool) -> SetupUIResult { + public static func setupViewController(pluginHost: PluginHost, onboarding: Bool, allowDebugFeatures: Bool) -> SetupUIResult { let navController = ServiceNavigationController() navController.isNavigationBarHidden = true @@ -58,7 +58,7 @@ extension TidepoolService: @retroactive ServiceUI { Task { await navController.notifyComplete() } - }, onboarding: onboarding) + }, onboarding: onboarding).environment(\.allowDebugFeatures, allowDebugFeatures) let hostingController = await UIHostingController(rootView: settingsView) await navController.pushViewController(hostingController, animated: false) @@ -67,11 +67,11 @@ extension TidepoolService: @retroactive ServiceUI { return .userInteractionRequired(navController) } - public static func setupViewController(colorPalette: LoopUIColorPalette, pluginHost: PluginHost) -> SetupUIResult { - return setupViewController(pluginHost: pluginHost, onboarding: false) + public static func setupViewController(colorPalette: LoopUIColorPalette, pluginHost: PluginHost, allowDebugFeatures: Bool) -> SetupUIResult { + return setupViewController(pluginHost: pluginHost, onboarding: false, allowDebugFeatures: allowDebugFeatures) } - public func settingsViewController(colorPalette: LoopUIColorPalette) -> ServiceViewController { + public func settingsViewController(colorPalette: LoopUIColorPalette, allowDebugFeatures: Bool) -> ServiceViewController { let navController = ServiceNavigationController() navController.isNavigationBarHidden = true @@ -92,7 +92,7 @@ extension TidepoolService: @retroactive ServiceUI { Task { await navController.notifyComplete() } - }, onboarding: false) + }, onboarding: false).environment(\.allowDebugFeatures, allowDebugFeatures) let hostingController = await UIHostingController(rootView: settingsView) await navController.pushViewController(hostingController, animated: false)