Quellcode durchsuchen

Beautify UI for Bluetooth Required Warning #422

Deniz Cengiz vor 1 Jahr
Ursprung
Commit
a7584c8fa6

+ 8 - 4
Trio.xcodeproj/project.pbxproj

@@ -575,6 +575,7 @@
 		DD5DC9F92CF3DAA900AB8703 /* RadioButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD5DC9F82CF3DAA900AB8703 /* RadioButton.swift */; };
 		DD5DC9FB2CF3E1B100AB8703 /* AdjustmentsStateModel+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD5DC9FA2CF3E1AA00AB8703 /* AdjustmentsStateModel+Helpers.swift */; };
 		DD68889D2C386E17006E3C44 /* NightscoutExercise.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD68889C2C386E17006E3C44 /* NightscoutExercise.swift */; };
+		DD6A4E082DBD95F1008C4B26 /* BluetoothRequiredView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6A4E072DBD95F1008C4B26 /* BluetoothRequiredView.swift */; };
 		DD6B7CB22C7B6F0800B75029 /* Rounding.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6B7CB12C7B6F0800B75029 /* Rounding.swift */; };
 		DD6B7CB42C7B71F700B75029 /* ForecastDisplayType.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6B7CB32C7B71F700B75029 /* ForecastDisplayType.swift */; };
 		DD6D67E42C9C253500660C9B /* ColorSchemeOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6D67E32C9C253500660C9B /* ColorSchemeOption.swift */; };
@@ -660,11 +661,11 @@
 		DDF847E62C5D66490049BB3B /* AddMealPresetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF847E52C5D66490049BB3B /* AddMealPresetView.swift */; };
 		DDF847E82C5DABA30049BB3B /* WatchConfigAppleWatchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF847E72C5DABA30049BB3B /* WatchConfigAppleWatchView.swift */; };
 		DDF847EA2C5DABAC0049BB3B /* WatchConfigGarminView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDF847E92C5DABAC0049BB3B /* WatchConfigGarminView.swift */; };
+		DDFF202F2DB1D14500AB8A96 /* NotificationPermissionStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFF202E2DB1D14500AB8A96 /* NotificationPermissionStepView.swift */; };
+		DDFF20312DB1D15500AB8A96 /* BluetoothPermissionStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFF20302DB1D15500AB8A96 /* BluetoothPermissionStepView.swift */; };
 		DDFF204A2DB29EF500AB8A96 /* WatchLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFF20492DB29EF500AB8A96 /* WatchLogger.swift */; };
 		DDFF204E2DB2C00B00AB8A96 /* WatchStateSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFF204D2DB2C00B00AB8A96 /* WatchStateSnapshot.swift */; };
 		DDFF20502DB2C11900AB8A96 /* WatchStateSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFF204F2DB2C11900AB8A96 /* WatchStateSnapshot.swift */; };
-		DDFF202F2DB1D14500AB8A96 /* NotificationPermissionStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFF202E2DB1D14500AB8A96 /* NotificationPermissionStepView.swift */; };
-		DDFF20312DB1D15500AB8A96 /* BluetoothPermissionStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFF20302DB1D15500AB8A96 /* BluetoothPermissionStepView.swift */; };
 		E00EEC0327368630002FF094 /* ServiceAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = E00EEBFD27368630002FF094 /* ServiceAssembly.swift */; };
 		E00EEC0427368630002FF094 /* SecurityAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = E00EEBFE27368630002FF094 /* SecurityAssembly.swift */; };
 		E00EEC0527368630002FF094 /* StorageAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = E00EEBFF27368630002FF094 /* StorageAssembly.swift */; };
