| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- import LoopKitUI
- import SwiftUI
- import Swinject
- extension CGM {
- struct RootView: BaseView {
- let resolver: Resolver
- let displayClose: Bool
- @StateObject var state = StateModel()
- @State private var shouldDisplayHint: Bool = false
- @State var hintDetent = PresentationDetent.large
- @State var selectedVerboseHint: AnyView?
- @State var hintLabel: String?
- @State private var decimalPlaceholder: Decimal = 0.0
- @State private var booleanPlaceholder: Bool = false
- @State var showCGMSelection: Bool = false
- @Environment(\.colorScheme) var colorScheme
- @Environment(AppState.self) var appState
- var body: some View {
- NavigationView {
- Form {
- Section(
- header: Text("CGM Integration to Trio"),
- content: {
- let cgmState = state.cgmCurrent
- if cgmState.type != .none {
- Button {
- state.setupCGM = true
- } label: {
- HStack {
- Image(systemName: "sensor.tag.radiowaves.forward.fill")
- Text(cgmState.displayName)
- }
- .frame(maxWidth: .infinity, minHeight: 50, alignment: .center)
- .font(.title2)
- }.padding()
- } else {
- VStack {
- Button {
- showCGMSelection.toggle()
- } label: {
- Text("Add CGM")
- .font(.title3) }
- .frame(maxWidth: .infinity, alignment: .center)
- .buttonStyle(.bordered)
- HStack(alignment: .center) {
- Text(
- "Pair your CGM with Trio. See hint for compatible devices."
- )
- .font(.footnote)
- .foregroundColor(.secondary)
- .lineLimit(nil)
- Spacer()
- Button(
- action: {
- shouldDisplayHint.toggle()
- },
- label: {
- HStack {
- Image(systemName: "questionmark.circle")
- }
- }
- ).buttonStyle(BorderlessButtonStyle())
- }.padding(.top)
- }.padding(.vertical)
- }
- }
- )
- .listRowBackground(Color.chart)
- if state.cgmCurrent.type == .plugin && state.cgmCurrent.id.contains("Libre") {
- Section {
- NavigationLink(
- destination: Calibrations.RootView(resolver: resolver),
- label: { Text("Libre Calibrations") }
- )
- }.listRowBackground(Color.chart)
- }
- SettingInputSection(
- decimalValue: $decimalPlaceholder,
- booleanValue: $state.smoothGlucose,
- shouldDisplayHint: $shouldDisplayHint,
- selectedVerboseHint: Binding(
- get: { selectedVerboseHint },
- set: {
- selectedVerboseHint = $0.map { AnyView($0) }
- hintLabel = "Smooth Glucose Value"
- }
- ),
- units: state.units,
- type: .boolean,
- label: "Smooth Glucose Value",
- miniHint: "Smooth CGM readings using Savitzky-Golay filtering.",
- verboseHint:
- VStack(alignment: .leading, spacing: 10) {
- Text("Default: OFF").bold()
- Text(
- "This filter looks at small groups of nearby readings and fits them to a simple mathematical curve. This process doesn't change the overall pattern of your glucose data but helps smooth out the \"noise\" or irregular fluctuations that could lead to false highs or lows."
- )
- Text(
- "It's designed to keep the important trends in your data while minimizing those small, misleading variations, giving you and Trio a clearer sense of where your blood sugar is really headed. This type of filtering is useful in Trio, as it can help prevent over-corrections based on inaccurate glucose readings. This can help reduce the impact of sudden spikes or dips that might not reflect your true blood glucose levels."
- )
- Text(
- "Note: If enabled, the smoothed values you see in Trio may differ from what is shown in your CGM app."
- )
- }
- )
- }
- .scrollContentBackground(.hidden).background(appState.trioBackgroundColor(for: colorScheme))
- .onAppear(perform: configureView)
- .navigationTitle("CGM")
- .navigationBarTitleDisplayMode(.automatic)
- .navigationBarItems(leading: displayClose ? Button("Close", action: state.hideModal) : nil)
- .sheet(isPresented: $state.setupCGM) {
- switch state.cgmCurrent.type {
- case .enlite,
- .nightscout,
- .none,
- .simulator,
- .xdrip:
- OtherCGMView(resolver: self.resolver, state: state)
- case .plugin:
- if let cgmFetchManager = state.cgmManager,
- let cgmManager = cgmFetchManager.cgmManager,
- state.cgmCurrent.type == cgmFetchManager.cgmGlucoseSourceType,
- state.cgmCurrent.id == cgmFetchManager.cgmGlucosePluginId
- {
- CGMSettingsView(
- cgmManager: cgmManager,
- bluetoothManager: state.provider.apsManager.bluetoothManager!,
- unit: state.settingsManager.settings.units,
- completionDelegate: state
- )
- } else {
- CGMSetupView(
- CGMType: state.cgmCurrent,
- bluetoothManager: state.provider.apsManager.bluetoothManager!,
- unit: state.settingsManager.settings.units,
- completionDelegate: state,
- setupDelegate: state,
- pluginCGMManager: self.state.pluginCGMManager
- )
- }
- }
- }
- .sheet(isPresented: $shouldDisplayHint) {
- SettingInputHintView(
- hintDetent: $hintDetent,
- shouldDisplayHint: $shouldDisplayHint,
- hintLabel: hintLabel ?? "",
- hintText: AnyView(
- VStack(alignment: .leading, spacing: 10) {
- Text(
- "Current CGM Models Supported:"
- )
- VStack(alignment: .leading) {
- Text("• Dexcom G5")
- Text("• Dexcom G6 / ONE")
- Text("• Dexcom G7 / ONE+")
- Text("• Dexcom Share")
- Text("• Freestyle Libre")
- Text("• Freestyle Libre Demo")
- Text("• Glucose Simulator")
- Text("• Medtronic Enlite")
- Text("• Nightscout")
- Text("• xDrip4iOS")
- }
- Text(
- "Note: The CGM Heartbeat can come from either a CGM or a pump to wake up Trio when phone is locked or in the background. If CGM is on the same phone as Trio and xDrip4iOS is configured to use the same AppGroup as Trio and the heartbeat feature is turned on in xDrip4iOS, then the CGM can provide a heartbeat to wake up Trio when phone is locked or app is in the background."
- )
- }
- ),
- sheetTitle: "Help"
- )
- }
- .confirmationDialog("CGM Model", isPresented: $showCGMSelection) {
- Button("Nightscout") { state.addCGM(cgm: state.listOfCGM.first(where: { $0.type == .nightscout })!) }
- Button("Dexcom G5") {
- state.addCGM(cgm: state.listOfCGM.first(where: { $0.type == .plugin && $0.displayName.contains("G5") })!)
- }
- Button("Dexcom G6 / ONE") {
- state
- .addCGM(
- cgm: state.listOfCGM
- .first(where: { $0.type == .plugin && $0.displayName.contains("G6") })!
- )
- }
- Button("Dexcom G7 / ONE+") {
- state
- .addCGM(
- cgm: state.listOfCGM
- .first(where: { $0.type == .plugin && $0.displayName.contains("G7") })!
- )
- }
- Button("Dexcom Share") {
- state.addCGM(
- cgm: state.listOfCGM
- .first(where: { $0.type == .plugin && $0.displayName.contains("Dexcom Share") })!
- ) }
- Button("FreeStyle Libre") {
- state.addCGM(
- cgm: state.listOfCGM
- .first(
- where: { $0.type == .plugin && $0.displayName == "FreeStyle Libre" }
- )!
- ) }
- Button("FreeStyle Libre Demo") {
- state.addCGM(
- cgm: state.listOfCGM
- .first(where: { $0.type == .plugin && $0.displayName == "FreeStyle Libre Demo" })!
- ) }
- Button("Medtronic Enlite") {
- state.addCGM(cgm: state.listOfCGM.first(where: { $0.type == .enlite })!) }
- Button("xDrip4iOS") {
- state.addCGM(cgm: state.listOfCGM.first(where: { $0.type == .xdrip })!) }
- Button("Glucose Simulator") {
- state
- .addCGM(
- cgm: state.listOfCGM
- .first(where: { $0.type == .simulator })!
- ) }
- } message: { Text("Select CGM Model") }
- }
- }
- }
- }
|