Selaa lähdekoodia

Merge branch 'dev' into update_feat/dev-medtrum

marionbarker 6 kuukautta sitten
vanhempi
commit
bde338fbe8

+ 1 - 1
CGMBLEKit

@@ -1 +1 @@
-Subproject commit 1cc9e9e7627cf8fb76ccdb015dd6991196038e31
+Subproject commit 26fa00bed8c2f5e4b52ecb3241b422d058117c2c

+ 1 - 1
Config.xcconfig

@@ -19,7 +19,7 @@ TRIO_APP_GROUP_ID = group.org.nightscout.$(DEVELOPMENT_TEAM).trio.trio-app-group
 
 
 // The developers set the version numbers, please leave them alone
 // The developers set the version numbers, please leave them alone
 APP_VERSION = 0.6.0
 APP_VERSION = 0.6.0
-APP_DEV_VERSION = 0.6.0.16
+APP_DEV_VERSION = 0.6.0.20
 APP_BUILD_NUMBER = 1
 APP_BUILD_NUMBER = 1
 COPYRIGHT_NOTICE =
 COPYRIGHT_NOTICE =
 
 

+ 1 - 1
DanaKit

@@ -1 +1 @@
-Subproject commit 084de69f69b1b17c92b595b4d5afeaed5b5d1e55
+Subproject commit f740e6c1858c121dc96eb6a18b931c8fe2fb7519

+ 1 - 1
G7SensorKit

@@ -1 +1 @@
-Subproject commit 9fa27889f0b216cbe0a23844e888de6698793b63
+Subproject commit 43f55ad8e1227fa6b4bec25d152726c56c0ffb0c

+ 1 - 1
LibreTransmitter

@@ -1 +1 @@
-Subproject commit 1950f1fec2a0e9f256c1be6e5bafd06ff79d3144
+Subproject commit 25c31bae22082caaa6823179010129912d6c8f8f

+ 1 - 1
LoopKit

@@ -1 +1 @@
-Subproject commit ddee20aca806f7635b8421617a675ddbd9c6d924
+Subproject commit ce07c0993b1038f6f60ea5b6db7c23da0be3fee6

+ 1 - 1
OmniBLE

@@ -1 +1 @@
-Subproject commit e4378ba744a46c5f06f9507eabceb4072c058992
+Subproject commit d8375ebf242e0d0e02ace7a03d9e1632557de38e

+ 1 - 1
OmniKit

@@ -1 +1 @@
-Subproject commit 1be14fcc27f22258cf8daa0355ac70c89737c0cc
+Subproject commit 1a73635568750289ac4d2f702b6bf191efbdda9f

+ 1 - 1
RileyLinkKit

@@ -1 +1 @@
-Subproject commit b280e8b9b7e75674b763f3ebf96d8b21dddcf80a
+Subproject commit c818fa8c90c0c98a4ba26cd18dacfeed01cc2bd5

+ 1 - 1
TidepoolService

@@ -1 +1 @@
-Subproject commit 59b0cd9384d180c7cccaf2cd2416fa2592a0ce45
+Subproject commit 84cab9b60e65b4aa814b0e12024a5e068ca65bfd

+ 21 - 1
Trio/Sources/APS/APSManager.swift