@@ -1374,6 +1375,7 @@
 		DD5DC9F82CF3DAA900AB8703 /* RadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButton.swift; sourceTree = "<group>"; };
 		DD5DC9FA2CF3E1AA00AB8703 /* AdjustmentsStateModel+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AdjustmentsStateModel+Helpers.swift"; sourceTree = "<group>"; };
 		DD68889C2C386E17006E3C44 /* NightscoutExercise.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightscoutExercise.swift; sourceTree = "<group>"; };
+		DD6A4E072DBD95F1008C4B26 /* BluetoothRequiredView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BluetoothRequiredView.swift; sourceTree = "<group>"; };
 		DD6B7CB12C7B6F0800B75029 /* Rounding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Rounding.swift; sourceTree = "<group>"; };
 		DD6B7CB32C7B71F700B75029 /* ForecastDisplayType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForecastDisplayType.swift; sourceTree = "<group>"; };
 		DD6D67E32C9C253500660C9B /* ColorSchemeOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorSchemeOption.swift; sourceTree = "<group>"; };
@@ -1462,11 +1464,11 @@
 		DDF847E52C5D66490049BB3B /* AddMealPresetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddMealPresetView.swift; sourceTree = "<group>"; };
 		DDF847E72C5DABA30049BB3B /* WatchConfigAppleWatchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchConfigAppleWatchView.swift; sourceTree = "<group>"; };
 		DDF847E92C5DABAC0049BB3B /* WatchConfigGarminView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchConfigGarminView.swift; sourceTree = "<group>"; };
+		DDFF202E2DB1D14500AB8A96 /* NotificationPermissionStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPermissionStepView.swift; sourceTree = "<group>"; };
+		DDFF20302DB1D15500AB8A96 /* BluetoothPermissionStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BluetoothPermissionStepView.swift; sourceTree = "<group>"; };
 		DDFF20492DB29EF500AB8A96 /* WatchLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchLogger.swift; sourceTree = "<group>"; };
 		DDFF204D2DB2C00B00AB8A96 /* WatchStateSnapshot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchStateSnapshot.swift; sourceTree = "<group>"; };
 		DDFF204F2DB2C11900AB8A96 /* WatchStateSnapshot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchStateSnapshot.swift; sourceTree = "<group>"; };
-		DDFF202E2DB1D14500AB8A96 /* NotificationPermissionStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPermissionStepView.swift; sourceTree = "<group>"; };
-		DDFF20302DB1D15500AB8A96 /* BluetoothPermissionStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BluetoothPermissionStepView.swift; sourceTree = "<group>"; };
 		E00EEBFD27368630002FF094 /* ServiceAssembly.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceAssembly.swift; sourceTree = "<group>"; };
 		E00EEBFE27368630002FF094 /* SecurityAssembly.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecurityAssembly.swift; sourceTree = "<group>"; };
 		E00EEBFF27368630002FF094 /* StorageAssembly.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StorageAssembly.swift; sourceTree = "<group>"; };
@@ -2220,6 +2222,7 @@
 		3883582E25EEAFC000E024B2 /* Views */ = {
 			isa = PBXGroup;
 			children = (
+				DD6A4E072DBD95F1008C4B26 /* BluetoothRequiredView.swift */,
 				3811DE5925C9D4D500A708ED /* ViewModifiers.swift */,
 				3883581B25EE79BB00E024B2 /* TextFieldWithToolBar.swift */,
 				383420D825FFEB3F002D46C1 /* Popup.swift */,
@@ -4290,6 +4293,7 @@
 				DD1745442C55C60E00211FAC /* AutosensSettingsDataFlow.swift in Sources */,
 				BD249DA72D42FE4600412DEB /* Calendar+GlucoseStatsChart.swift in Sources */,
 				BDCAF2382C639F35002DC907 /* SettingItems.swift in Sources */,
+				DD6A4E082DBD95F1008C4B26 /* BluetoothRequiredView.swift in Sources */,
 				58D08B342C8DF9A700AA37D3 /* CobIobChart.swift in Sources */,
 				642F76A05A4FF530463A9FD0 /* NightscoutConfigRootView.swift in Sources */,
 				BD249D9B2D42FCDB00412DEB /* LoopChartSetup.swift in Sources */,

+ 6 - 6
Trio/Sources/Localizations/Main/Localizable.xcstrings

@@ -47686,9 +47686,6 @@
         }
       }
     },
-    "Bluetooth Access Required" : {
-
-    },
     "Bluetooth is used to communicate with insulin pump and continuous glucose monitor devices." : {
       "localizations" : {
         "bg" : {
@@ -47897,6 +47894,9 @@
         }
       }
     },
+    "Bluetooth Required" : {
+
+    },
     "Bluetooth State restored (APS restarted?). Found %d peripherals, and connected to %@ with identifier %@" : {
       "comment" : "Restored state message",
       "extractionState" : "manual",
@@ -87587,9 +87587,6 @@
         }
       }
     },
-    "Enable Bluetooth in Settings" : {
-
-    },
     "Enable device connectivity" : {
       "localizations" : {
         "bg" : {
@@ -197343,6 +197340,9 @@
         }
       }
     },
