|
|
@@ -5,7 +5,7 @@ import Swinject
|
|
|
extension OverrideProfilesConfig {
|
|
|
struct RootView: BaseView {
|
|
|
let resolver: Resolver
|
|
|
-
|
|
|
+
|
|
|
@StateObject var state = StateModel()
|
|
|
@State private var isEditing = false
|
|
|
@State private var showAlert = false
|
|
|
@@ -14,24 +14,24 @@ extension OverrideProfilesConfig {
|
|
|
@State private var isEditSheetPresented: Bool = false
|
|
|
@State private var alertSring = ""
|
|
|
@State var isSheetPresented: Bool = false
|
|
|
-
|
|
|
+
|
|
|
@Environment(\.dismiss) var dismiss
|
|
|
@Environment(\.managedObjectContext) var moc
|
|
|
-
|
|
|
+
|
|
|
@FetchRequest(
|
|
|
entity: OverridePresets.entity(),
|
|
|
sortDescriptors: [NSSortDescriptor(key: "name", ascending: true)], predicate: NSPredicate(
|
|
|
format: "name != %@", "" as String
|
|
|
)
|
|
|
) var fetchedProfiles: FetchedResults<OverridePresets>
|
|
|
-
|
|
|
+
|
|
|
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
|
|
|
@@ -42,7 +42,7 @@ extension OverrideProfilesConfig {
|
|
|
formatter.roundingMode = .halfUp
|
|
|
return formatter
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
var presetPopover: some View {
|
|
|
Form {
|
|
|
nameSection(header: "Enter a name")
|
|
|
@@ -56,18 +56,17 @@ extension OverrideProfilesConfig {
|
|
|
state.profileName.isEmpty || fetchedProfiles
|
|
|
.contains(where: { $0.name == state.profileName })
|
|
|
)
|
|
|
-
|
|
|
+
|
|
|
Button("Cancel") {
|
|
|
isSheetPresented = false
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
var editPresetPopover: some View {
|
|
|
Form {
|
|
|
nameSection(header: "Keep or change name?")
|
|
|
- // settingsSection(header: "New settings to save")
|
|
|
settingsConfig(header: "Change settings")
|
|
|
Section {
|
|
|
Button("Save") {
|
|
|
@@ -76,14 +75,14 @@ extension OverrideProfilesConfig {
|
|
|
isEditSheetPresented = false
|
|
|
}
|
|
|
.disabled(state.profileName.isEmpty)
|
|
|
-
|
|
|
+
|
|
|
Button("Cancel") {
|
|
|
isEditSheetPresented = false
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
@ViewBuilder private func nameSection(header: String) -> some View {
|
|
|
Section {
|
|
|
TextField("Profile override name", text: $state.profileName)
|
|
|
@@ -91,7 +90,7 @@ extension OverrideProfilesConfig {
|
|
|
Text(header)
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
@ViewBuilder private func settingsConfig(header: String) -> some View {
|
|
|
Section {
|
|
|
VStack {
|
|
|
@@ -122,7 +121,7 @@ extension OverrideProfilesConfig {
|
|
|
Text("minutes").foregroundColor(.secondary)
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
HStack {
|
|
|
Toggle(isOn: $state.override_target) {
|
|
|
Text("Override Profile Target")
|
|
|
@@ -207,7 +206,7 @@ extension OverrideProfilesConfig {
|
|
|
Text(header)
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
@ViewBuilder private func settingsSection(header: String) -> some View {
|
|
|
Section(header: Text(header)) {
|
|
|
let percentString = Text("Override: \(Int(state.percentage))%")
|
|
|
@@ -223,7 +222,7 @@ extension OverrideProfilesConfig {
|
|
|
.smbMinutes != 0 ? Text("\(state.smbMinutes.formatted()) SMB Basal minutes") : Text("")
|
|
|
let maxMinutesUAMString = state
|
|
|
.uamMinutes != 0 ? Text("\(state.uamMinutes.formatted()) UAM Basal minutes") : Text("")
|
|
|
-
|
|
|
+
|
|
|
VStack(alignment: .leading, spacing: 2) {
|
|
|
percentString
|
|
|
if targetString != Text("") { targetString }
|
|
|
@@ -239,7 +238,7 @@ extension OverrideProfilesConfig {
|
|
|
.font(.caption)
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
var body: some View {
|
|
|
Form {
|
|
|
if state.presets.isNotEmpty {
|
|
|
@@ -253,10 +252,10 @@ extension OverrideProfilesConfig {
|
|
|
} label: {
|
|
|
Label("Delete", systemImage: "trash")
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
Button {
|
|
|
selectedPreset = preset
|
|
|
- state.profileName = preset.name ?? ""
|
|
|
+ state.populateSettings(from: preset)
|
|
|
isEditSheetPresented = true
|
|
|
} label: {
|
|
|
Label("Edit", systemImage: "square.and.pencil")
|
|
|
@@ -264,11 +263,11 @@ extension OverrideProfilesConfig {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- header: { Text("Activate profile override") }
|
|
|
- footer: { VStack(alignment: .leading) {
|
|
|
- Text("Swipe left on a profile to edit or delete it.")
|
|
|
- }
|
|
|
- }
|
|
|
+ header: { Text("Activate profile override") }
|
|
|
+ footer: { VStack(alignment: .leading) {
|
|
|
+ Text("Swipe left on a profile to edit or delete it.")
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
settingsConfig(header: "Insulin")
|
|
|
Section {
|
|
|
@@ -276,37 +275,37 @@ extension OverrideProfilesConfig {
|
|
|
Button("Start new Profile") {
|
|
|
showAlert.toggle()
|
|
|
alertSring = "\(state.percentage.formatted(.number)) %, " +
|
|
|
- (
|
|
|
- state.duration > 0 || !state
|
|
|
- ._indefinite ?
|
|
|
- (
|
|
|
- state
|
|
|
- .duration
|
|
|
- .formatted(.number.grouping(.never).rounded().precision(.fractionLength(0))) +
|
|
|
- " min."
|
|
|
- ) :
|
|
|
- NSLocalizedString(" infinite duration.", comment: "")
|
|
|
- ) +
|
|
|
- (
|
|
|
- (state.target == 0 || !state.override_target) ? "" :
|
|
|
- (" Target: " + state.target.formatted() + " " + state.units.rawValue + ".")
|
|
|
- )
|
|
|
- +
|
|
|
+ (
|
|
|
+ state.duration > 0 || !state
|
|
|
+ ._indefinite ?
|
|
|
(
|
|
|
state
|
|
|
- .smbIsOff ?
|
|
|
- NSLocalizedString(
|
|
|
- " SMBs are disabled either by schedule or during the entire duration.",
|
|
|
- comment: ""
|
|
|
- ) : ""
|
|
|
- )
|
|
|
- +
|
|
|
- "\n\n"
|
|
|
- +
|
|
|
+ .duration
|
|
|
+ .formatted(.number.grouping(.never).rounded().precision(.fractionLength(0))) +
|
|
|
+ " min."
|
|
|
+ ) :
|
|
|
+ NSLocalizedString(" infinite duration.", comment: "")
|
|
|
+ ) +
|
|
|
+ (
|
|
|
+ (state.target == 0 || !state.override_target) ? "" :
|
|
|
+ (" Target: " + state.target.formatted() + " " + state.units.rawValue + ".")
|
|
|
+ )
|
|
|
+ +
|
|
|
+ (
|
|
|
+ state
|
|
|
+ .smbIsOff ?
|
|
|
NSLocalizedString(
|
|
|
- "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile.",
|
|
|
+ " SMBs are disabled either by schedule or during the entire duration.",
|
|
|
comment: ""
|
|
|
- )
|
|
|
+ ) : ""
|
|
|
+ )
|
|
|
+ +
|
|
|
+ "\n\n"
|
|
|
+ +
|
|
|
+ NSLocalizedString(
|
|
|
+ "Starting this override will change your Profiles and/or your Target Glucose used for looping during the entire selected duration. Tapping ”Start Profile” will start your new profile or edit your current active profile.",
|
|
|
+ comment: ""
|
|
|
+ )
|
|
|
}
|
|
|
.disabled(unChanged())
|
|
|
.buttonStyle(BorderlessButtonStyle())
|
|
|
@@ -331,7 +330,7 @@ extension OverrideProfilesConfig {
|
|
|
Button {
|
|
|
isSheetPresented = true
|
|
|
}
|
|
|
- label: { Text("Save as Profile") }
|
|
|
+ label: { Text("Save as Profile") }
|
|
|
.tint(.orange)
|
|
|
.frame(maxWidth: .infinity, alignment: .trailing)
|
|
|
.buttonStyle(BorderlessButtonStyle())
|
|
|
@@ -343,12 +342,12 @@ extension OverrideProfilesConfig {
|
|
|
presetPopover
|
|
|
}
|
|
|
}
|
|
|
- footer: {
|
|
|
- Text(
|
|
|
- "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage."
|
|
|
- )
|
|
|
- }
|
|
|
-
|
|
|
+ footer: {
|
|
|
+ Text(
|
|
|
+ "Your profile basal insulin will be adjusted with the override percentage and your profile ISF and CR will be inversly adjusted with the percentage."
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
Button("Return to Normal") {
|
|
|
state.cancelProfile()
|
|
|
dismiss()
|
|
|
@@ -368,7 +367,7 @@ extension OverrideProfilesConfig {
|
|
|
.padding()
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
@ViewBuilder private func profilesView(for preset: OverridePresets) -> some View {
|
|
|
let target = state.units == .mmolL ? (((preset.target ?? 0) as NSDecimalNumber) as Decimal)
|
|
|
.asMmolL : (preset.target ?? 0) as Decimal
|
|
|
@@ -386,7 +385,7 @@ extension OverrideProfilesConfig {
|
|
|
let crString = preset.cr ? "CR" : ""
|
|
|
let dash = crString != "" ? "/" : ""
|
|
|
let isfAndCRstring = isfString + dash + crString
|
|
|
-
|
|
|
+
|
|
|
if name != "" {
|
|
|
HStack {
|
|
|
VStack {
|
|
|
@@ -422,17 +421,17 @@ extension OverrideProfilesConfig {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
private func unChanged() -> Bool {
|
|
|
let defaultProfile = state.percentage == 100 && !state.override_target && !state.advancedSettings
|
|
|
let noDurationSpecified = !state._indefinite && state.duration == 0
|
|
|
let targetZeroWithOverride = state.override_target && state.target == 0
|
|
|
let allSettingsDefault = state.percentage == 100 && !state.override_target && !state.smbIsOff && !state
|
|
|
.smbIsScheduledOff && state.smbMinutes == state.defaultSmbMinutes && state.uamMinutes == state.defaultUamMinutes
|
|
|
-
|
|
|
+
|
|
|
return defaultProfile || noDurationSpecified || targetZeroWithOverride || allSettingsDefault
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
private func removeProfile(at offsets: IndexSet) {
|
|
|
for index in offsets {
|
|
|
let language = fetchedProfiles[index]
|
|
|
@@ -446,3 +445,28 @@ extension OverrideProfilesConfig {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+extension OverrideProfilesConfig.StateModel {
|
|
|
+ func populateSettings(from preset: OverridePresets) {
|
|
|
+ profileName = preset.name ?? ""
|
|
|
+ percentage = preset.percentage
|
|
|
+ duration = (preset.duration ?? 0) as Decimal
|
|
|
+ _indefinite = preset.indefinite
|
|
|
+ override_target = preset.target != nil
|
|
|
+ if let targetValue = preset.target as Decimal? {
|
|
|
+ target = units == .mmolL ? targetValue.asMmolL : targetValue
|
|
|
+ } else {
|
|
|
+ target = 0
|
|
|
+ }
|
|
|
+ advancedSettings = preset.advancedSettings
|
|
|
+ smbIsOff = preset.smbIsOff
|
|
|
+ smbIsScheduledOff = preset.smbIsScheduledOff
|
|
|
+ isf = preset.isf
|
|
|
+ cr = preset.cr
|
|
|
+ smbMinutes = (preset.smbMinutes ?? 0) as Decimal
|
|
|
+ uamMinutes = (preset.uamMinutes ?? 0) as Decimal
|
|
|
+ isfAndCr = preset.isfAndCr
|
|
|
+ start = (preset.start ?? 0) as Decimal
|
|
|
+ end = (preset.end ?? 0) as Decimal
|
|
|
+ }
|
|
|
+}
|