| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- import Charts
- import SwiftUI
- struct TrioMainWatchView: View {
- @State private var state = WatchState()
- // misc
- @State private var currentPage: Int = 0
- @State private var rotationDegrees: Double = 0.0
- @State private var showingTempTargetSheet = false
- // view visbility
- @State private var showingTreatmentMenuSheet: Bool = false
- @State private var showingOverrideSheet: Bool = false
- // navigation flag for meal bolus combo
- @State private var continueToBolus = false
- // @State private var navigationPath: [NavigationDestinations] = []
- @State private var navigationPath = NavigationPath()
- // treatments
- @State private var selectedTreatment: TreatmentOption?
- // Active adjustment indicator
- private func isAdjustmentActive<T>(for presets: [T], predicate: (T) -> Bool) -> Bool {
- let sortedPresets = presets.sorted { predicate($0) && !predicate($1) }
- return !sortedPresets.isEmpty && sortedPresets.first(where: predicate) != nil
- }
- private var isTempTargetActive: Bool {
- isAdjustmentActive(for: state.tempTargetPresets) { $0.isEnabled }
- }
- private var isOverrideActive: Bool {
- isAdjustmentActive(for: state.overridePresets) { $0.isEnabled }
- }
- private var trioBackgroundColor = LinearGradient(
- gradient: Gradient(colors: [Color.bgDarkBlue, Color.bgDarkerDarkBlue]),
- startPoint: .top,
- endPoint: .bottom
- )
- var body: some View {
- NavigationStack(path: $navigationPath) {
- TabView(selection: $currentPage) {
- // Page 1: Current glucose trend in "BG bobble"
- GlucoseTrendView(state: state, rotationDegrees: rotationDegrees)
- .tag(0)
- // Page 2: Glucose chart
- GlucoseChartView(glucoseValues: state.glucoseValues)
- .tag(1)
- }
- .background(trioBackgroundColor)
- .tabViewStyle(.verticalPage)
- .digitalCrownRotation($currentPage.doubleBinding(), from: 0, through: 1, by: 1)
- .onChange(of: state.trend) { _, newTrend in
- withAnimation {
- updateRotation(for: newTrend)
- }
- }
- .onAppear {
- state.confirmationProgress = 0 // reset auth progress
- }
- .toolbar {
- ToolbarItem(placement: .topBarLeading) {
- HStack {
- Image(systemName: "syringe.fill")
- .foregroundStyle(.blue)
- Text(state.iob ?? "--")
- .foregroundStyle(.white)
- }.font(.caption)
- }
- ToolbarItem(placement: .topBarTrailing) {
- HStack {
- Text(state.cob ?? "--")
- .foregroundStyle(.white)
- Image(systemName: "fork.knife")
- .foregroundStyle(.orange)
- }.font(.caption)
- }
- ToolbarItemGroup(placement: .bottomBar) {
- Button {
- showingOverrideSheet = true
- } label: {
- Image(systemName: "clock.arrow.2.circlepath")
- .foregroundStyle(Color.primary, isOverrideActive ? Color.primary : Color.purple)
- }.tint(isOverrideActive ? Color.purple : nil)
- Button {
- showingTreatmentMenuSheet = true
- } label: {
- Image(systemName: "plus")
- .foregroundStyle(Color.bgDarkerDarkBlue)
- }
- .controlSize(.large)
- .buttonStyle(WatchOSButtonStyle())
- Button {
- showingTempTargetSheet = true
- } label: {
- Image(systemName: "target")
- .foregroundStyle(isTempTargetActive ? Color.primary : Color.green.opacity(0.75))
- }.tint(isTempTargetActive ? Color.green.opacity(0.75) : nil)
- }
- }
- .fullScreenCover(isPresented: $showingTreatmentMenuSheet) {
- TreatmentMenuView(selectedTreatment: $selectedTreatment) {
- handleTreatmentSelection()
- }
- .onAppear {
- // reset the conditional navigation flag when opening
- continueToBolus = false
- }
- }
- .sheet(isPresented: $showingOverrideSheet) {
- OverridePresetsView(
- overridePresets: state.overridePresets,
- state: state
- )
- }
- .sheet(isPresented: $showingTempTargetSheet) {
- TempTargetPresetsView(
- tempTargetPresets: state.tempTargetPresets,
- state: state
- )
- }
- .navigationDestination(for: NavigationDestinations.self) { destination in
- switch destination {
- case .acknowledgmentPending:
- AcknowledgementPendingView(
- navigationPath: $navigationPath,
- state: state
- )
- case .carbsInput:
- CarbsInputView(
- navigationPath: $navigationPath,
- state: state,
- continueToBolus: continueToBolus
- )
- case .bolusInput:
- BolusInputView(
- navigationPath: $navigationPath,
- state: state
- )
- case .bolusConfirm:
- BolusConfirmationView(
- navigationPath: $navigationPath,
- state: state,
- bolusAmount: $state.bolusAmount,
- confirmationProgress: $state.confirmationProgress
- )
- }
- }
- .onChange(of: navigationPath) { _, newPath in
- if newPath.isEmpty {
- // Reset conditional view navigation when returning to root view
- continueToBolus = false
- }
- }
- }
- .blur(radius: state.showBolusProgressOverlay ? 3 : 0)
- .overlay {
- if state.showBolusProgressOverlay {
- BolusProgressOverlay(state: state)
- .transition(.opacity)
- }
- }
- }
- private func updateRotation(for trend: String?) {
- switch trend {
- case "DoubleUp",
- "SingleUp":
- rotationDegrees = -90
- case "FortyFiveUp":
- rotationDegrees = -45
- case "Flat":
- rotationDegrees = 0
- case "FortyFiveDown":
- rotationDegrees = 45
- case "DoubleDown",
- "SingleDown":
- rotationDegrees = 90
- default:
- rotationDegrees = 0
- }
- }
- private func handleTreatmentSelection() {
- showingTreatmentMenuSheet = false // Dismiss the sheet
- guard let treatment = selectedTreatment else { return }
- switch treatment {
- case .meal:
- navigationPath.append(NavigationDestinations.carbsInput)
- case .bolus:
- navigationPath.append(NavigationDestinations.bolusInput)
- case .mealBolusCombo:
- continueToBolus = true // Explicitely set subsequent view navigation
- navigationPath.append(NavigationDestinations.carbsInput)
- }
- }
- }
- #Preview {
- TrioMainWatchView()
- }
|