Преглед изворни кода

Merge pull request #5 from polscm32/loadingbar

Loadingbar integration
Deniz Cengiz пре 2 година
родитељ
комит
30a78b87ed

+ 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
@@ -315,14 +317,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()
+                }
             }
         }
 
@@ -475,6 +476,9 @@ extension Bolus.StateModel: SuggestionObserver {
     func suggestionDidUpdate(_: Suggestion) {
         DispatchQueue.main.async {
             self.waitForSuggestion = false
+            if self.addButtonPressed {
+                self.hideModal()
+            }
         }
         setupInsulinRequired()
     }

+ 220 - 187
FreeAPS/Sources/Modules/Bolus/View/AlternativeBolusCalcRootView.swift

@@ -264,225 +264,258 @@ extension Bolus {
         }
 
         var body: some View {
-            Form {
-                // MARK: ADDED
-
-                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()
-                    }
+            ZStack(alignment: .center) {
+                Form {
+                    // MARK: ADDED
 
-                    // Summary when combining presets
-                    if state.waitersNotepad() != "" {
+                    Section {
                         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)
+                            Text("Carbs").fontWeight(.semibold)
+                            Spacer()
+                            DecimalTextField(
+                                "0",
+                                value: $state.carbs,
+                                formatter: formatter,
+                                autofocus: false,
+                                cleanInput: true
+                            )
+                            Text("g").foregroundColor(.secondary)
                         }
-                    }
 
-                    // 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)
+                        if state.useFPUconversion {
+                            proteinAndFat()
                         }
-                    }
-
-                    .popover(isPresented: $isPromptPresented) {
-                        presetPopover
-                    }
-
-                    HStack {
-                        Spacer()
-                        Button {
-                            isCalculating = true
-                            state.insulinCalculated = state.calculateInsulin()
 
-                            DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
-                                isCalculating = false
+                        // 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)
                             }
                         }
-                        label: {
-                            if !isCalculating {
-                                Text("Calculate")
+
+                        // Time
+                        HStack {
+                            Text("Time").foregroundStyle(Color.secondary)
+                            Spacer()
+                            if !pushed {
+                                Button {
+                                    pushed = true
+                                } label: { Text("Now") }.buttonStyle(.borderless).foregroundColor(.secondary)
+                                    .padding(.trailing, 5)
                             } else {
-                                ProgressView().progressViewStyle(CircularProgressViewStyle())
+                                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)
                             }
-                        }.disabled(empty)
-
-                        Spacer()
-                    }
-                } header: { Text("Carbs") }.listRowBackground(Color.chart)
+                        }
 
-                Section {
-                    mealPresets
-                }.listRowBackground(Color.chart)
+                        .popover(isPresented: $isPromptPresented) {
+                            presetPopover
+                        }
 
-                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 {
+                        HStack {
                             Spacer()
-                            Toggle(isOn: $state.useFattyMealCorrectionFactor) {
-                                Text("Fatty Meal")
-                            }
-                            .toggleStyle(CheckboxToggleStyle())
-                            .font(.footnote)
-                            .onChange(of: state.useFattyMealCorrectionFactor) { _ in
+                            Button {
+                                isCalculating = true
                                 state.insulinCalculated = state.calculateInsulin()
-                                if state.useFattyMealCorrectionFactor {
-                                    state.useSuperBolus = false
+
+                                DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
+                                    isCalculating = false
                                 }
                             }
-                        }
-                        if state.sweetMeals {
+                            label: {
+                                if !isCalculating {
+                                    Text("Calculate")
+                                } else {
+                                    ProgressView().progressViewStyle(CircularProgressViewStyle())
+                                }
+                            }.disabled(empty)
+
                             Spacer()
-                            Toggle(isOn: $state.useSuperBolus) {
-                                Text("Super Bolus")
+                        }
+                    } header: { Text("Carbs") }.listRowBackground(Color.chart)
+
+                    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")
+                                }
+                                .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.useSuperBolus) { _ in
-                                state.insulinCalculated = state.calculateInsulin()
-                                if state.useSuperBolus {
-                                    state.useFattyMealCorrectionFactor = 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
+                                    }
                                 }
                             }
                         }
-                    }
 
-                    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
+                        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
+                            }
                         }