@@ -20,6 +20,8 @@ protocol APSManager {
     var pumpExpiresAtDate: CurrentValueSubject<Date?, Never> { get }
     var pumpExpiresAtDate: CurrentValueSubject<Date?, Never> { get }
     var pumpActivatedAtDate: CurrentValueSubject<Date?, Never> { get }
     var pumpActivatedAtDate: CurrentValueSubject<Date?, Never> { get }
     var isManualTempBasal: Bool { get }
     var isManualTempBasal: Bool { get }
+    var isScheduledBasal: Bool? { get }
+    var isSuspended: Bool { get }
     func enactTempBasal(rate: Double, duration: TimeInterval) async
     func enactTempBasal(rate: Double, duration: TimeInterval) async
     func determineBasal() async throws
     func determineBasal() async throws
     func determineBasalSync() async throws
     func determineBasalSync() async throws
@@ -105,6 +107,10 @@ final class BaseAPSManager: APSManager, Injectable {
 
 
     @Persisted(key: "isManualTempBasal") var isManualTempBasal: Bool = false
     @Persisted(key: "isManualTempBasal") var isManualTempBasal: Bool = false
 
 
+    @Persisted(key: "isScheduledBasal") var isScheduledBasal: Bool? = false
+
+    @Persisted(key: "isSuspended") var isSuspended: Bool = false
+
     let isLooping = CurrentValueSubject<Bool, Never>(false)
     let isLooping = CurrentValueSubject<Bool, Never>(false)
     let lastLoopDateSubject = PassthroughSubject<Date, Never>()
     let lastLoopDateSubject = PassthroughSubject<Date, Never>()
     let lastError = CurrentValueSubject<Error?, Never>(nil)
     let lastError = CurrentValueSubject<Error?, Never>(nil)
@@ -188,7 +194,21 @@ final class BaseAPSManager: APSManager, Injectable {
             }
             }
             .store(in: &lifetime)
             .store(in: &lifetime)
 
 
-        // manage a manual Temp Basal from OmniPod - Force loop() after stop a temp basal or finished
+        deviceDataManager.scheduledBasal
+            .receive(on: processQueue)
+            .sink { scheduledBasal in
+                self.isScheduledBasal = scheduledBasal
+            }
+            .store(in: &lifetime)
+
+        deviceDataManager.suspended
+            .receive(on: processQueue)
+            .sink { suspended in
+                self.isSuspended = suspended
+            }
+            .store(in: &lifetime)
+
+        // manage a manual Temp Basal from PumpManager - force loop() after manual temp basal is cancelled or finishes
         deviceDataManager.manualTempBasal
         deviceDataManager.manualTempBasal
             .receive(on: processQueue)
             .receive(on: processQueue)
             .sink { manualBasal in
             .sink { manualBasal in

+ 28 - 4
Trio/Sources/APS/DeviceDataManager.swift

@@ -23,6 +23,8 @@ protocol DeviceDataManager: GlucoseSource {
     var recommendsLoop: PassthroughSubject<Void, Never> { get }
     var recommendsLoop: PassthroughSubject<Void, Never> { get }
     var bolusTrigger: PassthroughSubject<Bool, Never> { get }
     var bolusTrigger: PassthroughSubject<Bool, Never> { get }
     var manualTempBasal: PassthroughSubject<Bool, Never> { get }
     var manualTempBasal: PassthroughSubject<Bool, Never> { get }
+    var scheduledBasal: PassthroughSubject<Bool?, Never> { get }
+    var suspended: PassthroughSubject<Bool, Never> { get }
     var errorSubject: PassthroughSubject<Error, Never> { get }
     var errorSubject: PassthroughSubject<Error, Never> { get }
     var pumpName: CurrentValueSubject<String, Never> { get }
     var pumpName: CurrentValueSubject<String, Never> { get }
     var pumpExpiresAtDate: CurrentValueSubject<Date?, Never> { get }
     var pumpExpiresAtDate: CurrentValueSubject<Date?, Never> { get }
@@ -72,6 +74,8 @@ final class BaseDeviceDataManager: DeviceDataManager, Injectable {
     let errorSubject = PassthroughSubject<Error, Never>()
     let errorSubject = PassthroughSubject<Error, Never>()
     let pumpNewStatus = PassthroughSubject<Void, Never>()
     let pumpNewStatus = PassthroughSubject<Void, Never>()
     let manualTempBasal = PassthroughSubject<Bool, Never>()
     let manualTempBasal = PassthroughSubject<Bool, Never>()
+    let scheduledBasal = PassthroughSubject<Bool?, Never>()
+    let suspended = PassthroughSubject<Bool, Never>()
 
 
     private let router = TrioApp.resolver.resolve(Router.self)!
     private let router = TrioApp.resolver.resolve(Router.self)!
     @SyncAccess private var pumpUpdateCancellable: AnyCancellable?
     @SyncAccess private var pumpUpdateCancellable: AnyCancellable?
@@ -81,11 +85,15 @@ final class BaseDeviceDataManager: DeviceDataManager, Injectable {
 
 
     var pumpManager: PumpManagerUI? {
     var pumpManager: PumpManagerUI? {
         didSet {
         didSet {
-            pumpManager?.pumpManagerDelegate = self
-            pumpManager?.delegateQueue = processQueue
-            rawPumpManager = pumpManager?.rawValue
-            UserDefaults.standard.clearLegacyPumpManagerRawValue()
             if let pumpManager = pumpManager {
             if let pumpManager = pumpManager {
+                pumpManager.pumpManagerDelegate = self
+                pumpManager.delegateQueue = processQueue
+
+                /// Since the pump manager has been successfully instantiated from its saved state,
+                /// copy its rawValue to rawPumpManager which will be saved to persistant storage.
+                rawPumpManager = pumpManager.rawValue
+                UserDefaults.standard.clearLegacyPumpManagerRawValue()
+
                 pumpDisplayState.value = PumpDisplayState(name: pumpManager.localizedTitle, image: pumpManager.smallImage)
                 pumpDisplayState.value = PumpDisplayState(name: pumpManager.localizedTitle, image: pumpManager.smallImage)
                 pumpName.send(pumpManager.localizedTitle)
                 pumpName.send(pumpManager.localizedTitle)
 
 
@@ -432,6 +440,22 @@ extension BaseDeviceDataManager: PumpManagerDelegate {
             bolusTrigger.send(false)
             bolusTrigger.send(false)
         }
         }
 
 
+        switch status.basalDeliveryState {
+        case let .active(at):
+            if at == .distantPast {
+                scheduledBasal.send(nil) // pump is not currently available
+            } else {
+                suspended.send(false)
+                scheduledBasal.send(true)
+            }
+        case .suspended:
+            suspended.send(true)
+            scheduledBasal.send(false)
+        default:
+            suspended.send(false)
+            scheduledBasal.send(false)
+        }
+
         if status.insulinType != oldStatus.insulinType {
         if status.insulinType != oldStatus.insulinType {
             settingsManager.updateInsulinCurve(status.insulinType)
             settingsManager.updateInsulinCurve(status.insulinType)
         }
         }

+ 45 - 34
Trio/Sources/APS/Storage/TDDStorage.swift

@@ -545,41 +545,8 @@ final class BaseTDDStorage: TDDStorage, Injectable {
               let minutes = Int(timeComponents[1])
               let minutes = Int(timeComponents[1])
         else { return nil }
         else { return nil }
 
 
-        // Convert time to total minutes since midnight for easier comparison
         let totalMinutes = hours * 60 + minutes
         let totalMinutes = hours * 60 + minutes
-
-        // Special case: If profile has only one entry, it applies for full 24 hours
-        // Return its rate immediately without searching
-        if profile.count == 1 {
-            return profile[0].rate
-        }
-
-        // Use binary search to efficiently find the applicable basal rate
-        // Profile entries are sorted by minutes, so we can divide and conquer
-        var left = 0
-        var right = profile.count - 1
-
-        while left <= right {
-            let mid = (left + right) / 2
-            let entry = profile[mid]
-            // Get end time for current entry - either next entry's start time or end of day (1440 mins)
-            let nextMinutes = mid + 1 < profile.count ? profile[mid + 1].minutes : 1440
-
-            // Check if target time falls within current entry's time range
-            if totalMinutes >= entry.minutes, totalMinutes < nextMinutes {
-                return entry.rate
-            }
-
-            // Adjust search range based on comparison
-            if totalMinutes < entry.minutes {
-                right = mid - 1 // Search in left half if target time is earlier
-            } else {
-                left = mid + 1 // Search in right half if target time is later
-            }
-        }
-
-        // No applicable rate found for the given time
-        return nil
+        return findBasalRateForOffset(for: totalMinutes, in: profile)
     }
     }
 
 
     /// Calculates a weighted average of Total Daily Dose (TDD) based on recent and historical data
     /// Calculates a weighted average of Total Daily Dose (TDD) based on recent and historical data
@@ -692,3 +659,47 @@ extension Decimal {
         return result
         return result
     }
     }
 }
 }
+
+/// Finds the basal rate at the specified minute offset using binary search
+/// - Parameters:
+///   - totalMinutes: minute offset into a 24 hour day
+///   - profile: Array of basal profile entries sorted by time
+/// - Returns: Basal rate in units per hour, or nil if not found
+func findBasalRateForOffset(for totalMinutes: Int, in profile: [BasalProfileEntry]) -> Decimal? {
+    if profile.isEmpty {
+        return nil // not yet initalized
+    }
+
+    // Special case: If profile has only one entry, it applies for full 24 hours
+    // Return its rate immediately without searching
+    if profile.count == 1 {
+        return profile[0].rate
+    }
+
+    // Use binary search to efficiently find the applicable basal rate
+    // Profile entries are sorted by minutes, so we can divide and conquer
+    var left = 0
+    var right = profile.count - 1
+
+    while left <= right {
+        let mid = (left + right) / 2
+        let entry = profile[mid]
+        // Get end time for current entry - either next entry's start time or end of day (24 * 60 mins)
+        let nextMinutes = mid + 1 < profile.count ? profile[mid + 1].minutes : 24 * 60
+
+        // Check if target time falls within current entry's time range
+        if totalMinutes >= entry.minutes, totalMinutes < nextMinutes {
+            return entry.rate
+        }
+
+        // Adjust search range based on comparison
+        if totalMinutes < entry.minutes {
+            right = mid - 1 // Search in left half if target time is earlier
+        } else {
+            left = mid + 1 // Search in right half if target time is later
+        }
+    }
+
+    // No applicable rate found for the given time
+    return nil
+}

+ 6 - 6
Trio/Sources/Modules/BasalProfileEditor/BasalProfileEditorStateModel.swift

@@ -113,6 +113,12 @@ extension BasalProfileEditor {
                         // Successfully saved and synced
                         // Successfully saved and synced
                         self.initialItems = self.items.map { Item(rateIndex: $0.rateIndex, timeIndex: $0.timeIndex) }
                         self.initialItems = self.items.map { Item(rateIndex: $0.rateIndex, timeIndex: $0.timeIndex) }
 
 
+                        DispatchQueue.main.async {
+                            self.broadcaster.notify(BasalProfileObserver.self, on: .main) {
+                                $0.basalProfileDidChange(profile)
+                            }
+                        }
+
                         Task.detached(priority: .low) {
                         Task.detached(priority: .low) {
                             do {
                             do {
                                 debug(.nightscout, "Attempting to upload basal rates to Nightscout")
                                 debug(.nightscout, "Attempting to upload basal rates to Nightscout")
@@ -130,12 +136,6 @@ extension BasalProfileEditor {
                     print("We were successful")
                     print("We were successful")
                 }
                 }
                 .store(in: &lifetime)
                 .store(in: &lifetime)
-
-            DispatchQueue.main.async {
-                self.broadcaster.notify(BasalProfileObserver.self, on: .main) {
-                    $0.basalProfileDidChange(profile)
-                }
-            }
         }
         }
 
 
         @MainActor func validate() {
         @MainActor func validate() {

+ 2 - 6
Trio/Sources/Modules/Home/HomeStateModel+Setup/PumpHistorySetup.swift

@@ -41,15 +41,11 @@ extension Home.StateModel {
         insulinFromPersistence = insulinObjects
         insulinFromPersistence = insulinObjects
 
 
         manualTempBasal = apsManager.isManualTempBasal
         manualTempBasal = apsManager.isManualTempBasal
-        tempBasals = insulinFromPersistence.filter({ $0.tempBasal != nil })
+        tempBasals = insulinFromPersistence.filter { $0.tempBasal != nil }
 
 
-        suspensions = insulinFromPersistence.filter {
+        suspendAndResumeEvents = insulinFromPersistence.filter {
             $0.type == EventType.pumpSuspend.rawValue || $0.type == EventType.pumpResume.rawValue
             $0.type == EventType.pumpSuspend.rawValue || $0.type == EventType.pumpResume.rawValue
         }
         }
-        let lastSuspension = suspensions.last
-
-        pumpSuspended = tempBasals.last?.timestamp ?? Date() > lastSuspension?.timestamp ?? .distantPast && lastSuspension?
-            .type == EventType.pumpSuspend.rawValue
     }
     }
 
 
     // Setup Last Bolus to display the bolus progress bar
     // Setup Last Bolus to display the bolus progress bar

+ 14 - 4
Trio/Sources/Modules/Home/HomeStateModel.swift

@@ -2,6 +2,7 @@ import CGMBLEKitUI
 import Combine
 import Combine
 import CoreData
 import CoreData
 import Foundation
 import Foundation
+import LoopKit
 import LoopKitUI
 import LoopKitUI
 import Observation
 import Observation
 import SwiftDate
 import SwiftDate
@@ -40,7 +41,6 @@ extension Home {
         var targetProfiles: [TargetProfile] = []
         var targetProfiles: [TargetProfile] = []
         var timerDate = Date()
         var timerDate = Date()
         var closedLoop = false
         var closedLoop = false
-        var pumpSuspended = false
         var isLooping = false
         var isLooping = false
         var statusTitle = ""
         var statusTitle = ""
         var lastLoopDate: Date = .distantPast
         var lastLoopDate: Date = .distantPast
@@ -93,7 +93,7 @@ extension Home {
         var fetchedTDDs: [TDD] = []
         var fetchedTDDs: [TDD] = []
         var insulinFromPersistence: [PumpEventStored] = []
         var insulinFromPersistence: [PumpEventStored] = []
         var tempBasals: [PumpEventStored] = []
         var tempBasals: [PumpEventStored] = []
-        var suspensions: [PumpEventStored] = []
+        var suspendAndResumeEvents: [PumpEventStored] = []
         var batteryFromPersistence: [OpenAPS_Battery] = []
         var batteryFromPersistence: [OpenAPS_Battery] = []
         var lastPumpBolus: PumpEventStored?
         var lastPumpBolus: PumpEventStored?
         var overrides: [OverrideStored] = []
         var overrides: [OverrideStored] = []
@@ -108,6 +108,7 @@ extension Home {
         var cgmAvailable: Bool = false
         var cgmAvailable: Bool = false
         var listOfCGM: [CGMModel] = []
         var listOfCGM: [CGMModel] = []
         var cgmCurrent = cgmDefaultModel
         var cgmCurrent = cgmDefaultModel
+        var pumpInitialSettings = PumpConfig.PumpInitialSettings.default
         var shouldRunDeleteOnSettingsChange = true
         var shouldRunDeleteOnSettingsChange = true
 
 
         var showCarbsRequiredBadge: Bool = true
         var showCarbsRequiredBadge: Bool = true
@@ -556,9 +557,11 @@ extension Home {
         }
         }
 
 
         private func setupPumpSettings() async {
         private func setupPumpSettings() async {
-            let maxBasal = await provider.pumpSettings().maxBasal
+            let settings = await provider.pumpSettings()
             await MainActor.run {
             await MainActor.run {
-                self.maxBasal = maxBasal
+                self.maxBasal = settings.maxBasal
+                self.pumpInitialSettings.maxBasalRateUnitsPerHour = Double(settings.maxBasal)
+                self.pumpInitialSettings.maxBolusUnits = Double(settings.maxBolus)
             }
             }
         }
         }
 
 
@@ -566,6 +569,13 @@ extension Home {
             let basalProfile = await provider.getBasalProfile()
             let basalProfile = await provider.getBasalProfile()
             await MainActor.run {
             await MainActor.run {
                 self.basalProfile = basalProfile
                 self.basalProfile = basalProfile
+
+                if let schedule = BasalRateSchedule(
+                    dailyItems: basalProfile
+                        .map { RepeatingScheduleValue(startTime: TimeInterval($0.minutes * 60), value: Double($0.rate)) }
+                ) {
+                    self.pumpInitialSettings.basalSchedule = schedule
+                }
             }
             }
         }
         }
 
 

+ 3 - 2
Trio/Sources/Modules/Home/View/Chart/ChartElements/BasalChart.swift

@@ -104,7 +104,7 @@ extension MainChartView {
     }
     }
 
 
     func drawSuspensions() -> some ChartContent {
     func drawSuspensions() -> some ChartContent {
-        let suspensions = state.suspensions
+        let suspensions = state.suspendAndResumeEvents
         return ForEach(suspensions) { suspension in
         return ForEach(suspensions) { suspension in
             let now = Date()
             let now = Date()
 
 
@@ -154,7 +154,8 @@ extension MainChartView {
             let duration = temp.tempBasal?.duration ?? 0
             let duration = temp.tempBasal?.duration ?? 0
             let timestamp = temp.timestamp ?? Date()
             let timestamp = temp.timestamp ?? Date()
             let end = timestamp + duration.minutes
             let end = timestamp + duration.minutes
-            let isInsulinSuspended = state.suspensions.contains { $0.timestamp ?? now >= timestamp && $0.timestamp ?? now <= end }
+            let isInsulinSuspended = state.suspendAndResumeEvents
+                .contains { $0.timestamp ?? now >= timestamp && $0.timestamp ?? now <= end }
 
 
             let rate = Double(truncating: temp.tempBasal?.rate ?? Decimal.zero as NSDecimalNumber) * (isInsulinSuspended ? 0 : 1)
             let rate = Double(truncating: temp.tempBasal?.rate ?? Decimal.zero as NSDecimalNumber) * (isInsulinSuspended ? 0 : 1)
 
 

+ 64 - 32
Trio/Sources/Modules/Home/View/HomeRootView.swift

@@ -163,22 +163,51 @@ extension Home {
             }
             }
         }
         }
 
 
-        var tempBasalString: String? {
-            guard let lastTempBasal = state.tempBasals.last?.tempBasal, let tempRate = lastTempBasal.rate else {
+        var basalString: String? {
+            var rate: NSNumber = 0
+            var manualBasalString = ""
+
+            guard let apsManager = state.apsManager else {
                 return nil
                 return nil
             }
             }
-            let rateString = Formatter.decimalFormatterWithTwoFractionDigits.string(from: tempRate as NSNumber) ?? "0"
-            var manualBasalString = ""
 
 
-            if let apsManager = state.apsManager, apsManager.isManualTempBasal {
-                manualBasalString = String(
-                    localized:
-                    " - Manual Basal ⚠️",
-                    comment: "Manual Temp basal"
-                )
+            if apsManager.isScheduledBasal == true {
+                guard let scheduledRate = scheduledBasalDeliveryRate(at: Date()) else {
+                    return nil
+                }
+                rate = scheduledRate
+            } else {
+                guard let lastTempBasal = state.tempBasals.last?.tempBasal, let tempRate = lastTempBasal.rate else {
+                    return nil
+                }
+                if apsManager.isManualTempBasal {
+                    manualBasalString = String(
+                        localized: " - Manual Basal ⚠️",
+                        comment: "Manual Temp basal"
+                    )
+                }
+                rate = tempRate
             }
             }
 
 
-            return rateString + String(localized: " U/hr", comment: "Unit per hour with space") + manualBasalString
+            let rateString = Formatter.decimalFormatterWithTwoFractionDigits.string(from: rate) ?? "0"
+            return rateString + String(localized: " U/hr", comment: "Unit per hour with space") +
+                manualBasalString
+        }
+
+        // Returns the scheduled basal rate for the current time based on the saved basal scheduled.
+        // Would be better if in the future BasalDeliveryStatus could be updated to include this info.
+        func scheduledBasalDeliveryRate(at when: Date) -> NSNumber? {
+            let calendar = Calendar(identifier: .gregorian)
+            // calendar.timeZone = timeZone /// should come from pumpManager in case it's different!
+
+            let hours = calendar.component(.hour, from: when)
+            let minutes = calendar.component(.minute, from: when)
+            let totalMinutes = hours * 60 + minutes
+
+            if let rate = findBasalRateForOffset(for: totalMinutes, in: state.basalProfile) {
+                return NSDecimalNumber(decimal: rate)
+            }
+            return nil
         }
         }
 
 
         var overrideString: String? {
         var overrideString: String? {
@@ -468,31 +497,34 @@ extension Home {
                         .font(.callout)
                         .font(.callout)
                 } else {
                 } else {
                     HStack {
                     HStack {
-                        if state.pumpSuspended {
-                            Text("Pump suspended")
-                                .font(.callout).fontWeight(.bold).fontDesign(.rounded)
-                                .foregroundColor(.loopGray)
-                        } else if let tempBasalString = tempBasalString {
+                        /// Only display the insulin delivery rate info if the pump is not
+                        /// suspended and is available (e.g., pod is paired & not faulted).
+                        let pumpAvailable = state.apsManager.isScheduledBasal != nil
+                        if !state.apsManager.isSuspended && pumpAvailable {
                             Image(systemName: "drop.circle")
                             Image(systemName: "drop.circle")
                                 .font(.callout)
                                 .font(.callout)
                                 .foregroundColor(.insulinTintColor)
                                 .foregroundColor(.insulinTintColor)
-                            if tempBasalString.count > 5 {
-                                Text(tempBasalString)
-                                    .font(.callout).fontWeight(.bold).fontDesign(.rounded)
-                                    .lineLimit(1)
-                                    .minimumScaleFactor(0.85)
-                                    .truncationMode(.tail)
-                                    .allowsTightening(true)
+                            if let basalString = self.basalString {
+                                /// Adjust opacity when displaying a scheduled basal rate
+                                let opacity = state.apsManager?.isScheduledBasal == true ? 0.6 : 1.0
+                                if basalString.count > 5 {
+                                    Text(basalString)
+                                        .font(.callout).fontWeight(.bold).fontDesign(.rounded)
+                                        .lineLimit(1)
+                                        .minimumScaleFactor(0.85)
+                                        .truncationMode(.tail)
+                                        .allowsTightening(true)
+                                        .opacity(opacity)
+                                } else {
+                                    // Short strings can just display normally
+                                    Text(basalString)
+                                        .font(.callout).fontWeight(.bold).fontDesign(.rounded)
+                                        .opacity(opacity)
+                                }
                             } else {
                             } else {
-                                // Short strings can just display normally
-                                Text(tempBasalString).font(.callout).fontWeight(.bold).fontDesign(.rounded)
+                                Text("No Data")
+                                    .font(.callout).fontWeight(.bold).fontDesign(.rounded)
                             }
                             }
-                        } else {
-                            Image(systemName: "drop.circle")
-                                .font(.callout)
-                                .foregroundColor(.insulinTintColor)
-                            Text("No Data")
-                                .font(.callout).fontWeight(.bold).fontDesign(.rounded)
                         }
                         }
                     }
                     }
                 }
                 }
@@ -966,7 +998,7 @@ extension Home {
                 } else {
                 } else {
                     PumpConfig.PumpSetupView(
                     PumpConfig.PumpSetupView(
                         pumpType: state.setupPumpType,
                         pumpType: state.setupPumpType,
-                        pumpInitialSettings: PumpConfig.PumpInitialSettings.default,
+                        pumpInitialSettings: state.pumpInitialSettings,
                         bluetoothManager: state.provider.apsManager.bluetoothManager!,
                         bluetoothManager: state.provider.apsManager.bluetoothManager!,
                         completionDelegate: state,
                         completionDelegate: state,
                         setupDelegate: state
                         setupDelegate: state

+ 3 - 3
Trio/Sources/Modules/PumpConfig/PumpConfigDataFlow.swift

@@ -15,9 +15,9 @@ enum PumpConfig {
     }
     }
 
 
     struct PumpInitialSettings {
     struct PumpInitialSettings {
-        let maxBolusUnits: Double
-        let maxBasalRateUnitsPerHour: Double
-        let basalSchedule: BasalRateSchedule
+        var maxBolusUnits: Double
+        var maxBasalRateUnitsPerHour: Double
+        var basalSchedule: BasalRateSchedule
 
 
         static let `default` = PumpInitialSettings(
         static let `default` = PumpInitialSettings(
             maxBolusUnits: 10,
             maxBolusUnits: 10,

+ 1 - 1
dexcom-share-client-swift

@@ -1 +1 @@
-Subproject commit 41cf95dab00f125f7a7602c433aac79fea8fc549
+Subproject commit 82a9179d444b3e79d5e9cfe99bbe7f298c4e8b40