Procházet zdrojové kódy

Tabbar rework

	* UI changes for reworked tabbar

	* refactoring

	* fix alert for profiles popping up even when no profile is selected

alignment

	* alignment
polscm32 před 2 roky
rodič
revize
88e4611376

+ 0 - 2
FreeAPS/Sources/Modules/Bolus/View/AlternativeBolusCalcRootView.swift

@@ -26,8 +26,6 @@ extension Bolus {
 
         @FocusState private var isFocused: Bool
 
-        @ObservedObject var appState: AppState
-
         @Environment(\.managedObjectContext) var moc
 
         private enum Config {

+ 2 - 5
FreeAPS/Sources/Modules/Bolus/View/BolusRootView.swift

@@ -9,7 +9,6 @@ extension Bolus {
         let editMode: Bool
         let override: Bool
         @StateObject var state = StateModel()
-        @ObservedObject var appState = AppState()
 
         var body: some View {
             if state.useCalc {
@@ -20,8 +19,7 @@ extension Bolus {
                     fetch: fetch,
                     editMode: editMode,
                     override: override,
-                    state: state,
-                    appState: appState
+                    state: state
                 )
             } else {
                 // show iAPS standard bolus calc
@@ -29,8 +27,7 @@ extension Bolus {
                     resolver: resolver,
                     waitForSuggestion: waitForSuggestion,
                     fetch: fetch,
-                    state: state,
-                    appState: appState
+                    state: state
                 )
             }
         }

+ 0 - 3
FreeAPS/Sources/Modules/Bolus/View/DefaultBolusCalcRootView.swift

@@ -14,7 +14,6 @@ extension Bolus {
         @State private var presentInfo = false
         @State private var displayError = false
         @State private var keepForNextWiew: Bool = false
-        @ObservedObject var appState: AppState
 
         @Environment(\.colorScheme) var colorScheme
 
@@ -121,7 +120,6 @@ extension Bolus {
                             keepForNextWiew = true
                             state.add()
                             state.hideModal()
-//                            appState.currentTab = .home
                         }
                         label: { Text(!(state.amount > state.maxBolus) ? "Enact bolus" : "Max Bolus exceeded!") }
                             .frame(maxWidth: .infinity, alignment: .center)
@@ -136,7 +134,6 @@ extension Bolus {
                         Button {
                             keepForNextWiew = true
                             state.hideModal()
-//                            appState.currentTab = .home
                         }
                         label: { Text("Continue without bolus") }.frame(maxWidth: .infinity, alignment: .center)
                     }.listRowBackground(Color.chart)

+ 12 - 23
FreeAPS/Sources/Modules/Home/View/Chart/MainChartView.swift

@@ -33,7 +33,7 @@ private struct ChartBolus: Hashable {
     let amount: Decimal
     let timestamp: Date
     let nearestGlucose: BloodGlucose
-    let yPosition: Int
+    let yPosition: Decimal
 }
 
 private struct ChartTempTarget: Hashable {
@@ -125,6 +125,14 @@ struct MainChartView: View {
         units == .mgdL ? 400 : 22.2
     }
 
+    private var defaultBolusPosition: Int {
+        units == .mgdL ? 120 : 7
+    }
+
+    private var bolusOffset: Decimal {
+        units == .mgdL ? 30 : 1.66
+    }
+
     var body: some View {
         VStack {
             ScrollViewReader { scroller in
@@ -370,7 +378,7 @@ extension MainChartView {
                     calculatePredictions()
                 }
                 .frame(
-                    minHeight: UIScreen.main.bounds.height / 3.1
+                    minHeight: UIScreen.main.bounds.height / 3.3
                 )
                 .frame(width: fullWidth(viewWidth: screenSize.width))
                 // .chartYScale(domain: minValue ... maxValue)
@@ -502,7 +510,7 @@ extension MainChartView {
                 calculateTempBasals()
             }
             .frame(
-                minHeight: UIScreen.main.bounds.height / 9.9
+                minHeight: UIScreen.main.bounds.height / 9.8
             )
             .frame(width: fullWidth(viewWidth: screenSize.width))
             .rotationEffect(.degrees(180))
@@ -634,8 +642,7 @@ extension MainChartView {
         var calculatedBoluses: [ChartBolus] = []
         boluses.forEach { bolus in
             let bg = timeToNearestGlucose(time: bolus.timestamp.timeIntervalSince1970)
-            let offset = (bg.sgv ?? 120) + 30
-            let yPosition = offset * (units == .mmolL ? Int(0.0555) : 1)
+            let yPosition = (Decimal(bg.sgv ?? defaultBolusPosition) * conversionFactor) + bolusOffset
             calculatedBoluses
                 .append(ChartBolus(
                     amount: bolus.amount ?? 0,
@@ -907,24 +914,6 @@ extension MainChartView {
 //        }.min()
 //    }
 
-    /*   private func generateYAxisValues(maxYLabel: Int) -> [Int] {
-         var yAxisValues = [50, 100, 150]
-
-         if maxYLabel > 170, maxYLabel < 200 {
-             yAxisValues.append(maxYLabel)
-         } else if maxYLabel > 200, maxYLabel < 250 {
-             yAxisValues += [200, maxYLabel]
-         } else if maxYLabel > 250, maxYLabel < 350 {
-             yAxisValues += [200, 250, maxYLabel]
-         } else if maxYLabel > 350 {
-             yAxisValues += [200, 250, 300, maxYLabel]
-         } else if maxYLabel == 400 {
-             yAxisValues += [200, 250, 300, 350, 400]
-         }
-
-         return yAxisValues
-     } */
-
     private func calculateBasals() {
         let dayAgoTime = Date().addingTimeInterval(-1.days.timeInterval).timeIntervalSince1970
         let firstTempTime = (tempBasals.first?.timestamp ?? Date()).timeIntervalSince1970

+ 119 - 104
FreeAPS/Sources/Modules/Home/View/HomeRootView.swift

@@ -8,14 +8,12 @@ extension Home {
     struct RootView: BaseView {
         let resolver: Resolver
 
-        @ObservedObject var appState = AppState()
         @StateObject var state = StateModel()
         @State var isStatusPopupPresented = false
         @State var showCancelAlert = false
         @State var isMenuPresented = false
         @State var showTreatments = false
         @State var selectedTab: Int = 0
-        @State var currentTab: Tab
 
         struct Buttons: Identifiable {
             let label: String
@@ -584,7 +582,9 @@ extension Home {
                     )
                     .padding(.trailing, 8)
                     .onTapGesture {
-                        showCancelAlert = true
+                        if selectedProfile().name != "Normal Profile" {
+                            showCancelAlert = true
+                        }
                     }
             }.padding(.horizontal, 10).padding(.bottom, 10)
 
@@ -804,66 +804,63 @@ extension Home {
 
         @ViewBuilder func mainView() -> some View {
             GeometryReader { geo in
-                ZStack(alignment: .bottom) {
-                    VStack(spacing: 0) {
-                        Spacer()
+                VStack(spacing: 0) {
+                    Spacer()
+                        .frame(height: UIScreen.main.bounds.height / 16)
 
-                        ZStack {
-                            /// glucose bobble
-                            glucoseView
-
-                            /// right panel with loop status and evBG
-                            HStack {
-                                Spacer()
-                                rightHeaderPanel(geo)
-                            }.padding(.trailing, 20)
-
-                            /// left panel with pump related info
-                            HStack {
-                                pumpView
-                                Spacer()
-                            }.padding(.leading, 20)
-
-                            HStack {
-                                Spacer()
-                                Button {
-                                    isMenuPresented.toggle()
-                                }
-                                label: {
-                                    Image(systemName: "text.justify")
-                                        .font(.body).foregroundStyle(colorScheme == .dark ? Color.white : Color.black)
-                                }.padding(.trailing, 20).padding(.bottom, 110)
-                            }
+                    ZStack {
+                        /// glucose bobble
+                        glucoseView
 
-                        }.padding(.top, 10)
+                        /// right panel with loop status and evBG
+                        HStack {
+                            Spacer()
+                            rightHeaderPanel(geo)
+                        }.padding(.trailing, 20)
 
-                        mealPanel(geo).padding(.top, 30).padding(.bottom, 20)
+                        /// left panel with pump related info
+                        HStack {
+                            pumpView
+                            Spacer()
+                        }.padding(.leading, 20)
 
-                        RoundedRectangle(cornerRadius: 15)
-                            .fill(Color("Chart"))
-                            .overlay(mainChart)
-                            .clipShape(RoundedRectangle(cornerRadius: 15))
-                            .shadow(
-                                color: colorScheme == .dark ? Color(red: 0.02745098039, green: 0.1098039216, blue: 0.1411764706) :
-                                    Color.black.opacity(0.33),
-                                radius: 3
-                            )
-                            .padding(.horizontal, 10)
-                            .frame(maxHeight: UIScreen.main.bounds.height / 2.2)
+                        HStack {
+                            Spacer()
+                            Button {
+                                isMenuPresented.toggle()
+                            }
+                            label: {
+                                Image(systemName: "text.justify")
+                                    .font(.body).foregroundStyle(colorScheme == .dark ? Color.white : Color.black)
+                            }.padding(.trailing, 20).padding(.bottom, 110)
+                        }
 
-                        timeInterval.padding(.top, 20).padding(.bottom, 90)
+                    }.padding(.top, 10)
 
-                        Spacer()
-                    }
+                    mealPanel(geo).padding(.top, 30).padding(.bottom, 20)
+
+                    RoundedRectangle(cornerRadius: 15)
+                        .fill(Color("Chart"))
+                        .overlay(mainChart)
+                        .clipShape(RoundedRectangle(cornerRadius: 15))
+                        .shadow(
+                            color: colorScheme == .dark ? Color(red: 0.02745098039, green: 0.1098039216, blue: 0.1411764706) :
+                                Color.black.opacity(0.33),
+                            radius: 3
+                        )
+                        .padding(.horizontal, 10)
+                        .frame(maxHeight: UIScreen.main.bounds.height / 2.2)
+
+                    timeInterval.padding(.top, 15).padding(.bottom, 30)
 
                     if let progress = state.bolusProgress {
-                        bolusView(geo, progress).padding(.bottom, 80)
+                        bolusView(geo, progress)
                     } else {
-                        profileView(geo).padding(.bottom, 80)
+                        profileView(geo)
                     }
                 }
+
                 .background(color)
-                .blur(radius: isMenuPresented ? 5 : 0)
                 .edgesIgnoringSafeArea(.all)
             }
             .onChange(of: state.hours) { _ in
@@ -900,58 +897,88 @@ extension Home {
             }
         }
 
-        @ViewBuilder func tabBar() -> some View {
-            ZStack(alignment: .bottom) {
-                TabView(selection: $appState.currentTab) {
-                    mainView()
-                        .tabItem { Label("Home", systemImage: "house") }
-                        .tag(Tab.home)
-
-                    NavigationStack { DataTable.RootView(resolver: resolver) }
-                        .tabItem { Label("History", systemImage: historySFSymbol) }
-                        .tag(Tab.history)
-
-                    Spacer()
+        @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)
+                    }
+                })
+            }
+        }
 
-                    NavigationStack { OverrideProfilesConfig.RootView(resolver: resolver) }
-                        .tabItem {
-                            Label(
-                                "Profile",
-                                systemImage: state.isTempTargetActive || overrideString != nil ? "person.fill" : "person"
-                            ) }
-                        .tag(Tab.profile)
-
-                    NavigationStack { Settings.RootView(resolver: resolver) }
-                        .tabItem {
-                            Label(
-                                "Settings",
-                                systemImage: "gear"
-                            ) }
-                        .tag(Tab.settings)
+        @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()
+                    }
                 }
-                .tint(Color.tabBar)
-
-                Button(
-                    action: {
-                        state.showModal(for: .bolus(waitForSuggestion: true, fetch: false, editMode: false, override: false)) },
-                    label: {
-                        Image(systemName: "plus.circle.fill").font(.system(size: 40)).foregroundStyle(Color.gray)
+                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: true, fetch: false, editMode: false, override: false))
+                    }) {
+                        Image(systemName: "plus.circle.fill")
+                            .font(.system(size: 45))
+                            .shadow(
+                                color: colorScheme == .dark ? Color(red: 0.02745098039, green: 0.1098039216, blue: 0.1411764706) :
+                                    Color.black.opacity(0.33),
+                                radius: 3
+                            )
+                            .foregroundStyle(Color.tabBar)
                             .padding(.bottom, 2)
                     }
-                )
-            }
+                    Spacer()
+                    tabBarButton(
+                        index: 2,
+                        systemName: selectedTab == 2 ? "person.fill" : "person",
+                        label: "Profile"
+                    )
+                    Spacer()
+                    tabBarButton(index: 3, systemName: "gear", label: "Settings")
+                }
+                .padding(.horizontal, 20)
+            }.blur(radius: isMenuPresented ? 5 : 0)
         }
 
         var body: some View {
             ZStack(alignment: .trailing) {
-                // mainView()
-                tabBar()
+                customTabBar()
 
                 // burger menu
                 if isMenuPresented {
-                    HStack {
-                        sideMenuView().background(Color.chart).ignoresSafeArea(.all)
-                    }
+                    sideMenuView().background(Color.chart)
                 }
             }
         }
@@ -984,15 +1011,3 @@ extension Home {
         }
     }
 }
-
-class AppState: ObservableObject {
-    @Published var currentTab: Tab = .home
-}
-
-enum Tab {
-    case home
-    case history
-    case treatments
-    case profile
-    case settings
-}

+ 1 - 1
FreeAPS/Sources/Modules/OverrideProfilesConfig/View/OverrideProfilesRootView.swift

@@ -94,7 +94,7 @@ extension OverrideProfilesConfig {
                             .foregroundColor(
                                 state
                                     .percentage >= 130 ? .red :
-                                    (isEditing ? .orange : Color.tabBar)
+                                    (isEditing ? .orange : Color.blue)
                             )
                             .font(.largeTitle)
                         Slider(

+ 1 - 1
FreeAPS/Sources/Router/Screen.swift

@@ -44,7 +44,7 @@ extension Screen {
         case .loading:
             ProgressView()
         case .home:
-            Home.RootView(resolver: resolver, currentTab: .home)
+            Home.RootView(resolver: resolver)
         case .settings:
             Settings.RootView(resolver: resolver)
         case let .configEditor(file):