-                    }
 
-                } header: { Text("Bolus") }.listRowBackground(Color.chart)
+                    } header: { Text("Bolus") }.listRowBackground(Color.chart)
 
-                if state.amount > 0 {
-                    Section {
-                        Button {
-                            Task {
-                                await state.add()
-                                state.hideModal()
-                                state.addCarbs()
+                    if state.amount > 0 {
+                        Section {
+                            Button {
+                                Task {
+                                    await state.add()
+                                    state.waitForSuggestion = true
+                                    state.addCarbs()
+                                    state.addButtonPressed = true
+                                }
                             }
-                        }
 
-                        label: { Text(exceededMaxBolus ? "Max Bolus exceeded!" : "Enact bolus") }
-                            .frame(maxWidth: .infinity, alignment: .center)
-                            .disabled(disabled)
-                            .listRowBackground(!disabled ? Color(.systemBlue) : Color(.systemGray4))
-                            .tint(.white)
-                    }
-                }
-                if state.amount <= 0 {
-                    Section {
-                        Button {
-                            state.hideModal()
-                            state.addCarbs()
-                        }
-                        label: { Text("Continue without bolus") }.frame(maxWidth: .infinity, alignment: .center)
-                    }.listRowBackground(Color.chart)
-                }
-            }.scrollContentBackground(.hidden).background(color)
-                .blur(radius: showInfo ? 3 : 0)
-                .navigationTitle("Treatments")
-                .navigationBarTitleDisplayMode(.large)
-                .toolbar(content: {
-                    ToolbarItem(placement: .topBarLeading) {
-                        Button {
-                            state.hideModal()
-                        } label: {
-                            Text("Close")
+                            label: { Text(exceededMaxBolus ? "Max Bolus exceeded!" : "Enact bolus") }
+                                .frame(maxWidth: .infinity, alignment: .center)
+                                .disabled(disabled)
+                                .listRowBackground(!disabled ? Color(.systemBlue) : Color(.systemGray4))
+                                .tint(.white)
                         }
                     }
-                })
-                .onAppear {
-                    configureView {
-                        state.insulinCalculated = state.calculateInsulin()
+                    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)
+                        }.listRowBackground(Color.chart)
                     }
-                }
+                }.blur(radius: state.waitForSuggestion ? 5 : 0)
 
