polscm32 aka Marvout 1 год назад
Родитель
Сommit
fe6aed4abc

+ 42 - 0
FreeAPS/Sources/Helpers/Formatters.swift

@@ -28,6 +28,48 @@ extension Formatter {
         formatter.formatOptions = [.withInternetDateTime]
         return formatter
     }()
+
+    static let decimalFormatterWithTwoFractionDigits: NumberFormatter = {
+        let formatter = NumberFormatter()
+        formatter.numberStyle = .decimal
+        formatter.maximumFractionDigits = 2
+        return formatter
+    }()
+
+    static let dateFormatter: DateFormatter = {
+        let dateFormatter = DateFormatter()
+        dateFormatter.timeStyle = .short
+        return dateFormatter
+    }()
+
+    static let decimalFormatterWithOneFractionDigit: NumberFormatter = {
+        let formatter = NumberFormatter()
+        formatter.numberStyle = .decimal
+        formatter.maximumFractionDigits = 1
+        return formatter
+    }()
+
+    static let integerFormatter: NumberFormatter = {
+        let formatter = NumberFormatter()
+        formatter.numberStyle = .decimal
+        formatter.maximumFractionDigits = 0
+        return formatter
+    }()
+
+    static func glucoseFormatter(for units: GlucoseUnits) -> NumberFormatter {
+        let formatter = NumberFormatter()
+        formatter.numberStyle = .decimal
+        formatter.roundingMode = .halfUp
+
+        switch units {
+        case .mmolL:
+            formatter.maximumFractionDigits = 1
+        case .mgdL:
+            formatter.maximumFractionDigits = 0
+        }
+
+        return formatter
+    }
 }
 
 extension JSONDecoder.DateDecodingStrategy {

+ 3 - 20
FreeAPS/Sources/Modules/Adjustments/View/AdjustmentsRootView.swift

@@ -24,28 +24,11 @@ extension Adjustments {
         @Environment(\.colorScheme) var colorScheme
         @Environment(AppState.self) var appState
 
-        private var formatter: NumberFormatter {
-            let formatter = NumberFormatter()
-            formatter.numberStyle = .decimal
-            formatter.maximumFractionDigits = 0
-            return formatter
-        }
-
-        private var glucoseFormatter: NumberFormatter {
-            let formatter = NumberFormatter()
-            formatter.numberStyle = .decimal
-            formatter.maximumFractionDigits = 0
-            if state.units == .mmolL {
-                formatter.maximumFractionDigits = 1
-            }
-            formatter.roundingMode = .halfUp
-            return formatter
-        }
-
         private func formattedGlucose(glucose: Decimal) -> String {
             let formattedValue: String
             if state.units == .mgdL {
-                formattedValue = glucoseFormatter.string(from: glucose as NSDecimalNumber) ?? "\(glucose)"
+                formattedValue = Formatter.glucoseFormatter(for: state.units)
+                    .string(from: glucose as NSDecimalNumber) ?? "\(glucose)"
             } else {
                 formattedValue = glucose.formattedAsMmolL
             }
@@ -550,7 +533,7 @@ extension Adjustments {
                             Text("for")
                                 .foregroundColor(.secondary)
                                 .font(.caption)
-                            Text("\(formatter.string(from: (tempTarget.duration ?? 0) as NSNumber)!)")
+                            Text("\(Formatter.integerFormatter.string(from: (tempTarget.duration ?? 0) as NSNumber)!)")
                                 .foregroundColor(.secondary)
                                 .font(.caption)
                             Text("min")

+ 2 - 20
FreeAPS/Sources/Modules/Adjustments/View/TempTargets/AddTempTargetForm.swift

@@ -27,24 +27,6 @@ struct AddTempTargetForm: View {
     @State var hintLabel: String?
     var isCustomizedAdjustSens: Bool = false
 
-    private var formatter: NumberFormatter {
-        let formatter = NumberFormatter()
-        formatter.numberStyle = .decimal
-        formatter.maximumFractionDigits = 0
-        return formatter
-    }
-
-    private var glucoseFormatter: NumberFormatter {
-        let formatter = NumberFormatter()
-        formatter.numberStyle = .decimal
-        formatter.maximumFractionDigits = 0
-        if state.units == .mmolL {
-            formatter.maximumFractionDigits = 1
-        }
-        formatter.roundingMode = .halfUp
-        return formatter
-    }
-
     var body: some View {
         NavigationView {
             List {
@@ -331,13 +313,13 @@ struct AddTempTargetForm: View {
 
     private func formattedPercentage(_ value: Double) -> String {
         let percentageNumber = NSNumber(value: value)
-        return formatter.string(from: percentageNumber) ?? "\(value)"
+        return Formatter.integerFormatter.string(from: percentageNumber) ?? "\(value)"
     }
 
     private func formattedGlucose(glucose: Decimal) -> String {
         let formattedValue: String
         if state.units == .mgdL {
-            formattedValue = glucoseFormatter.string(from: glucose as NSDecimalNumber) ?? "\(glucose)"
+            formattedValue = Formatter.glucoseFormatter(for: state.units).string(from: glucose as NSDecimalNumber) ?? "\(glucose)"
         } else {
             formattedValue = glucose.formattedAsMmolL
         }

+ 24 - 50
FreeAPS/Sources/Modules/DataTable/View/DataTableRootView.swift

@@ -58,27 +58,6 @@ extension DataTable {
             animation: .bouncy
         ) var tempTargetRunStored: FetchedResults<TempTargetRunStored>
 
-        private var insulinFormatter: NumberFormatter {
-            let formatter = NumberFormatter()
-            formatter.numberStyle = .decimal
-            formatter.maximumFractionDigits = 2
-            return formatter
-        }
-
-        private var glucoseFormatter: NumberFormatter {
-            let formatter = NumberFormatter()
-            formatter.numberStyle = .decimal
-
-            if state.units == .mmolL {
-                formatter.maximumFractionDigits = 1
-                formatter.minimumFractionDigits = 1
-                formatter.roundingMode = .halfUp
-            } else {
-                formatter.maximumFractionDigits = 0
-            }
-            return formatter
-        }
-
         private var manualGlucoseFormatter: NumberFormatter {
             let formatter = NumberFormatter()
             formatter.numberStyle = .decimal
@@ -91,19 +70,6 @@ extension DataTable {
             return formatter
         }
 
-        private var dateFormatter: DateFormatter {
-            let formatter = DateFormatter()
-            formatter.timeStyle = .short
-            return formatter
-        }
-
-        private var numberFormatter: NumberFormatter {
-            let formatter = NumberFormatter()
-            formatter.numberStyle = .decimal
-            formatter.maximumFractionDigits = 2
-            return formatter
-        }
-
         var body: some View {
             ZStack(alignment: .center, content: {
                 VStack {
@@ -324,7 +290,8 @@ extension DataTable {
         }
 
         @ViewBuilder private func adjustmentView(for item: AdjustmentItem) -> some View {
-            let formattedDates = "\(dateFormatter.string(from: item.startDate)) - \(dateFormatter.string(from: item.endDate))"
+            let formattedDates =
+                "\(Formatter.dateFormatter.string(from: item.startDate)) - \(Formatter.dateFormatter.string(from: item.endDate))"
 
             let labels: [String] = [
                 "\(state.units == .mgdL ? item.target : item.target.asMmolL) \(state.units.rawValue)",
@@ -381,7 +348,7 @@ extension DataTable {
 
                             Spacer()
 
-                            Text(dateFormatter.string(from: glucose.date ?? Date()))
+                            Text(Formatter.dateFormatter.string(from: glucose.date ?? Date()))
                         }.swipeActions {
                             Button(
                                 "Delete",
@@ -391,9 +358,9 @@ extension DataTable {
                                     alertGlucoseToDelete = glucose
 
                                     alertTitle = "Delete Glucose?"
-                                    alertMessage = dateFormatter
+                                    alertMessage = Formatter.dateFormatter
                                         .string(from: glucose.date ?? Date()) + ", " +
-                                        (numberFormatter.string(for: glucose.glucose) ?? "0")
+                                        (Formatter.decimalFormatterWithTwoFractionDigits.string(for: glucose.glucose) ?? "0")
 
                                     isRemoveHistoryItemAlertPresented = true
                                 }
@@ -513,8 +480,11 @@ extension DataTable {
                 if let bolus = item.bolus, let amount = bolus.amount {
                     Image(systemName: "circle.fill").foregroundColor(Color.insulin)
                     Text(bolus.isSMB ? "SMB" : item.type ?? "Bolus")
-                    Text((insulinFormatter.string(from: amount) ?? "0") + NSLocalizedString(" U", comment: "Insulin unit"))
-                        .foregroundColor(.secondary)
+                    Text(
+                        (Formatter.decimalFormatterWithTwoFractionDigits.string(from: amount) ?? "0") +
+                            NSLocalizedString(" U", comment: "Insulin unit")
+                    )
+                    .foregroundColor(.secondary)
                     if bolus.isExternal {
                         Text(NSLocalizedString("External", comment: "External Insulin")).foregroundColor(.secondary)
                     }
@@ -522,7 +492,7 @@ extension DataTable {
                     Image(systemName: "circle.fill").foregroundColor(Color.insulin.opacity(0.4))
                     Text("Temp Basal")
                     Text(
-                        (insulinFormatter.string(from: rate) ?? "0") +
+                        (Formatter.decimalFormatterWithTwoFractionDigits.string(from: rate) ?? "0") +
                             NSLocalizedString(" U/hr", comment: "Unit insulin per hour")
                     )
                     .foregroundColor(.secondary)
@@ -534,7 +504,7 @@ extension DataTable {
                     Text(item.type ?? "Pump Event")
                 }
                 Spacer()
-                Text(dateFormatter.string(from: item.timestamp ?? Date())).moveDisabled(true)
+                Text(Formatter.dateFormatter.string(from: item.timestamp ?? Date())).moveDisabled(true)
             }
             .swipeActions {
                 if item.bolus != nil {
@@ -545,9 +515,9 @@ extension DataTable {
                         action: {
                             alertTreatmentToDelete = item
                             alertTitle = "Delete Insulin?"
-                            alertMessage = dateFormatter
+                            alertMessage = Formatter.dateFormatter
                                 .string(from: item.timestamp ?? Date()) + ", " +
-                                (insulinFormatter.string(from: item.bolus?.amount ?? 0) ?? "0") +
+                                (Formatter.decimalFormatterWithTwoFractionDigits.string(from: item.bolus?.amount ?? 0) ?? "0") +
                                 NSLocalizedString(" U", comment: "Insulin unit")
 
                             if let bolus = item.bolus {
@@ -585,19 +555,22 @@ extension DataTable {
                     if meal.isFPU {
                         Image(systemName: "circle.fill").foregroundColor(Color.orange.opacity(0.5))
                         Text("Fat / Protein")
-                        Text((numberFormatter.string(for: meal.carbs) ?? "0") + NSLocalizedString(" g", comment: "gram of carbs"))
+                        Text(
+                            (Formatter.decimalFormatterWithTwoFractionDigits.string(for: meal.carbs) ?? "0") +
+                                NSLocalizedString(" g", comment: "gram of carbs")
+                        )
                     } else {
                         Image(systemName: "circle.fill").foregroundColor(Color.loopYellow)
                         Text("Carbs")
                         Text(
-                            (numberFormatter.string(for: meal.carbs) ?? "0") +
+                            (Formatter.decimalFormatterWithTwoFractionDigits.string(for: meal.carbs) ?? "0") +
                                 NSLocalizedString(" g", comment: "gram of carb equilvalents")
                         )
                     }
 
                     Spacer()
 
-                    Text(dateFormatter.string(from: meal.date ?? Date()))
+                    Text(Formatter.dateFormatter.string(from: meal.date ?? Date()))
                         .moveDisabled(true)
                 }
                 if let note = meal.note, note != "" {
@@ -618,8 +591,9 @@ extension DataTable {
 
                         if !meal.isFPU {
                             alertTitle = "Delete Carbs?"
-                            alertMessage = dateFormatter
-                                .string(from: meal.date ?? Date()) + ", " + (numberFormatter.string(for: meal.carbs) ?? "0") +
+                            alertMessage = Formatter.dateFormatter
+                                .string(from: meal.date ?? Date()) + ", " +
+                                (Formatter.decimalFormatterWithTwoFractionDigits.string(for: meal.carbs) ?? "0") +
                                 NSLocalizedString(" g", comment: "gram of carbs")
                         } else {
                             alertTitle = "Delete Carb Equivalents?"
@@ -652,7 +626,7 @@ extension DataTable {
         // MARK: - Format glucose
 
         private func formatGlucose(_ value: Decimal, isManual: Bool) -> String {
-            let formatter = isManual ? manualGlucoseFormatter : glucoseFormatter
+            let formatter = isManual ? manualGlucoseFormatter : Formatter.glucoseFormatter(for: state.units)
             let glucoseValue = state.units == .mmolL ? value.asMmolL : value
             let formattedValue = formatter.string(from: glucoseValue as NSNumber) ?? "--"
 

+ 1 - 1
FreeAPS/Sources/Modules/Home/View/Chart/OverrideView.swift

@@ -4,7 +4,7 @@ import Foundation
 import SwiftUI
 
 struct OverrideView: ChartContent {
-    @ObservedObject var state: Home.StateModel // @ObservedObject will be replaced when converting to Observable
+    var state: Home.StateModel
     let overrides: [OverrideStored]
     let overrideRunStored: [OverrideRunStored]
     let units: GlucoseUnits

+ 0 - 20
FreeAPS/Sources/Modules/Home/View/Header/CurrentGlucoseView.swift

@@ -24,20 +24,6 @@ struct CurrentGlucoseView: View {
 
     @Environment(\.colorScheme) var colorScheme
 
-    private var glucoseFormatter: NumberFormatter {
-        let formatter = NumberFormatter()
-        formatter.numberStyle = .decimal
-
-        if units == .mmolL {
-            formatter.maximumFractionDigits = 1
-            formatter.minimumFractionDigits = 1
-            formatter.roundingMode = .halfUp
-        } else {
-            formatter.maximumFractionDigits = 0
-        }
-        return formatter
-    }
-
     private var deltaFormatter: NumberFormatter {
         let formatter = NumberFormatter()
         formatter.numberStyle = .decimal
@@ -61,12 +47,6 @@ struct CurrentGlucoseView: View {
         return formatter
     }
 
-    private var dateFormatter: DateFormatter {
-        let formatter = DateFormatter()
-        formatter.timeStyle = .short
-        return formatter
-    }
-
     var body: some View {
         let triangleColor = Color(red: 0.262745098, green: 0.7333333333, blue: 0.9137254902)
 

+ 0 - 6
FreeAPS/Sources/Modules/Home/View/Header/LoopView.swift

@@ -16,12 +16,6 @@ struct LoopView: View {
 
     let determination: [OrefDetermination]
 
-    private var dateFormatter: DateFormatter {
-        let formatter = DateFormatter()
-        formatter.timeStyle = .short
-        return formatter
-    }
-
     private let rect = CGRect(x: 0, y: 0, width: 18, height: 18)
 
     var body: some View {

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

@@ -12,32 +12,12 @@ struct PumpView: View {
 
     @Environment(\.colorScheme) var colorScheme
 
-    private var reservoirFormatter: NumberFormatter {
-        let formatter = NumberFormatter()
-        formatter.numberStyle = .decimal
-        formatter.maximumFractionDigits = 0
-        return formatter
-    }
-
     private var batteryFormatter: NumberFormatter {
         let formatter = NumberFormatter()
         formatter.numberStyle = .percent
         return formatter
     }
 
-    private var numberFormatter: NumberFormatter {
-        let formatter = NumberFormatter()
-        formatter.numberStyle = .decimal
-        formatter.maximumFractionDigits = 2
-        return formatter
-    }
-
-    private var dateFormatter: DateFormatter {
-        let dateFormatter = DateFormatter()
-        dateFormatter.timeStyle = .short
-        return dateFormatter
-    }
-
     var body: some View {
         if let pumpStatusHighlightMessage = pumpStatusHighlightMessage { // display message instead pump info
             VStack(alignment: .center) {
@@ -71,7 +51,7 @@ struct PumpView: View {
                                 .font(.system(size: 15, design: .rounded))
                         } else {
                             Text(
-                                reservoirFormatter
+                                Formatter.integerFormatter
                                     .string(from: reservoir as NSNumber)! + NSLocalizedString(" U", comment: "Insulin unit")
                             )
                             .font(.system(size: 16, design: .rounded))

+ 26 - 57
FreeAPS/Sources/Modules/Home/View/HomeRootView.swift

@@ -4,14 +4,26 @@ import SwiftDate
 import SwiftUI
 import Swinject
 
+struct TimePicker: Identifiable {
+    let label: String
+    let number: String
+    var active: Bool
+    let hours: Int16
+    var id: String { label }
+}
+
 extension Home {
     struct RootView: BaseView {
         let resolver: Resolver
         let safeAreaSize: CGFloat = 0.08
 
+        @Environment(\.managedObjectContext) var moc
+        @Environment(\.colorScheme) var colorScheme
         @Environment(AppState.self) var appState
 
         @State var state = StateModel()
+
+        @State var settingsPath = NavigationPath()
         @State var isStatusPopupPresented = false
         @State var showCancelAlert = false
         @State var showCancelConfirmDialog = false
@@ -24,28 +36,16 @@ extension Home {
         @State private var statusTitle: String = ""
         @State var showPumpSelection: Bool = false
         @State var notificationsDisabled = false
-
-        struct Buttons: Identifiable {
-            let label: String
-            let number: String
-            var active: Bool
-            let hours: Int16
-            var id: String { label }
-        }
-
-        @State var timeButtons: [Buttons] = [
-            Buttons(label: "2 hours", number: "2", active: false, hours: 2),
-            Buttons(label: "4 hours", number: "4", active: false, hours: 4),
-            Buttons(label: "6 hours", number: "6", active: false, hours: 6),
-            Buttons(label: "12 hours", number: "12", active: false, hours: 12),
-            Buttons(label: "24 hours", number: "24", active: false, hours: 24)
+        @State var timeButtons: [TimePicker] = [
+            TimePicker(label: "2 hours", number: "2", active: false, hours: 2),
+            TimePicker(label: "4 hours", number: "4", active: false, hours: 4),
+            TimePicker(label: "6 hours", number: "6", active: false, hours: 6),
+            TimePicker(label: "12 hours", number: "12", active: false, hours: 12),
+            TimePicker(label: "24 hours", number: "24", active: false, hours: 24)
         ]
 
         let buttonFont = Font.custom("TimeButtonFont", size: 14)
 
-        @Environment(\.managedObjectContext) var moc
-        @Environment(\.colorScheme) var colorScheme
-
         @FetchRequest(fetchRequest: OverrideStored.fetch(
             NSPredicate.lastActiveOverride,
             ascending: false,
@@ -58,8 +58,6 @@ extension Home {
             fetchLimit: 1
         )) var latestTempTarget: FetchedResults<TempTargetStored>
 
-        // TODO: end todo
-
         var bolusProgressFormatter: NumberFormatter {
             let formatter = NumberFormatter()
             formatter.numberStyle = .decimal
@@ -71,13 +69,6 @@ extension Home {
             return formatter
         }
 
-        private var numberFormatter: NumberFormatter {
-            let formatter = NumberFormatter()
-            formatter.numberStyle = .decimal
-            formatter.maximumFractionDigits = 2
-            return formatter
-        }
-
         private var fetchedTargetFormatter: NumberFormatter {
             let formatter = NumberFormatter()
             formatter.numberStyle = .decimal
@@ -87,26 +78,6 @@ extension Home {
             return formatter
         }
 
-        private var targetFormatter: NumberFormatter {
-            let formatter = NumberFormatter()
-            formatter.numberStyle = .decimal
-            formatter.maximumFractionDigits = 1
-            return formatter
-        }
-
-        private var tirFormatter: NumberFormatter {
-            let formatter = NumberFormatter()
-            formatter.numberStyle = .decimal
-            formatter.maximumFractionDigits = 0
-            return formatter
-        }
-
-        private var dateFormatter: DateFormatter {
-            let dateFormatter = DateFormatter()
-            dateFormatter.timeStyle = .short
-            return dateFormatter
-        }
-
         private var historySFSymbol: String {
             if #available(iOS 17.0, *) {
                 return "book.pages"
@@ -161,7 +132,7 @@ extension Home {
             guard let lastTempBasal = state.tempBasals.last?.tempBasal, let tempRate = lastTempBasal.rate else {
                 return nil
             }
-            let rateString = numberFormatter.string(from: tempRate as NSNumber) ?? "0"
+            let rateString = Formatter.decimalFormatterWithTwoFractionDigits.string(from: tempRate as NSNumber) ?? "0"
             var manualBasalString = ""
 
             if let apsManager = state.apsManager, apsManager.isManualTempBasal {
@@ -370,7 +341,7 @@ extension Home {
                         Image(systemName: "arrow.right.circle")
                             .font(.system(size: 16, weight: .bold))
                         Text(
-                            numberFormatter.string(
+                            Formatter.decimalFormatterWithTwoFractionDigits.string(
                                 from: (
                                     state.units == .mmolL ? bg
                                         .asMmolL : bg
@@ -398,7 +369,7 @@ extension Home {
                         .foregroundColor(Color.insulin)
                     Text(
                         (
-                            numberFormatter
+                            Formatter.decimalFormatterWithTwoFractionDigits
                                 .string(from: (state.enactedAndNonEnactedDeterminations.first?.iob ?? 0) as NSNumber) ?? "0"
                         ) +
                             NSLocalizedString(" U", comment: "Insulin unit")
@@ -414,7 +385,7 @@ extension Home {
                         .foregroundColor(.loopYellow)
                     Text(
                         (
-                            numberFormatter.string(
+                            Formatter.decimalFormatterWithTwoFractionDigits.string(
                                 from: NSNumber(value: state.enactedAndNonEnactedDeterminations.first?.cob ?? 0)
                             ) ?? "0"
                         ) +
@@ -448,7 +419,7 @@ extension Home {
                     Text(
                         "TDD: " +
                             (
-                                numberFormatter
+                                Formatter.decimalFormatterWithTwoFractionDigits
                                     .string(from: (state.determinationsFromPersistence.first?.totalDailyDose ?? 0) as NSNumber) ??
                                     "0"
                             ) +
@@ -712,7 +683,7 @@ extension Home {
                 let bolusString =
                     (bolusProgressFormatter.string(from: bolusFraction as NSNumber) ?? "0")
                         + " of " +
-                        (numberFormatter.string(from: bolusTotal as NSNumber) ?? "0")
+                        (Formatter.decimalFormatterWithTwoFractionDigits.string(from: bolusTotal as NSNumber) ?? "0")
                         + NSLocalizedString(" U", comment: "Insulin unit")
 
                 ZStack {
@@ -1007,8 +978,6 @@ extension Home {
             .navigationBarTitle("Legend", displayMode: .inline)
         }
 
-        @State var settingsPath = NavigationPath()
-
         @ViewBuilder func tabBar() -> some View {
             ZStack(alignment: .bottom) {
                 TabView(selection: $selectedTab) {
@@ -1021,7 +990,7 @@ extension Home {
                         let carbsRequiredDecimal = Decimal(carbsRequired)
                         if carbsRequiredDecimal > state.settingsManager.settings.carbsRequiredThreshold {
                             let numberAsNSNumber = NSDecimalNumber(decimal: carbsRequiredDecimal)
-                            return (numberFormatter.string(from: numberAsNSNumber) ?? "") + " g"
+                            return (Formatter.decimalFormatterWithTwoFractionDigits.string(from: numberAsNSNumber) ?? "") + " g"
                         }
                         return nil
                     }()
@@ -1147,7 +1116,7 @@ extension Home {
                 }
 
                 if let errorMessage = state.errorMessage, let date = state.errorDate {
-                    Text(NSLocalizedString("Error at", comment: "") + " " + dateFormatter.string(from: date))
+                    Text(NSLocalizedString("Error at", comment: "") + " " + Formatter.dateFormatter.string(from: date))
                         .foregroundColor(.white)
                         .font(.headline)
                         .padding(.bottom, 4)