فهرست منبع

merge branch 'loadingbar integration' into 'externalInsulin'

polscm32 2 سال پیش
والد
کامیت
2902a6bf5e

+ 11 - 7
FreeAPS/Sources/Modules/Bolus/BolusStateModel.swift

@@ -36,6 +36,8 @@ extension Bolus {
         @Published var waitForSuggestion: Bool = false
         @Published var carbRatio: Decimal = 0
 
+        @Published var addButtonPressed: Bool = false
+
         var waitForSuggestionInitial: Bool = false
 
         // added for bolus calculator
@@ -316,14 +318,13 @@ extension Bolus {
             )]
             carbsStorage.storeCarbs(carbsToStore)
 
-            if skipBolus {
-                apsManager.determineBasalSync()
-                showModal(for: nil)
-            } else if carbs > 0 {
+            if carbs > 0 {
                 saveToCoreData(carbsToStore)
-                apsManager.determineBasalSync()
-            } else {
-                hideModal()
+
+                // only perform determine basal sync if the user doesn't use the pump bolus, otherwise the enact bolus func in the APSManger does a sync
+                if amount <= 0 {
+                    apsManager.determineBasalSync()
+                }
             }
         }
 
@@ -524,6 +525,9 @@ extension Bolus.StateModel: SuggestionObserver {
     func suggestionDidUpdate(_: Suggestion) {
         DispatchQueue.main.async {
             self.waitForSuggestion = false
+            if self.addButtonPressed {
+                self.hideModal()
+            }
         }
         setupInsulinRequired()
     }

+ 229 - 196
FreeAPS/Sources/Modules/Bolus/View/AlternativeBolusCalcRootView.swift

@@ -264,240 +264,258 @@ extension Bolus {
         }
 
         var body: some View {
-            VStack {
-                Form {
-                    Section {
-                        HStack {
-                            Text("Carbs").fontWeight(.semibold)
-                            Spacer()
-                            DecimalTextField(
-                                "0",
-                                value: $state.carbs,
-                                formatter: formatter,
-                                autofocus: false,
-                                cleanInput: true
-                            )
-                            Text("g").foregroundColor(.secondary)
-                        }
+            ZStack(alignment: .center) {
+                VStack {
+                    Form {
+                        Section {
+                            HStack {
+                                Text("Carbs").fontWeight(.semibold)
+                                Spacer()
+                                DecimalTextField(
+                                    "0",
+                                    value: $state.carbs,
+                                    formatter: formatter,
+                                    autofocus: false,
+                                    cleanInput: true
+                                )
+                                Text("g").foregroundColor(.secondary)
+                            }
 
-                        if state.useFPUconversion {
-                            proteinAndFat()
-                        }
+                            if state.useFPUconversion {
+                                proteinAndFat()
+                            }
 
-                        // Summary when combining presets
-                        if state.waitersNotepad() != "" {
-                            HStack {
-                                Text("Total")
-                                let test = state.waitersNotepad().components(separatedBy: ", ").removeDublicates()
-                                HStack(spacing: 0) {
-                                    ForEach(test, id: \.self) {
-                                        Text($0).foregroundStyle(Color.randomGreen()).font(.footnote)
-                                        Text($0 == test[test.count - 1] ? "" : ", ")
-                                    }
-                                }.frame(maxWidth: .infinity, alignment: .trailing)
+                            // Summary when combining presets
+                            if state.waitersNotepad() != "" {
+                                HStack {
+                                    Text("Total")
+                                    let test = state.waitersNotepad().components(separatedBy: ", ").removeDublicates()
+                                    HStack(spacing: 0) {
+                                        ForEach(test, id: \.self) {
+                                            Text($0).foregroundStyle(Color.randomGreen()).font(.footnote)
+                                            Text($0 == test[test.count - 1] ? "" : ", ")
+                                        }
+                                    }.frame(maxWidth: .infinity, alignment: .trailing)
+                                }
                             }
-                        }
 
-                        // Time
-                        HStack {
-                            Text("Time").foregroundStyle(Color.secondary)
-                            Spacer()
-                            if !pushed {
-                                Button {
-                                    pushed = true
-                                } label: { Text("Now") }.buttonStyle(.borderless).foregroundColor(.secondary)
-                                    .padding(.trailing, 5)
-                            } else {
-                                Button { state.date = state.date.addingTimeInterval(-15.minutes.timeInterval) }
-                                label: { Image(systemName: "minus.circle") }.tint(.blue).buttonStyle(.borderless)
-                                DatePicker(
-                                    "Time",
-                                    selection: $state.date,
-                                    displayedComponents: [.hourAndMinute]
-                                ).controlSize(.mini)
-                                    .labelsHidden()
-                                Button {
-                                    state.date = state.date.addingTimeInterval(15.minutes.timeInterval)
+                            // Time
+                            HStack {
+                                Text("Time").foregroundStyle(Color.secondary)
+                                Spacer()
+                                if !pushed {
+                                    Button {
+                                        pushed = true
+                                    } label: { Text("Now") }.buttonStyle(.borderless).foregroundColor(.secondary)
+                                        .padding(.trailing, 5)
+                                } else {
+                                    Button { state.date = state.date.addingTimeInterval(-15.minutes.timeInterval) }
+                                    label: { Image(systemName: "minus.circle") }.tint(.blue).buttonStyle(.borderless)
+                                    DatePicker(
+                                        "Time",
+                                        selection: $state.date,
+                                        displayedComponents: [.hourAndMinute]
+                                    ).controlSize(.mini)
+                                        .labelsHidden()
+                                    Button {
+                                        state.date = state.date.addingTimeInterval(15.minutes.timeInterval)
+                                    }
+                                    label: { Image(systemName: "plus.circle") }.tint(.blue).buttonStyle(.borderless)
                                 }
-                                label: { Image(systemName: "plus.circle") }.tint(.blue).buttonStyle(.borderless)
                             }
-                        }
 
-                        .popover(isPresented: $isPromptPresented) {
-                            presetPopover
-                        }
+                            .popover(isPresented: $isPromptPresented) {
+                                presetPopover
+                            }
 
-                        HStack {
-                            Spacer()
-                            Button {
-                                isCalculating = true
-                                state.insulinCalculated = state.calculateInsulin()
+                            HStack {
+                                Spacer()
+                                Button {
+                                    isCalculating = true
+                                    state.insulinCalculated = state.calculateInsulin()
 
-                                DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
-                                    isCalculating = false
+                                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
+                                        isCalculating = false
+                                    }
                                 }
+                                label: {
+                                    if !isCalculating {
+                                        Text("Calculate")
+                                    } else {
+                                        ProgressView().progressViewStyle(CircularProgressViewStyle())
+                                    }
+                                }.disabled(empty)
+
+                                Spacer()
                             }
-                            label: {
-                                if !isCalculating {
-                                    Text("Calculate")
-                                } else {
-                                    ProgressView().progressViewStyle(CircularProgressViewStyle())
-                                }
-                            }.disabled(empty)
+                        }
 
-                            Spacer()
+                        if state.displayPresets {
+                            Section {
+                                mealPresets
+                            }.listRowBackground(Color.chart)
                         }
-                    }
 
-                    if state.displayPresets {
                         Section {
-                            mealPresets
-                        }.listRowBackground(Color.chart)
-                    }
-
-                    Section {
-                        HStack {
-                            Button(action: {
-                                showInfo.toggle()
-                            }, label: {
-                                Image(systemName: "info.circle")
-                                Text("Calculations")
-                            })
-                                .foregroundStyle(.blue)
-                                .font(.footnote)
-                                .buttonStyle(PlainButtonStyle())
-                                .frame(maxWidth: .infinity, alignment: .leading)
-
-                            if state.fattyMeals {
-                                Spacer()
-                                Toggle(isOn: $state.useFattyMealCorrectionFactor) {
-                                    Text("Fatty Meal")
+                            HStack {
+                                Button(action: {
+                                    showInfo.toggle()
+                                }, label: {
+                                    Image(systemName: "info.circle")
+                                    Text("Calculations")
+                                })
+                                    .foregroundStyle(.blue)
+                                    .font(.footnote)
+                                    .buttonStyle(PlainButtonStyle())
+                                    .frame(maxWidth: .infinity, alignment: .leading)
+
+                                if state.fattyMeals {
+                                    Spacer()
+                                    Toggle(isOn: $state.useFattyMealCorrectionFactor) {
+                                        Text("Fatty Meal")
+                                    }
+                                    .toggleStyle(CheckboxToggleStyle())
+                                    .font(.footnote)
+                                    .onChange(of: state.useFattyMealCorrectionFactor) { _ in
+                                        state.insulinCalculated = state.calculateInsulin()
+                                        if state.useFattyMealCorrectionFactor {
+                                            state.useSuperBolus = false
+                                        }
+                                    }
                                 }
-                                .toggleStyle(CheckboxToggleStyle())
-                                .font(.footnote)
-                                .onChange(of: state.useFattyMealCorrectionFactor) { _ in
-                                    state.insulinCalculated = state.calculateInsulin()
-                                    if state.useFattyMealCorrectionFactor {
-                                        state.useSuperBolus = false
+                                if state.sweetMeals {
+                                    Spacer()
+                                    Toggle(isOn: $state.useSuperBolus) {
+                                        Text("Super Bolus")
+                                    }
+                                    .toggleStyle(CheckboxToggleStyle())
+                                    .font(.footnote)
+                                    .onChange(of: state.useSuperBolus) { _ in
+                                        state.insulinCalculated = state.calculateInsulin()
+                                        if state.useSuperBolus {
+                                            state.useFattyMealCorrectionFactor = false
+                                        }
                                     }
                                 }
                             }
-                            if state.sweetMeals {
+
+                            HStack {
+                                Text("Recommended Bolus")
                                 Spacer()
-                                Toggle(isOn: $state.useSuperBolus) {
-                                    Text("Super Bolus")
-                                }
-                                .toggleStyle(CheckboxToggleStyle())
-                                .font(.footnote)
-                                .onChange(of: state.useSuperBolus) { _ in
-                                    state.insulinCalculated = state.calculateInsulin()
-                                    if state.useSuperBolus {
-                                        state.useFattyMealCorrectionFactor = false
-                                    }
+                                Text(
+                                    formatter
+                                        .string(from: Double(state.insulinCalculated) as NSNumber) ?? ""
+                                )
+                                Text(
+                                    NSLocalizedString(
+                                        " U",
+                                        comment: "Unit in number of units delivered (keep the space character!)"
+                                    )
+                                ).foregroundColor(.secondary)
+                            }.contentShape(Rectangle())
+                                .onTapGesture { state.amount = state.insulinCalculated }
+
+                            HStack {
+                                Text("Bolus")
+                                Spacer()
+                                DecimalTextField(
+                                    "0",
+                                    value: $state.amount,
+                                    formatter: formatter,
+                                    autofocus: false,
+                                    cleanInput: true
+                                )
+                                Text(exceededMaxBolus ? "😵" : " U").foregroundColor(.secondary)
+                            }
+                            .onChange(of: state.amount) { newValue in
+                                if newValue > state.maxBolus {
+                                    exceededMaxBolus = true
+                                } else {
+                                    exceededMaxBolus = false
                                 }
                             }
                         }
 
-                        HStack {
-                            Text("Recommended Bolus")
-                            Spacer()
-                            Text(
-                                formatter
-                                    .string(from: Double(state.insulinCalculated) as NSNumber) ?? ""
-                            )
-                            Text(
-                                NSLocalizedString(" U", comment: "Unit in number of units delivered (keep the space character!)")
-                            ).foregroundColor(.secondary)
-                        }.contentShape(Rectangle())
-                            .onTapGesture { state.amount = state.insulinCalculated }
-
-                        HStack {
-                            Text("Bolus")
-                            Spacer()
-                            DecimalTextField(
-                                "0",
-                                value: $state.amount,
-                                formatter: formatter,
-                                autofocus: false,
-                                cleanInput: true
-                            )
-                            Text(exceededMaxBolus ? "😵" : " U").foregroundColor(.secondary)
-                        }
-                        .onChange(of: state.amount) { newValue in
-                            if newValue > state.maxBolus {
-                                exceededMaxBolus = true
-                            } else {
-                                exceededMaxBolus = false
+                        if state.amount > 0 {
+                            Section {
+                                HStack {
+                                    Text("External insulin")
+                                    Spacer()
+                                    Toggle("", isOn: $state.externalInsulin).toggleStyle(Checkbox())
+                                }
                             }
                         }
                     }
-
+                }.safeAreaInset(edge: .bottom, spacing: 0) {
                     if state.amount > 0 {
                         Section {
-                            HStack {
-                                Text("External insulin")
-                                Spacer()
-                                Toggle("", isOn: $state.externalInsulin).toggleStyle(Checkbox())
-                            }
-                        }
-                    }
-                }
-            }.safeAreaInset(edge: .bottom, spacing: 0) {
-                if state.amount > 0 {
-                    Section {
-                        Button {
-                            if !state.externalInsulin {
-                                Task {
-                                    await state.add()
-                                    state.hideModal()
-                                    state.addCarbs()
-                                }
-                            } else {
-                                Task {
-                                    do {
-                                        await state.addExternalInsulin()
-                                        state.hideModal()
+                            Button {
+                                if !state.externalInsulin {
+                                    Task {
+                                        state.waitForSuggestion = true
+                                        await state.add()
                                         state.addCarbs()
+                                        state.addButtonPressed = true
+                                    }
+                                } else {
+                                    Task {
+                                        do {
+                                            state.waitForSuggestion = true
+                                            await state.addExternalInsulin()
+                                            state.addCarbs()
+                                            state.addButtonPressed = true
+                                        }
                                     }
                                 }
                             }
-                        }
 
-                        label: {
-                            if !state.externalInsulin {
-                                Text(exceededMaxBolus ? "Max Bolus exceeded!" : "Enact bolus")
-                            } else {
-                                Text("Log external insulin")
+                            label: {
+                                if !state.externalInsulin {
+                                    Text(exceededMaxBolus ? "Max Bolus exceeded!" : "Enact bolus")
+                                } else {
+                                    Text("Log external insulin")
+                                }
                             }
-                        }
-                        .frame(maxWidth: .infinity, alignment: .center)
-                        .frame(minHeight: 50)
-                        .disabled(state.externalInsulin ? limitManualBolus : limitPumpBolus)
-                        .background(logExternalInsulinBackground)
-                        .clipShape(RoundedRectangle(cornerRadius: 8))
-                        .tint(logExternalInsulinForeground)
-                        .padding()
-                    } header: {
-                        if state.amount > state.maxBolus
-                        {
-                            Text("⚠️ Warning! The entered insulin amount is greater than your Max Bolus setting!")
-                        }
-                    }
-                }
-                if state.amount <= 0 {
-                    Section {
-                        Button {
-                            state.hideModal()
-                            state.addCarbs()
-                        }
-                        label: { Text("Continue without bolus") }
                             .frame(maxWidth: .infinity, alignment: .center)
                             .frame(minHeight: 50)
-                            .background(Color(.systemBlue))
+                            .disabled(state.externalInsulin ? limitManualBolus : limitPumpBolus)
+                            .background(logExternalInsulinBackground)
                             .clipShape(RoundedRectangle(cornerRadius: 8))
-                            .tint(.white)
+                            .tint(logExternalInsulinForeground)
                             .padding()
-                    }.listRowBackground(Color.chart)
+                        } header: {
+                            if state.amount > state.maxBolus
+                            {
+                                Text("⚠️ Warning! The entered insulin amount is greater than your Max Bolus setting!")
+                            }
+                        }
+                    }
+                    if state.amount <= 0 {
+                        Section {
+                            Button {
+                                // show loading bar only when carbs are actually added
+                                if state.carbs > 0 {
+                                    state.waitForSuggestion = true
+                                } else {
+                                    // otherwise close view, because hideModal() is otherwise only excecuted after a suggestion update, see StateModal
+                                    state.hideModal()
+                                }
+                                state.addButtonPressed = true
+                                state.addCarbs()
+                            }
+                            label: { Text("Continue without bolus") }
+                                .frame(maxWidth: .infinity, alignment: .center)
+                                .frame(minHeight: 50)
+                                .background(Color(.systemBlue))
+                                .clipShape(RoundedRectangle(cornerRadius: 8))
+                                .tint(.white)
+                                .padding()
+                        }.listRowBackground(Color.chart)
+                    }
+                }.blur(radius: state.waitForSuggestion ? 5 : 0)
+
+                if state.waitForSuggestion {
+                    CustomProgressView(text: progressText)
                 }
             }
             .scrollContentBackground(.hidden).background(color)
@@ -518,7 +536,9 @@ extension Bolus {
                     state.insulinCalculated = state.calculateInsulin()
                 }
             }
-
+            .onDisappear {
+                state.addButtonPressed = false
+            }
             .sheet(isPresented: $showInfo) {
                 calculationsDetailView
                     .presentationDetents(
@@ -528,6 +548,19 @@ extension Bolus {
             }
         }
 
+        var progressText: String {
+            switch (state.amount > 0, state.carbs > 0) {
+            case (true, true):
+                return "Updating COB and IOB..."
+            case (false, true):
+                return "Updating COB..."
+            case (true, false):
+                return "Updating IOB..."
+            default:
+                return "Updating Treatments..."
+            }
+        }
+
         var calcSettingsFirstRow: some View {
             GridRow {
                 Group {

+ 2 - 0
FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift

@@ -161,6 +161,7 @@ extension DataTable {
 
         func deleteCarbs(_ treatment: Treatment) {
             provider.deleteCarbs(treatment)
+            apsManager.determineBasalSync()
         }
 
         func deleteInsulin(_ treatment: Treatment) async {
@@ -168,6 +169,7 @@ extension DataTable {
                 let authenticated = try await unlockmanager.unlock()
                 if authenticated {
                     provider.deleteInsulin(treatment)
+                    apsManager.determineBasalSync()
                 } else {
                     print("authentication failed")
                 }

+ 6 - 0
FreeAPS/Sources/Modules/Home/HomeStateModel.swift

@@ -72,6 +72,8 @@ extension Home {
 
         @Published var selectedTab: Int = 0
 
+        @Published var waitForSuggestion: Bool = false
+
         let coredataContext = CoreDataStack.shared.persistentContainer.viewContext
 
         override func subscribe() {
@@ -215,6 +217,9 @@ extension Home {
 
         func cancelBolus() {
             apsManager.cancelBolus()
+
+            // perform determine basal sync, otherwise you have could end up with too much iob when opening the calculator again
+            apsManager.determineBasalSync()
         }
 
         func cancelProfile() {
@@ -438,6 +443,7 @@ extension Home.StateModel:
         self.suggestion = suggestion
         carbsRequired = suggestion.carbsReq
         setStatusTitle()
+        waitForSuggestion = false
     }
 
     func settingsDidChange(_ settings: FreeAPSSettings) {

+ 9 - 74
FreeAPS/Sources/Modules/Home/View/HomeRootView.swift

@@ -690,6 +690,7 @@ extension Home {
                     Spacer()
 
                     Button {
+                        state.waitForSuggestion = true
                         state.cancelBolus()
                     } label: {
                         Image(systemName: "xmark.app")
@@ -787,77 +788,6 @@ extension Home {
             }
         }
 
-//
-//        @ViewBuilder func tabBarButton(index: Int, systemName: String, label: String) -> some View {
-//            Button(action: {
-//                selectedTab = index
-//            }) {
-//                ZStack(alignment: .bottom, content: {
-//                    VStack {
-//                        Image(systemName: systemName)
-//                            .font(.system(size: 22))
-//                            .foregroundStyle(selectedTab == index ? Color(.label) : Color.gray)
-//                        Text(label)
-//                            .font(.caption2)
-//                            .foregroundStyle(selectedTab == index ? Color(.label) : Color.gray)
-//                            .padding(.top, 1)
-//                    }
-//                    if selectedTab == index {
-//                        Capsule()
-//                            .frame(width: 25, height: 5)
-//                            .foregroundStyle(Color(.label))
-//                            .offset(y: 10)
-//                    }
-//                })
-//            }
-//        }
-//
-//        @ViewBuilder func customTabBar() -> some View {
-//            VStack {
-//                ZStack {
-//                    switch selectedTab {
-//                    case 0:
-//                        mainView()
-//                    case 1:
-//                        NavigationStack { DataTable.RootView(resolver: resolver) }
-//                    case 2:
-//                        NavigationStack { OverrideProfilesConfig.RootView(resolver: resolver) }
-//                    case 3:
-//                        NavigationStack { Settings.RootView(resolver: resolver) }
-//                    default:
-//                        mainView()
-//                    }
-//                }
-//                HStack {
-//                    tabBarButton(
-//                        index: 0,
-//                        systemName: selectedTab == 0 ? "house.fill" : "house",
-//                        label: "Home"
-//                    )
-//                    Spacer()
-//                    tabBarButton(index: 1, systemName: historySFSymbol, label: "History")
-//                    Spacer()
-//                    Button(action: {
-//                        state.showModal(for: .bolus(waitForSuggestion: false, fetch: false))
-//                    }) {
-//                        Image(systemName: "plus.circle.fill")
-//                            .font(.system(size: 45))
-//                            .foregroundStyle(Color.tabBar)
-//                            .padding(.bottom, 2)
-//                    }
-//                    Spacer()
-//                    tabBarButton(
-//                        index: 2,
-//                        systemName: selectedTab == 2 ? "person.fill" : "person",
-//                        label: "Profile"
-//                    )
-//                    Spacer()
-//                    tabBarButton(index: 3, systemName: "text.justify", label: "Menu")
-//                }
-//                .padding(.horizontal, 20)
-//            }.blur(radius: isMenuPresented ? 5 : 0)
-//        }
-
         @ViewBuilder func tabBar() -> some View {
             ZStack(alignment: .bottom) {
                 TabView {
@@ -896,12 +826,17 @@ extension Home {
                             .padding(.horizontal, 20)
                     }
                 )
-            }.ignoresSafeArea(.keyboard, edges: .bottom)
+            }.ignoresSafeArea(.keyboard, edges: .bottom).blur(radius: state.waitForSuggestion ? 8 : 0)
         }
 
         var body: some View {
-            // customTabBar()
-            tabBar()
+            ZStack(alignment: .center) {
+                tabBar()
+
+                if state.waitForSuggestion {
+                    CustomProgressView(text: "Updating IOB...")
+                }
+            }
         }
 
         private var popup: some View {