-                .sheet(isPresented: $showInfo) {
-                    calculationsDetailView
-                        .presentationDetents(
-                            [.fraction(0.9), .large],
-                            selection: $calculatorDetent
-                        )
+                if state.waitForSuggestion {
+                    CustomProgressView(text: progressText)
+                }
+            }
+            .scrollContentBackground(.hidden)
+            .background(color)
+            .blur(radius: showInfo ? 3 : 0)
+            .navigationTitle("Treatments")
+            .navigationBarTitleDisplayMode(.large)
+            .toolbar(content: {
+                ToolbarItem(placement: .topBarLeading) {
+                    Button {
+                        state.hideModal()
+                    } label: {
+                        Text("Close")
+                    }
+                }
+            })
+            .onAppear {
+                configureView {
+                    state.insulinCalculated = state.calculateInsulin()
                 }
+            }
+            .onDisappear {
+                state.addButtonPressed = false
+            }
+
+            .sheet(isPresented: $showInfo) {
+                calculationsDetailView
+                    .presentationDetents(
+                        [.fraction(0.9), .large],
+                        selection: $calculatorDetent
+                    )
+            }
+        }
+
+        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 predictionChart: some View {

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

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

+ 58 - 48
FreeAPS/Sources/Modules/DataTable/View/DataTableRootView.swift

@@ -74,61 +74,68 @@ extension DataTable {
         }
 
         var body: some View {
-            VStack {
-                Picker("Mode", selection: $state.mode) {
-                    ForEach(
-                        Mode.allCases.filter({ state.historyLayout == .twoTabs ? $0 != .meals : true }).indexed(),
-                        id: \.1
-                    ) { index, item in
-                        if state.historyLayout == .threeTabs && item == .treatments {
-                            Text("Insulin")
-                                .tag(index)
-                        } else {
-                            Text(item.name)
-                                .tag(index)
+            ZStack(alignment: .center) {
+                VStack {
+                    Picker("Mode", selection: $state.mode) {
+                        ForEach(
+                            Mode.allCases.filter({ state.historyLayout == .twoTabs ? $0 != .meals : true }).indexed(),
+                            id: \.1
+                        ) { index, item in
+                            if state.historyLayout == .threeTabs && item == .treatments {
+                                Text("Insulin")
+                                    .tag(index)
+                            } else {
+                                Text(item.name)
+                                    .tag(index)
+                            }
                         }
                     }
-                }
-                .pickerStyle(SegmentedPickerStyle())
-                .padding(.horizontal)
+                    .pickerStyle(SegmentedPickerStyle())
+                    .padding(.horizontal)
 
-                Form {
-                    switch state.mode {
-                    case .treatments: treatmentsList
-                    case .glucose: glucoseList
-                    case .meals: state.historyLayout == .threeTabs ? AnyView(mealsList) : AnyView(EmptyView())
-                    }
-                }.scrollContentBackground(.hidden)
-                    .background(color)
-            }.background(color)
-                .onAppear(perform: configureView)
-                .navigationTitle("History")
-                .navigationBarTitleDisplayMode(.large)
-                .toolbar {
-                    ToolbarItem(placement: .topBarTrailing) {
+                    Form {
                         switch state.mode {
-                        case .treatments: addButton({
-                                state.showExternalInsulin = true
-                                state.externalInsulinDate = Date()
-                            })
-                        case .meals: EmptyView()
-                        case .glucose: addButton({
-                                showManualGlucose = true
-                                state.manualGlucose = 0
-                            })
+                        case .treatments: treatmentsList
+                        case .glucose: glucoseList
+                        case .meals: state.historyLayout == .threeTabs ? AnyView(mealsList) : AnyView(EmptyView())
                         }
-                    }
-                }
-                .sheet(isPresented: $showManualGlucose) {
-                    addGlucoseView()
+                    }.scrollContentBackground(.hidden)
+                        .background(color)
+                }.blur(radius: state.waitForSuggestion ? 8 : 0)
+
+                if state.waitForSuggestion {
+                    CustomProgressView(text: "Updating History...")
                 }
-                .sheet(
-                    isPresented: $state.showExternalInsulin,
-                    onDismiss: { if isAmountUnconfirmed { state.externalInsulinAmount = 0
-                        state.externalInsulinDate = Date() } }
-                ) {
-                    addExternalInsulinView()
+            }
+            .background(color)
+            .onAppear(perform: configureView)
+            .navigationTitle("History")
+            .navigationBarTitleDisplayMode(.large)
+            .toolbar {
+                ToolbarItem(placement: .topBarTrailing) {
+                    switch state.mode {
+                    case .treatments: addButton({
+                            state.showExternalInsulin = true
+                            state.externalInsulinDate = Date()
+                        })
+                    case .meals: EmptyView()
+                    case .glucose: addButton({
+                            showManualGlucose = true
+                            state.manualGlucose = 0
+                        })
+                    }
                 }
+            }
+            .sheet(isPresented: $showManualGlucose) {
+                addGlucoseView()
+            }
+            .sheet(
+                isPresented: $state.showExternalInsulin,
+                onDismiss: { if isAmountUnconfirmed { state.externalInsulinAmount = 0
+                    state.externalInsulinDate = Date() } }
+            ) {
+                addExternalInsulinView()
+            }
         }
 
         @ViewBuilder func addButton(_ action: @escaping () -> Void) -> some View {
@@ -323,10 +330,12 @@ extension DataTable {
 
                     if state.historyLayout == .twoTabs, treatmentToDelete.type == .carbs || treatmentToDelete.type == .fpus {
                         state.deleteCarbs(treatmentToDelete)
+                        state.waitForSuggestion = true
                     } else {
                         Task {
                             do {
                                 await state.deleteInsulin(treatmentToDelete)
+                                state.waitForSuggestion = true
                             }
                         }
                     }
@@ -386,6 +395,7 @@ extension DataTable {
                     }
 
                     state.deleteCarbs(treatmentToDelete)
+                    state.waitForSuggestion = true
                 }
             } message: {
                 Text("\n" + NSLocalizedString(alertMessage, comment: ""))

+ 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 {