+    "Tap to Enable Bluetooth in iOS Settings" : {
+
+    },
     "tapped save schedules" : {
       "extractionState" : "manual",
       "localizations" : {

+ 2 - 12
Trio/Sources/Modules/CGMSettings/View/CGMRootView.swift

@@ -37,19 +37,9 @@ extension CGMSettings {
                         content: {
                             if bluetoothManager.bluetoothAuthorization != .authorized {
                                 HStack {
-                                    Image(systemName: "exclamationmark.triangle.fill")
-                                        .foregroundStyle(.red)
-                                    Text("Bluetooth Access Required")
-                                        .foregroundColor(.red)
                                     Spacer()
-                                    Button(action: {
-                                        if let url = URL(string: UIApplication.openSettingsURLString) {
-                                            UIApplication.shared.open(url)
-                                        }
-                                    }) {
-                                        Text("Enable")
-                                            .foregroundColor(.blue)
-                                    }
+                                    BluetoothRequiredView()
+                                    Spacer()
                                 }
                             } else {
                                 let cgmState = state.cgmCurrent

+ 1 - 21
Trio/Sources/Modules/Home/View/Header/CurrentGlucoseView.swift

@@ -11,7 +11,6 @@ struct CurrentGlucoseView: View {
     var currentGlucoseTarget: Decimal
     let glucoseColorScheme: GlucoseColorScheme
     let glucose: [GlucoseStored] // This contains the last two glucose values, no matter if its manual or a cgm reading
-    let bluetoothManager: BluetoothStateManager?
     @State private var rotationDegrees: Double = 0.0
     @State private var angularGradient = AngularGradient(colors: [
         Color(red: 0.7215686275, green: 0.3411764706, blue: 1),
@@ -42,26 +41,7 @@ struct CurrentGlucoseView: View {
     var body: some View {
         let triangleColor = Color(red: 0.262745098, green: 0.7333333333, blue: 0.9137254902)
 
-        if let bluetoothManager = bluetoothManager, bluetoothManager.bluetoothAuthorization != .authorized {
-            VStack(alignment: .center, spacing: 12) {
-                HStack {
-                    Image(systemName: "exclamationmark.triangle.fill")
-                        .foregroundStyle(.red)
-                        .font(.system(size: 20))
-                    Text("Bluetooth Access Required")
-                        .font(.caption)
-                        .bold()
-                }
-                Text("Enable Bluetooth in Settings")
-                    .font(.caption)
-                    .foregroundColor(.secondary)
-            }
-            .onTapGesture {
-                if let url = URL(string: UIApplication.openSettingsURLString) {
-                    UIApplication.shared.open(url)
-                }
-            }
-        } else if cgmAvailable {
+        if cgmAvailable {
             ZStack {
                 TrendShape(gradient: angularGradient, color: triangleColor)
                     .rotationEffect(.degrees(rotationDegrees))

+ 1 - 21
Trio/Sources/Modules/Home/View/Header/PumpView.swift

@@ -8,7 +8,6 @@ struct PumpView: View {
     let timerDate: Date
     let pumpStatusHighlightMessage: String?
     let battery: [OpenAPS_Battery]
-    let bluetoothManager: BluetoothStateManager?
     @Environment(\.colorScheme) var colorScheme
 
     private var batteryFormatter: NumberFormatter {
@@ -18,26 +17,7 @@ struct PumpView: View {
     }
 
     var body: some View {
-        if let bluetoothManager = bluetoothManager, bluetoothManager.bluetoothAuthorization != .authorized {
-            VStack(alignment: .center, spacing: 12) {
-                HStack {
-                    Image(systemName: "exclamationmark.triangle.fill")
-                        .foregroundStyle(.red)
-                        .font(.system(size: 20))
-                    Text("Bluetooth Access Required")
-                        .font(.caption)
-                        .bold()
-                }
-                Text("Enable Bluetooth in Settings")
-                    .font(.caption)
-                    .foregroundColor(.secondary)
-            }
-            .onTapGesture {
-                if let url = URL(string: UIApplication.openSettingsURLString) {
-                    UIApplication.shared.open(url)
-                }
-            }
-        } else if let pumpStatusHighlightMessage = pumpStatusHighlightMessage { // display message instead pump info
+        if let pumpStatusHighlightMessage = pumpStatusHighlightMessage { // display message instead pump info
             VStack(alignment: .center) {
                 Text(pumpStatusHighlightMessage).font(.footnote).fontWeight(.bold)
                     .multilineTextAlignment(.center).frame(maxWidth: /*@START_MENU_TOKEN@*/ .infinity/*@END_MENU_TOKEN@*/)

+ 20 - 16
Trio/Sources/Modules/Home/View/HomeRootView.swift

@@ -126,8 +126,7 @@ extension Home {
                 cgmAvailable: state.cgmAvailable,
                 currentGlucoseTarget: state.currentGlucoseTarget,
                 glucoseColorScheme: state.glucoseColorScheme,
-                glucose: state.latestTwoGlucoseValues,
-                bluetoothManager: state.bluetoothManager
+                glucose: state.latestTwoGlucoseValues
             ).scaleEffect(0.9)
                 .onTapGesture {
                     if !state.cgmAvailable {
@@ -150,8 +149,7 @@ extension Home {
                 expiresAtDate: state.pumpExpiresAtDate,
                 timerDate: state.timerDate,
                 pumpStatusHighlightMessage: state.pumpStatusHighlightMessage,
-                battery: state.batteryFromPersistence,
-                bluetoothManager: state.bluetoothManager
+                battery: state.batteryFromPersistence
             )
             .onTapGesture {
                 if state.pumpDisplayState == nil {
@@ -846,20 +844,26 @@ extension Home {
         @ViewBuilder func mainViewElements(_ geo: GeometryProxy) -> some View {
             VStack(spacing: 0) {
                 ZStack {
-                    /// glucose bobble
-                    glucoseView
+                    if let apsManager = state.apsManager, let bluetoothManager = apsManager.bluetoothManager,
+                       bluetoothManager.bluetoothAuthorization != .authorized
+                    {
+                        BluetoothRequiredView()
+                    } else {
+                        /// right panel with loop status and evBG
+                        HStack {
+                            Spacer()
+                            rightHeaderPanel(geo)
+                        }.padding(.trailing, 20)
 
-                    /// right panel with loop status and evBG
-                    HStack {
-                        Spacer()
-                        rightHeaderPanel(geo)
-                    }.padding(.trailing, 20)
+                        /// glucose bobble
+                        glucoseView
 
-                    /// left panel with pump related info
-                    HStack {
-                        pumpView
-                        Spacer()
-                    }.padding(.leading, 20)
+                        /// left panel with pump related info
+                        HStack {
+                            pumpView
+                            Spacer()
+                        }.padding(.leading, 20)
+                    }
                 }
                 .padding(.top, 10)
                 .safeAreaInset(edge: .top, spacing: 0) {

+ 2 - 12
Trio/Sources/Modules/PumpConfig/View/PumpConfigRootView.swift

@@ -26,19 +26,9 @@ extension PumpConfig {
                         content: {
                             if bluetoothManager.bluetoothAuthorization != .authorized {
                                 HStack {
-                                    Image(systemName: "exclamationmark.triangle.fill")
-                                        .foregroundStyle(.red)
-                                    Text("Bluetooth Access Required")
-                                        .foregroundColor(.red)
                                     Spacer()
-                                    Button(action: {
-                                        if let url = URL(string: UIApplication.openSettingsURLString) {
-                                            UIApplication.shared.open(url)
-                                        }
-                                    }) {
-                                        Text("Enable")
-                                            .foregroundColor(.blue)
-                                    }
+                                    BluetoothRequiredView()
+                                    Spacer()
                                 }
                             } else if let pumpState = state.pumpState {
                                 Button {

+ 2 - 13
Trio/Sources/Services/Bluetooth/BluetoothStateManager.swift

@@ -3,24 +3,13 @@ import LoopKit
 import LoopKitUI
 import Swinject
 
-protocol BluetoothStateManager: BluetoothProvider {
-//    var isBluetoothAuthorized: Bool { get }
-//    var isBluetoothDenied: Bool { get }
-}
+protocol BluetoothStateManager: BluetoothProvider {}
 
 public class BaseBluetoothStateManager: NSObject, BluetoothStateManager, Injectable {
     private var completion: ((BluetoothAuthorization) -> Void)?
     private var centralManager: CBCentralManager?
     private var bluetoothObservers = WeakSynchronizedSet<BluetoothObserver>()
-
-//    public var isBluetoothAuthorized: Bool {
-//        bluetoothAuthorization == .authorized
-//    }
-//
-//    public var isBluetoothDenied: Bool {
-//        bluetoothAuthorization == .denied || bluetoothAuthorization == .restricted
-//    }
-
+    
     init(resolver: Resolver) {
         super.init()
         injectServices(resolver)

+ 35 - 0
Trio/Sources/Views/BluetoothRequiredView.swift

@@ -0,0 +1,35 @@
+//
+//  BluetoothRequiredView.swift
+//  Trio
+//
+//  Created by Cengiz Deniz on 27.04.25.
+//
+import SwiftUI
+
+public struct BluetoothRequiredView: View {
+    public var body: some View {
+        VStack(alignment: .center, spacing: 12) {
+            HStack {
+                Image("logo.bluetooth.capsule.portrait.fill")
+                    .foregroundStyle(Color.red)
+                Text("Bluetooth Required")
+            }
+            .font(.headline.bold())
+            .padding(.vertical, 6)
+            .padding(.horizontal, 12)
+            .overlay(
+                Capsule()
+                    .stroke(Color.red.opacity(0.75), lineWidth: 2)
+            )
+
+            Text("Tap to Enable Bluetooth in iOS Settings")
+                .font(.subheadline.bold())
+                .foregroundStyle(Color.primary.opacity(0.8))
+        }
+        .onTapGesture {
+            if let url = URL(string: UIApplication.openSettingsURLString) {
+                UIApplication.shared.open(url)
+            }
+        }
+    }
+}