瀏覽代碼

remove swiftcharts

Ivan Valkou 5 年之前
父節點
當前提交
cded0235cb
共有 62 個文件被更改,包括 157 次插入29273 次删除
  1. 0 172
      Dependecies/LoopKit/LoopKit.xcodeproj/project.pbxproj
  2. 0 57
      Dependecies/LoopKit/LoopKitUI/Charts/GlucoseChart.swift
  3. 0 140
      Dependecies/LoopKit/LoopKitUI/Charts/InsulinModelChart.swift
  4. 0 23
      Dependecies/LoopKit/LoopKitUI/Extensions/ChartLineModel+LoopKitUI.swift
  5. 0 23
      Dependecies/LoopKit/LoopKitUI/Extensions/ChartSettings+LoopKitUI.swift
  6. 0 31
      Dependecies/LoopKit/LoopKitUI/Models/ChartAxisValueDoubleUnit.swift
  7. 0 239
      Dependecies/LoopKit/LoopKitUI/View Controllers/ChartsManager.swift
  8. 0 161
      Dependecies/LoopKit/LoopKitUI/View Controllers/ChartsTableViewController.swift
  9. 0 40
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/BasalRatesInformationView.swift
  10. 0 44
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/CarbRatioInformationView.swift
  11. 0 62
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/CorrectionRangeInformationView.swift
  12. 0 96
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/CorrectionRangeOverrideInformationView.swift
  13. 0 67
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/DeliveryLimitsInformationView.swift
  14. 0 102
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/GlucoseTherapySettingInformationView.swift
  15. 0 6
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/Contents.json
  16. 0 5240
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/glucoseTargetRange mgdL.imageset/Chart=Correction, Version=V7, Appearance=Dark, Unit=mgdL.pdf
  17. 二進制
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/glucoseTargetRange mgdL.imageset/Chart=Correction, Version=V7, Appearance=Light, Unit=mgdL.pdf
  18. 0 26
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/glucoseTargetRange mgdL.imageset/Contents.json
  19. 0 5041
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/preMealCorrectionRangeOverride mgdL.imageset/Chart=Premeal, Version=V7, Appearance=Dark, Unit=mgdL.pdf
  20. 二進制
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/preMealCorrectionRangeOverride mgdL.imageset/Chart=Premeal, Version=V7, Appearance=Light, Unit=mgdL.pdf
  21. 0 26
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/preMealCorrectionRangeOverride mgdL.imageset/Contents.json
  22. 0 3283
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/suspendThreshold mgdL.imageset/Chart=Glucose, Version=V7, Appearance=Dark, Unit=mgdL.pdf
  23. 0 3210
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/suspendThreshold mgdL.imageset/Chart=Glucose, Version=V7, Appearance=Light, Unit=mgdL.pdf
  24. 0 26
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/suspendThreshold mgdL.imageset/Contents.json
  25. 0 5307
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/workoutCorrectionRangeOverride mgdL.imageset/Chart=Workout, Version=V7, Appearance=Dark, Unit=mgdL.pdf
  26. 二進制
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/workoutCorrectionRangeOverride mgdL.imageset/Chart=Workout, Version=V7, Appearance=Light, Unit=mgdL.pdf
  27. 0 26
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/workoutCorrectionRangeOverride mgdL.imageset/Contents.json
  28. 0 91
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationView.swift
  29. 0 62
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InsulinModelInformationView.swift
  30. 0 44
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InsulinSensitivityInformationView.swift
  31. 0 54
      Dependecies/LoopKit/LoopKitUI/Views/Information Screens/SuspendThresholdInformationView.swift
  32. 0 224
      Dependecies/LoopKit/LoopKitUI/Views/QuantityScheduleEditor.swift
  33. 0 435
      Dependecies/LoopKit/LoopKitUI/Views/ScheduleEditor.swift
  34. 0 173
      Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/BasalRateScheduleEditor.swift
  35. 0 112
      Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/CarbRatioScheduleEditor.swift
  36. 0 367
      Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/CorrectionRangeOverridesEditor.swift
  37. 0 50
      Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/CorrectionRangeOverridesExpandableSetting.swift
  38. 0 29
      Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/CorrectionRangeOverridesExtension.swift
  39. 0 194
      Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/CorrectionRangeScheduleEditor.swift
  40. 0 368
      Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/DeliveryLimitsEditor.swift
  41. 0 46
      Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/InsulinModelChartView.swift
  42. 0 262
      Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/InsulinModelSelection.swift
  43. 0 128
      Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/InsulinSensitivityScheduleEditor.swift
  44. 0 18
      Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/PumpSupportedIncrements.swift
  45. 0 27
      Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/SettingsPresentationMode.swift
  46. 0 16
      Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/SupportedInsulinModelSettings.swift
  47. 0 251
      Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/SuspendThresholdEditor.swift
  48. 0 47
      Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/TherapySetting+Settings.swift
  49. 0 589
      Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/TherapySettingsView.swift
  50. 0 113
      Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/TherapySettingsViewModel.swift
  51. 0 1736
      Dependecies/SwiftCharts/SwiftCharts.xcodeproj/project.pbxproj
  52. 0 7
      Dependecies/SwiftCharts/SwiftCharts.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  53. 0 8
      Dependecies/SwiftCharts/SwiftCharts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  54. 0 87
      Dependecies/SwiftCharts/SwiftCharts.xcodeproj/xcshareddata/xcschemes/Examples.xcscheme
  55. 0 76
      Dependecies/SwiftCharts/SwiftCharts.xcodeproj/xcshareddata/xcschemes/SwiftCharts tvOS.xcscheme
  56. 0 109
      Dependecies/SwiftCharts/SwiftCharts.xcodeproj/xcshareddata/xcschemes/SwiftCharts.xcscheme
  57. 10 16
      FreeAPS.xcodeproj/project.pbxproj
  58. 0 28
      FreeAPS.xcodeproj/xcshareddata/xcschemes/FreeAPS.xcscheme
  59. 0 3
      FreeAPS.xcworkspace/contents.xcworkspacedata
  60. 22 4
      FreeAPS.xcworkspace/xcshareddata/swiftpm/Package.resolved
  61. 124 50
      FreeAPS/Sources/Modules/Home/View/GlucoseChartView.swift
  62. 1 1
      FreeAPS/Sources/Modules/Home/View/HomeRootView.swift

+ 0 - 172
Dependecies/LoopKit/LoopKit.xcodeproj/project.pbxproj

@@ -26,25 +26,17 @@
 		1D096C0224C24C220078B6B5 /* InsulinModelSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D096BFF24C24C220078B6B5 /* InsulinModelSettings.swift */; };
 		1D096C0324C24C220078B6B5 /* ExponentialInsulinModelPreset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D096C0024C24C220078B6B5 /* ExponentialInsulinModelPreset.swift */; };
 		1D096C0524C624F70078B6B5 /* InsulinModelSettings+LoopKitUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D096C0424C624F70078B6B5 /* InsulinModelSettings+LoopKitUI.swift */; };
-		1D1438B825633E2100BE8F06 /* GlucoseTherapySettingInformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D1438B725633E2100BE8F06 /* GlucoseTherapySettingInformationView.swift */; };
-		1D1A019E24B678BF0077D86E /* TherapySettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D1A019D24B678BF0077D86E /* TherapySettingsView.swift */; };
-		1D1FCE2324BD13A2000300A8 /* CorrectionRangeOverridesExpandableSetting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D1FCE2224BD13A2000300A8 /* CorrectionRangeOverridesExpandableSetting.swift */; };
-		1D1FCE2524BD42EF000300A8 /* TherapySettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D1FCE2424BD42EF000300A8 /* TherapySettingsViewModel.swift */; };
 		1D1FCE2724BE4DE2000300A8 /* CorrectionRangeOverrides.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D1FCE2624BE4DE2000300A8 /* CorrectionRangeOverrides.swift */; };
 		1D1FCE2924BE4F11000300A8 /* TherapySetting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D1FCE2824BE4F11000300A8 /* TherapySetting.swift */; };
-		1D1FCE2B24BE704A000300A8 /* TherapySetting+Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D1FCE2A24BE704A000300A8 /* TherapySetting+Settings.swift */; };
 		1D24A8D524C896E100AB8DB9 /* Prescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D24A8D424C896E100AB8DB9 /* Prescription.swift */; };
 		1D25C22E246A2A1A00E87FA0 /* critical.caf in Resources */ = {isa = PBXBuildFile; fileRef = 1D25C22D246A2A1A00E87FA0 /* critical.caf */; };
 		1D498E4724D892B0000627F2 /* Environment+Authenticate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D498E4624D892B0000627F2 /* Environment+Authenticate.swift */; };
 		1D60355E24D39ED10095DC2A /* Environment+AppName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D60355D24D39ED10095DC2A /* Environment+AppName.swift */; };
 		1D640FF724525228008F9755 /* sub.caf in Resources */ = {isa = PBXBuildFile; fileRef = 1D640FF524524284008F9755 /* sub.caf */; };
-		1D67E79D2563001800A82ED6 /* InformationScreens.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1D67E79C2563001800A82ED6 /* InformationScreens.xcassets */; };
-		1D6EAB9124C12C090081249D /* PumpSupportedIncrements.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D6EAB9024C12C090081249D /* PumpSupportedIncrements.swift */; };
 		1D841AAD24577EE10069DBFF /* AlertSoundPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D841AAC24577EE10069DBFF /* AlertSoundPlayer.swift */; };
 		1D97A33C256F11E00042737E /* View+InsetGroupedListStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D97A33B256F11E00042737E /* View+InsetGroupedListStyle.swift */; };
 		1DA649AB2445174400F61E75 /* Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DA649AA2445174400F61E75 /* Alert.swift */; };
 		1DABAD3A2453615200ACF708 /* IssueAlertTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DABAD392453615200ACF708 /* IssueAlertTableViewController.swift */; };
-		1DC64C7C24BF6BFD004A63A1 /* CorrectionRangeOverridesExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DC64C7B24BF6BFD004A63A1 /* CorrectionRangeOverridesExtension.swift */; };
 		1DC64C7E24BF6EBC004A63A1 /* DeliveryLimits.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DC64C7D24BF6EBC004A63A1 /* DeliveryLimits.swift */; };
 		1DC9240F2575EF9A004F132A /* QuantityFormatter+Guardrails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DC9240E2575EF9A004F132A /* QuantityFormatter+Guardrails.swift */; };
 		1DD1964E248AE88000420876 /* HorizontalSizeClassOverride.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DD1964D248AE88000420876 /* HorizontalSizeClassOverride.swift */; };
@@ -53,7 +45,6 @@
 		1DECC3F52513F98D00F4056E /* UITextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DECC3F42513F98D00F4056E /* UITextField.swift */; };
 		1DEE227724A676A300693C32 /* HKHealthStoreMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437AFF1E203A763F008C4892 /* HKHealthStoreMock.swift */; };
 		1DEE229D24A676A300693C32 /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43D8FDCB1C728FDF0073BE78 /* LoopKit.framework */; };
-		1DEF977524C62F8400D630CB /* SupportedInsulinModelSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DEF977424C62F8400D630CB /* SupportedInsulinModelSettings.swift */; };
 		1DFB99D6245CB2E900DCC8C9 /* AlertTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DFB99D5245CB2E900DCC8C9 /* AlertTests.swift */; };
 		1F5DAB1D2118C95700048054 /* LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F5DAB1C2118C95700048054 /* LocalizedString.swift */; };
 		1F5DAB1F2118C95700048054 /* LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F5DAB1C2118C95700048054 /* LocalizedString.swift */; };
@@ -397,14 +388,11 @@
 		89627B16244115A400BEB424 /* CardList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89627B15244115A400BEB424 /* CardList.swift */; };
 		89627B182441168900BEB424 /* ConfigurationPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89627B172441168900BEB424 /* ConfigurationPage.swift */; };
 		89653C802473527100E1BAA5 /* FractionalQuantityPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89653C7F2473527100E1BAA5 /* FractionalQuantityPicker.swift */; };
-		89653C822473592600E1BAA5 /* CarbRatioScheduleEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89653C812473592600E1BAA5 /* CarbRatioScheduleEditor.swift */; };
-		89653C8424738D2B00E1BAA5 /* BasalRateScheduleEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89653C8324738D2B00E1BAA5 /* BasalRateScheduleEditor.swift */; };
 		8974AFC022120D7A0043F01B /* TemporaryScheduleOverrideTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8974AFBF22120D7A0043F01B /* TemporaryScheduleOverrideTests.swift */; };
 		8974B0682215FE460043F01B /* Collection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8974B0672215FE460043F01B /* Collection.swift */; };
 		8974B0692215FE460043F01B /* Collection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8974B0672215FE460043F01B /* Collection.swift */; };
 		898B4E75246CCAB50053C484 /* Binding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 898B4E74246CCAB50053C484 /* Binding.swift */; };
 		898B4E77246DAE280053C484 /* GlucoseRangePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 898B4E76246DAE280053C484 /* GlucoseRangePicker.swift */; };
-		898B4E7B246DC6A70053C484 /* CorrectionRangeScheduleEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 898B4E7A246DC6A70053C484 /* CorrectionRangeScheduleEditor.swift */; };
 		898B4E7E246DEB920053C484 /* GuardrailConstrainedQuantityRangeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 898B4E7D246DEB920053C484 /* GuardrailConstrainedQuantityRangeView.swift */; };
 		898C896A24D4BF11002FA994 /* Guardrail+Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 898C896924D4BF11002FA994 /* Guardrail+Settings.swift */; };
 		898C896D24D4BF75002FA994 /* FloatingPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 898C896C24D4BF75002FA994 /* FloatingPoint.swift */; };
@@ -517,10 +505,7 @@
 		89F6E311244A1AAB00CB9E15 /* SettingDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89F6E310244A1AAB00CB9E15 /* SettingDescription.swift */; };
 		89F6E314244A1AB600CB9E15 /* GuardrailWarning.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89F6E312244A1AB500CB9E15 /* GuardrailWarning.swift */; };
 		89F6E315244A1AB600CB9E15 /* GlucoseValuePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89F6E313244A1AB600CB9E15 /* GlucoseValuePicker.swift */; };
-		89FC688F245A2D680075CF59 /* InsulinSensitivityScheduleEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89FC688A245A2D670075CF59 /* InsulinSensitivityScheduleEditor.swift */; };
-		89FC6890245A2D680075CF59 /* QuantityScheduleEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89FC688B245A2D670075CF59 /* QuantityScheduleEditor.swift */; };
 		89FC6891245A2D680075CF59 /* ScheduleItemPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89FC688C245A2D680075CF59 /* ScheduleItemPicker.swift */; };
-		89FC6892245A2D680075CF59 /* ScheduleEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89FC688D245A2D680075CF59 /* ScheduleEditor.swift */; };
 		89FC6893245A2D680075CF59 /* ScheduleItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89FC688E245A2D680075CF59 /* ScheduleItemView.swift */; };
 		9E78433F236653F00016C583 /* ice_35_min_none_piecewiselinear_output.json in Resources */ = {isa = PBXBuildFile; fileRef = 9E78433E236653F00016C583 /* ice_35_min_none_piecewiselinear_output.json */; };
 		9E784341236656770016C583 /* ice_35_min_partial_piecewiselinear_output.json in Resources */ = {isa = PBXBuildFile; fileRef = 9E784340236656770016C583 /* ice_35_min_partial_piecewiselinear_output.json */; };
@@ -771,29 +756,13 @@
 		C1F8403923DB84B700673141 /* DeviceLogEntry+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1F8403723DB84B700673141 /* DeviceLogEntry+CoreDataClass.swift */; };
 		C1F8403A23DB84B700673141 /* DeviceLogEntry+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1F8403823DB84B700673141 /* DeviceLogEntry+CoreDataProperties.swift */; };
 		C1F8B1E2223C3CC000DD66CF /* TimeZone.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4303C4901E2D664200ADEDC8 /* TimeZone.swift */; };
-		E9077D2724ACD59F0066A88D /* InformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9077D2624ACD59F0066A88D /* InformationView.swift */; };
-		E9077D2A24ACDE2C0066A88D /* CorrectionRangeInformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9077D2924ACDE2C0066A88D /* CorrectionRangeInformationView.swift */; };
-		E9086B2924B39EDC0062F5C8 /* ChartsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9086B2824B39EDC0062F5C8 /* ChartsTableViewController.swift */; };
-		E9086B2D24B3A4AC0062F5C8 /* ChartsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9086B2C24B3A4AC0062F5C8 /* ChartsManager.swift */; };
 		E9086B2F24B3A5080062F5C8 /* ChartColorPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9086B2E24B3A5080062F5C8 /* ChartColorPalette.swift */; };
 		E9086B3124B3A7270062F5C8 /* ChartTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9086B3024B3A7270062F5C8 /* ChartTableViewCell.swift */; };
 		E9086B3524B3A8820062F5C8 /* ChartContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9086B3424B3A8820062F5C8 /* ChartContainerView.swift */; };
 		E9086B3924B3CB4B0062F5C8 /* TherapySettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9086B3824B3CB4B0062F5C8 /* TherapySettings.swift */; };
-		E9086B4524B53CC50062F5C8 /* GlucoseChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9086B4424B53CC50062F5C8 /* GlucoseChart.swift */; };
-		E9086B4824B5405E0062F5C8 /* ChartAxisValueDoubleUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9086B4724B5405E0062F5C8 /* ChartAxisValueDoubleUnit.swift */; };
 		E9086B4A24B540B70062F5C8 /* DateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9086B4924B540B70062F5C8 /* DateFormatter.swift */; };
-		E916F56924AD32F000BE3547 /* CorrectionRangeOverridesEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E916F56824AD32F000BE3547 /* CorrectionRangeOverridesEditor.swift */; };
-		E916F56F24AE2FFE00BE3547 /* CorrectionRangeOverrideInformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E916F56E24AE2FFE00BE3547 /* CorrectionRangeOverrideInformationView.swift */; };
-		E92094EF257C5FFB004D6192 /* SettingsPresentationMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E92094EE257C5FFB004D6192 /* SettingsPresentationMode.swift */; };
 		E93BA06624A39DBC00C5D7E6 /* DismissibleHostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93BA06524A39DBC00C5D7E6 /* DismissibleHostingController.swift */; };
-		E93C86A024C8F6E00073089B /* InsulinModelSelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93C869F24C8F6E00073089B /* InsulinModelSelection.swift */; };
-		E93C86A224C8F7550073089B /* InsulinModelChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93C86A124C8F7550073089B /* InsulinModelChart.swift */; };
-		E93C86A424C8F79C0073089B /* ChartLineModel+LoopKitUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93C86A324C8F79C0073089B /* ChartLineModel+LoopKitUI.swift */; };
-		E93C86A624C8F7D90073089B /* ChartSettings+LoopKitUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93C86A524C8F7D90073089B /* ChartSettings+LoopKitUI.swift */; };
-		E93C86A824C8F7F70073089B /* InsulinModelChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93C86A724C8F7F60073089B /* InsulinModelChartView.swift */; };
 		E93C86B024CF7C470073089B /* TherapySettingsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93C86AF24CF7C470073089B /* TherapySettingsTests.swift */; };
-		E93C86B224D080E00073089B /* CarbRatioInformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93C86B124D080E00073089B /* CarbRatioInformationView.swift */; };
-		E93C86B624D08CAD0073089B /* InsulinSensitivityInformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93C86B524D08CAD0073089B /* InsulinSensitivityInformationView.swift */; };
 		E93E865A24DC744300FF40C8 /* effect_from_basal_output_exponential.json in Resources */ = {isa = PBXBuildFile; fileRef = E93E865924DC744300FF40C8 /* effect_from_basal_output_exponential.json */; };
 		E93E865C24DC75EF00FF40C8 /* basal_dose_with_expired.json in Resources */ = {isa = PBXBuildFile; fileRef = E93E865B24DC75EF00FF40C8 /* basal_dose_with_expired.json */; };
 		E93E865E24DC797A00FF40C8 /* basal_dose_with_delivered.json in Resources */ = {isa = PBXBuildFile; fileRef = E93E865D24DC797A00FF40C8 /* basal_dose_with_delivered.json */; };
@@ -802,13 +771,7 @@
 		E93E866424DCFB6D00FF40C8 /* OverrideHistoryCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93E866324DCFB6D00FF40C8 /* OverrideHistoryCollectionViewCell.swift */; };
 		E93E866A24DD05FA00FF40C8 /* OverrideSelectionHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93E866924DD05FA00FF40C8 /* OverrideSelectionHistory.swift */; };
 		E94141CE24C8F2950096C326 /* ExponentialInsulinModelPreset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D096C0024C24C220078B6B5 /* ExponentialInsulinModelPreset.swift */; };
-		E94141D024C8F31C0096C326 /* DeliveryLimitsEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E94141CF24C8F31C0096C326 /* DeliveryLimitsEditor.swift */; };
-		E949E38924AFC82F00024DA0 /* DeliveryLimitsInformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E949E38824AFC82F00024DA0 /* DeliveryLimitsInformationView.swift */; };
-		E949E38F24B3711E00024DA0 /* InsulinModelInformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E949E38E24B3711E00024DA0 /* InsulinModelInformationView.swift */; };
 		E96175AE24B7BE38008E5080 /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = E96175AD24B7BE38008E5080 /* Dictionary.swift */; };
-		E96DCB5824AEF50F007117BC /* SuspendThresholdInformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E96DCB5724AEF50F007117BC /* SuspendThresholdInformationView.swift */; };
-		E96DCB5A24AF74AC007117BC /* SuspendThresholdEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E96DCB5924AF74AC007117BC /* SuspendThresholdEditor.swift */; };
-		E96DCB5E24AF7DC7007117BC /* BasalRatesInformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E96DCB5D24AF7DC7007117BC /* BasalRatesInformationView.swift */; };
 		E99A132E2557548300D3F5B3 /* SegmentedGaugeBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = E99A132D2557548300D3F5B3 /* SegmentedGaugeBar.swift */; };
 		E9C58A6E24DA65E400487A17 /* HistoricalOverrideDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9C58A6D24DA65E400487A17 /* HistoricalOverrideDetailView.swift */; };
 		E9C6911A25180A4E009F9999 /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = E9C6911625180A4E009F9999 /* Model.xcdatamodeld */; };
@@ -957,25 +920,17 @@
 		1D096BFF24C24C220078B6B5 /* InsulinModelSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InsulinModelSettings.swift; sourceTree = "<group>"; };
 		1D096C0024C24C220078B6B5 /* ExponentialInsulinModelPreset.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExponentialInsulinModelPreset.swift; sourceTree = "<group>"; };
 		1D096C0424C624F70078B6B5 /* InsulinModelSettings+LoopKitUI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "InsulinModelSettings+LoopKitUI.swift"; sourceTree = "<group>"; };
-		1D1438B725633E2100BE8F06 /* GlucoseTherapySettingInformationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseTherapySettingInformationView.swift; sourceTree = "<group>"; };
-		1D1A019D24B678BF0077D86E /* TherapySettingsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TherapySettingsView.swift; sourceTree = "<group>"; };
-		1D1FCE2224BD13A2000300A8 /* CorrectionRangeOverridesExpandableSetting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CorrectionRangeOverridesExpandableSetting.swift; sourceTree = "<group>"; };
-		1D1FCE2424BD42EF000300A8 /* TherapySettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TherapySettingsViewModel.swift; sourceTree = "<group>"; };
 		1D1FCE2624BE4DE2000300A8 /* CorrectionRangeOverrides.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CorrectionRangeOverrides.swift; sourceTree = "<group>"; };
 		1D1FCE2824BE4F11000300A8 /* TherapySetting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TherapySetting.swift; sourceTree = "<group>"; };
-		1D1FCE2A24BE704A000300A8 /* TherapySetting+Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TherapySetting+Settings.swift"; sourceTree = "<group>"; };
 		1D24A8D424C896E100AB8DB9 /* Prescription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Prescription.swift; sourceTree = "<group>"; };
 		1D25C22D246A2A1A00E87FA0 /* critical.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = critical.caf; sourceTree = "<group>"; };
 		1D498E4624D892B0000627F2 /* Environment+Authenticate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Environment+Authenticate.swift"; sourceTree = "<group>"; };
 		1D60355D24D39ED10095DC2A /* Environment+AppName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Environment+AppName.swift"; sourceTree = "<group>"; };
 		1D640FF524524284008F9755 /* sub.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = sub.caf; sourceTree = "<group>"; };
-		1D67E79C2563001800A82ED6 /* InformationScreens.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = InformationScreens.xcassets; sourceTree = "<group>"; };
-		1D6EAB9024C12C090081249D /* PumpSupportedIncrements.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PumpSupportedIncrements.swift; sourceTree = "<group>"; };
 		1D841AAC24577EE10069DBFF /* AlertSoundPlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertSoundPlayer.swift; sourceTree = "<group>"; };
 		1D97A33B256F11E00042737E /* View+InsetGroupedListStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+InsetGroupedListStyle.swift"; sourceTree = "<group>"; };
 		1DA649AA2445174400F61E75 /* Alert.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Alert.swift; sourceTree = "<group>"; };
 		1DABAD392453615200ACF708 /* IssueAlertTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueAlertTableViewController.swift; sourceTree = "<group>"; };
-		1DC64C7B24BF6BFD004A63A1 /* CorrectionRangeOverridesExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CorrectionRangeOverridesExtension.swift; sourceTree = "<group>"; };
 		1DC64C7D24BF6EBC004A63A1 /* DeliveryLimits.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeliveryLimits.swift; sourceTree = "<group>"; };
 		1DC9240E2575EF9A004F132A /* QuantityFormatter+Guardrails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "QuantityFormatter+Guardrails.swift"; sourceTree = "<group>"; };
 		1DD1964D248AE88000420876 /* HorizontalSizeClassOverride.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HorizontalSizeClassOverride.swift; sourceTree = "<group>"; };
@@ -983,7 +938,6 @@
 		1DECC3F42513F98D00F4056E /* UITextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITextField.swift; sourceTree = "<group>"; };
 		1DEE230124A676A300693C32 /* LoopKitHostedTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LoopKitHostedTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
 		1DEE230224A676A300693C32 /* LoopKitHostedTests.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = LoopKitHostedTests.plist; sourceTree = "<group>"; };
-		1DEF977424C62F8400D630CB /* SupportedInsulinModelSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupportedInsulinModelSettings.swift; sourceTree = "<group>"; };
 		1DFB99D5245CB2E900DCC8C9 /* AlertTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertTests.swift; sourceTree = "<group>"; };
 		1F50C321212B20D300C18FAB /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/CarbKit.strings; sourceTree = "<group>"; };
 		1F50C322212B20D300C18FAB /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/InsulinKit.strings; sourceTree = "<group>"; };
@@ -1354,13 +1308,10 @@
 		89627B15244115A400BEB424 /* CardList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardList.swift; sourceTree = "<group>"; };
 		89627B172441168900BEB424 /* ConfigurationPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationPage.swift; sourceTree = "<group>"; };
 		89653C7F2473527100E1BAA5 /* FractionalQuantityPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FractionalQuantityPicker.swift; sourceTree = "<group>"; };
-		89653C812473592600E1BAA5 /* CarbRatioScheduleEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarbRatioScheduleEditor.swift; sourceTree = "<group>"; };
-		89653C8324738D2B00E1BAA5 /* BasalRateScheduleEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasalRateScheduleEditor.swift; sourceTree = "<group>"; };
 		8974AFBF22120D7A0043F01B /* TemporaryScheduleOverrideTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TemporaryScheduleOverrideTests.swift; sourceTree = "<group>"; };
 		8974B0672215FE460043F01B /* Collection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Collection.swift; sourceTree = "<group>"; };
 		898B4E74246CCAB50053C484 /* Binding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Binding.swift; sourceTree = "<group>"; };
 		898B4E76246DAE280053C484 /* GlucoseRangePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseRangePicker.swift; sourceTree = "<group>"; };
-		898B4E7A246DC6A70053C484 /* CorrectionRangeScheduleEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CorrectionRangeScheduleEditor.swift; sourceTree = "<group>"; };
 		898B4E7D246DEB920053C484 /* GuardrailConstrainedQuantityRangeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GuardrailConstrainedQuantityRangeView.swift; sourceTree = "<group>"; };
 		898C896924D4BF11002FA994 /* Guardrail+Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Guardrail+Settings.swift"; sourceTree = "<group>"; };
 		898C896C24D4BF75002FA994 /* FloatingPoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingPoint.swift; sourceTree = "<group>"; };
@@ -1438,10 +1389,7 @@
 		89F6E310244A1AAB00CB9E15 /* SettingDescription.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingDescription.swift; sourceTree = "<group>"; };
 		89F6E312244A1AB500CB9E15 /* GuardrailWarning.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GuardrailWarning.swift; sourceTree = "<group>"; };
 		89F6E313244A1AB600CB9E15 /* GlucoseValuePicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlucoseValuePicker.swift; sourceTree = "<group>"; };
-		89FC688A245A2D670075CF59 /* InsulinSensitivityScheduleEditor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InsulinSensitivityScheduleEditor.swift; sourceTree = "<group>"; };
-		89FC688B245A2D670075CF59 /* QuantityScheduleEditor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuantityScheduleEditor.swift; sourceTree = "<group>"; };
 		89FC688C245A2D680075CF59 /* ScheduleItemPicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScheduleItemPicker.swift; sourceTree = "<group>"; };
-		89FC688D245A2D680075CF59 /* ScheduleEditor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScheduleEditor.swift; sourceTree = "<group>"; };
 		89FC688E245A2D680075CF59 /* ScheduleItemView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScheduleItemView.swift; sourceTree = "<group>"; };
 		9E78433E236653F00016C583 /* ice_35_min_none_piecewiselinear_output.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = ice_35_min_none_piecewiselinear_output.json; sourceTree = "<group>"; };
 		9E784340236656770016C583 /* ice_35_min_partial_piecewiselinear_output.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = ice_35_min_partial_piecewiselinear_output.json; sourceTree = "<group>"; };
@@ -1577,30 +1525,14 @@
 		C1E84B8425C62FB100623C08 /* Modelv1v4.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = Modelv1v4.xcmappingmodel; sourceTree = "<group>"; };
 		C1F8403723DB84B700673141 /* DeviceLogEntry+CoreDataClass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DeviceLogEntry+CoreDataClass.swift"; sourceTree = "<group>"; };
 		C1F8403823DB84B700673141 /* DeviceLogEntry+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DeviceLogEntry+CoreDataProperties.swift"; sourceTree = "<group>"; };
-		E9077D2624ACD59F0066A88D /* InformationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InformationView.swift; sourceTree = "<group>"; };
-		E9077D2924ACDE2C0066A88D /* CorrectionRangeInformationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CorrectionRangeInformationView.swift; sourceTree = "<group>"; };
-		E9086B2824B39EDC0062F5C8 /* ChartsTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartsTableViewController.swift; sourceTree = "<group>"; };
-		E9086B2C24B3A4AC0062F5C8 /* ChartsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartsManager.swift; sourceTree = "<group>"; };
 		E9086B2E24B3A5080062F5C8 /* ChartColorPalette.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartColorPalette.swift; sourceTree = "<group>"; };
 		E9086B3024B3A7270062F5C8 /* ChartTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartTableViewCell.swift; sourceTree = "<group>"; };
 		E9086B3424B3A8820062F5C8 /* ChartContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartContainerView.swift; sourceTree = "<group>"; };
 		E9086B3824B3CB4B0062F5C8 /* TherapySettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TherapySettings.swift; sourceTree = "<group>"; };
-		E9086B4424B53CC50062F5C8 /* GlucoseChart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseChart.swift; sourceTree = "<group>"; };
-		E9086B4724B5405E0062F5C8 /* ChartAxisValueDoubleUnit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartAxisValueDoubleUnit.swift; sourceTree = "<group>"; };
 		E9086B4924B540B70062F5C8 /* DateFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateFormatter.swift; sourceTree = "<group>"; };
-		E916F56824AD32F000BE3547 /* CorrectionRangeOverridesEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CorrectionRangeOverridesEditor.swift; sourceTree = "<group>"; };
-		E916F56E24AE2FFE00BE3547 /* CorrectionRangeOverrideInformationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CorrectionRangeOverrideInformationView.swift; sourceTree = "<group>"; };
-		E92094EE257C5FFB004D6192 /* SettingsPresentationMode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsPresentationMode.swift; sourceTree = "<group>"; };
 		E9291366257D71880014116A /* Modelv4.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Modelv4.xcdatamodel; sourceTree = "<group>"; };
 		E93BA06524A39DBC00C5D7E6 /* DismissibleHostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DismissibleHostingController.swift; sourceTree = "<group>"; };
-		E93C869F24C8F6E00073089B /* InsulinModelSelection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InsulinModelSelection.swift; sourceTree = "<group>"; };
-		E93C86A124C8F7550073089B /* InsulinModelChart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InsulinModelChart.swift; sourceTree = "<group>"; };
-		E93C86A324C8F79C0073089B /* ChartLineModel+LoopKitUI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ChartLineModel+LoopKitUI.swift"; sourceTree = "<group>"; };
-		E93C86A524C8F7D90073089B /* ChartSettings+LoopKitUI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ChartSettings+LoopKitUI.swift"; sourceTree = "<group>"; };
-		E93C86A724C8F7F60073089B /* InsulinModelChartView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InsulinModelChartView.swift; sourceTree = "<group>"; };
 		E93C86AF24CF7C470073089B /* TherapySettingsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TherapySettingsTests.swift; sourceTree = "<group>"; };
-		E93C86B124D080E00073089B /* CarbRatioInformationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarbRatioInformationView.swift; sourceTree = "<group>"; };
-		E93C86B524D08CAD0073089B /* InsulinSensitivityInformationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InsulinSensitivityInformationView.swift; sourceTree = "<group>"; };
 		E93E865924DC744300FF40C8 /* effect_from_basal_output_exponential.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = effect_from_basal_output_exponential.json; sourceTree = "<group>"; };
 		E93E865B24DC75EF00FF40C8 /* basal_dose_with_expired.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = basal_dose_with_expired.json; sourceTree = "<group>"; };
 		E93E865D24DC797A00FF40C8 /* basal_dose_with_delivered.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = basal_dose_with_delivered.json; sourceTree = "<group>"; };
@@ -1608,13 +1540,7 @@
 		E93E866124DC87AE00FF40C8 /* effect_from_history_exponential_delivered_units_output.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = effect_from_history_exponential_delivered_units_output.json; sourceTree = "<group>"; };
 		E93E866324DCFB6D00FF40C8 /* OverrideHistoryCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverrideHistoryCollectionViewCell.swift; sourceTree = "<group>"; };
 		E93E866924DD05FA00FF40C8 /* OverrideSelectionHistory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OverrideSelectionHistory.swift; sourceTree = "<group>"; };
-		E94141CF24C8F31C0096C326 /* DeliveryLimitsEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeliveryLimitsEditor.swift; sourceTree = "<group>"; };
-		E949E38824AFC82F00024DA0 /* DeliveryLimitsInformationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeliveryLimitsInformationView.swift; sourceTree = "<group>"; };
-		E949E38E24B3711E00024DA0 /* InsulinModelInformationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InsulinModelInformationView.swift; sourceTree = "<group>"; };
 		E96175AD24B7BE38008E5080 /* Dictionary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dictionary.swift; sourceTree = "<group>"; };
-		E96DCB5724AEF50F007117BC /* SuspendThresholdInformationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuspendThresholdInformationView.swift; sourceTree = "<group>"; };
-		E96DCB5924AF74AC007117BC /* SuspendThresholdEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuspendThresholdEditor.swift; sourceTree = "<group>"; };
-		E96DCB5D24AF7DC7007117BC /* BasalRatesInformationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasalRatesInformationView.swift; sourceTree = "<group>"; };
 		E99A132D2557548300D3F5B3 /* SegmentedGaugeBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegmentedGaugeBar.swift; sourceTree = "<group>"; };
 		E9C58A6D24DA65E400487A17 /* HistoricalOverrideDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoricalOverrideDetailView.swift; sourceTree = "<group>"; };
 		E9C6911725180A4E009F9999 /* Modelv3.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Modelv3.xcdatamodel; sourceTree = "<group>"; };
@@ -1855,8 +1781,6 @@
 				89CCD4F921A911510068C3FB /* PercentageTextFieldTableViewController.swift */,
 				895695F521AA413B00828067 /* DateAndDurationTableViewController.swift */,
 				E93BA06524A39DBC00C5D7E6 /* DismissibleHostingController.swift */,
-				E9086B2824B39EDC0062F5C8 /* ChartsTableViewController.swift */,
-				E9086B2C24B3A4AC0062F5C8 /* ChartsManager.swift */,
 				E9C58A6D24DA65E400487A17 /* HistoricalOverrideDetailView.swift */,
 			);
 			path = "View Controllers";
@@ -1939,7 +1863,6 @@
 				B4C004B4241085DC00B40429 /* GuideNavigationButton.swift */,
 				B4C004B3241085DB00B40429 /* GuidePage.swift */,
 				892A5DAD2231E185008961AB /* HUDAssets.xcassets */,
-				E9077D2824ACD5AA0066A88D /* Information Screens */,
 				B46B62A623FEFE4D001E69BA /* InstructionList.swift */,
 				892155162245FBEF009112BC /* InsulinSensitivityScalingTableViewCell.swift */,
 				892155172245FBEF009112BC /* InsulinSensitivityScalingTableViewCell.xib */,
@@ -1967,13 +1890,11 @@
 				C1E4B304242E98E900E70CCB /* ProgressIndicatorView.swift */,
 				C1E4B303242E98E900E70CCB /* ProgressView.swift */,
 				89AC9DCA24529927004A6B8A /* QuantityPicker.swift */,
-				89FC688B245A2D670075CF59 /* QuantityScheduleEditor.swift */,
 				43D8FE0A1C7290530073BE78 /* RepeatingScheduleValueTableViewCell.swift */,
 				43D8FE0B1C7290530073BE78 /* RepeatingScheduleValueTableViewCell.xib */,
 				892A5DB62231E19F008961AB /* ReservoirVolumeHUDView.swift */,
 				892A5DB52231E19F008961AB /* ReservoirVolumeHUDView.xib */,
 				89BE75C224649C4C00B145D9 /* RoundedCorners.swift */,
-				89FC688D245A2D680075CF59 /* ScheduleEditor.swift */,
 				89FC688C245A2D680075CF59 /* ScheduleItemPicker.swift */,
 				89FC688E245A2D680075CF59 /* ScheduleItemView.swift */,
 				B46B62AE23FF0BF6001E69BA /* SectionHeader.swift */,
@@ -1985,7 +1906,6 @@
 				892A5D63222F6B13008961AB /* SetConstrainedScheduleEntryTableViewCell.swift */,
 				892A5D62222F6B13008961AB /* SetConstrainedScheduleEntryTableViewCell.xib */,
 				89F6E310244A1AAB00CB9E15 /* SettingDescription.swift */,
-				E916F56724AD31F900BE3547 /* Settings Editors */,
 				432CF86620D76AB90066B889 /* SettingsTableViewCell.swift */,
 				432CF86820D76B320066B889 /* SetupButton.swift */,
 				432CF86A20D76B9C0066B889 /* SetupIndicatorView.swift */,
@@ -2060,7 +1980,6 @@
 			isa = PBXGroup;
 			children = (
 				E9086B4624B5404D0062F5C8 /* Models */,
-				E9086B4324B53CB40062F5C8 /* Charts */,
 				B41A60B023D1DBB700636320 /* Extensions */,
 				43177D091D3732C70006E908 /* Assets.xcassets */,
 				43BA7160201E48910058961E /* CarbKit */,
@@ -2618,8 +2537,6 @@
 			isa = PBXGroup;
 			children = (
 				898B4E74246CCAB50053C484 /* Binding.swift */,
-				E93C86A324C8F79C0073089B /* ChartLineModel+LoopKitUI.swift */,
-				E93C86A524C8F7D90073089B /* ChartSettings+LoopKitUI.swift */,
 				E9086B4924B540B70062F5C8 /* DateFormatter.swift */,
 				E96175AD24B7BE38008E5080 /* Dictionary.swift */,
 				1D60355D24D39ED10095DC2A /* Environment+AppName.swift */,
@@ -2690,66 +2607,14 @@
 			path = DeviceLog;
 			sourceTree = "<group>";
 		};
-		E9077D2824ACD5AA0066A88D /* Information Screens */ = {
-			isa = PBXGroup;
-			children = (
-				1D67E79C2563001800A82ED6 /* InformationScreens.xcassets */,
-				E96DCB5D24AF7DC7007117BC /* BasalRatesInformationView.swift */,
-				E93C86B124D080E00073089B /* CarbRatioInformationView.swift */,
-				E9077D2924ACDE2C0066A88D /* CorrectionRangeInformationView.swift */,
-				E916F56E24AE2FFE00BE3547 /* CorrectionRangeOverrideInformationView.swift */,
-				E949E38824AFC82F00024DA0 /* DeliveryLimitsInformationView.swift */,
-				E9077D2624ACD59F0066A88D /* InformationView.swift */,
-				E949E38E24B3711E00024DA0 /* InsulinModelInformationView.swift */,
-				E93C86B524D08CAD0073089B /* InsulinSensitivityInformationView.swift */,
-				E96DCB5724AEF50F007117BC /* SuspendThresholdInformationView.swift */,
-				1D1438B725633E2100BE8F06 /* GlucoseTherapySettingInformationView.swift */,
-			);
-			path = "Information Screens";
-			sourceTree = "<group>";
-		};
-		E9086B4324B53CB40062F5C8 /* Charts */ = {
-			isa = PBXGroup;
-			children = (
-				E9086B4424B53CC50062F5C8 /* GlucoseChart.swift */,
-				E93C86A124C8F7550073089B /* InsulinModelChart.swift */,
-			);
-			path = Charts;
-			sourceTree = "<group>";
-		};
 		E9086B4624B5404D0062F5C8 /* Models */ = {
 			isa = PBXGroup;
 			children = (
-				E9086B4724B5405E0062F5C8 /* ChartAxisValueDoubleUnit.swift */,
 				B43DA43E24D49AA400CAFF4E /* GuidanceColors.swift */,
 			);
 			path = Models;
 			sourceTree = "<group>";
 		};
-		E916F56724AD31F900BE3547 /* Settings Editors */ = {
-			isa = PBXGroup;
-			children = (
-				89653C8324738D2B00E1BAA5 /* BasalRateScheduleEditor.swift */,
-				89653C812473592600E1BAA5 /* CarbRatioScheduleEditor.swift */,
-				E916F56824AD32F000BE3547 /* CorrectionRangeOverridesEditor.swift */,
-				1D1FCE2224BD13A2000300A8 /* CorrectionRangeOverridesExpandableSetting.swift */,
-				1DC64C7B24BF6BFD004A63A1 /* CorrectionRangeOverridesExtension.swift */,
-				898B4E7A246DC6A70053C484 /* CorrectionRangeScheduleEditor.swift */,
-				E94141CF24C8F31C0096C326 /* DeliveryLimitsEditor.swift */,
-				89FC688A245A2D670075CF59 /* InsulinSensitivityScheduleEditor.swift */,
-				E93C86A724C8F7F60073089B /* InsulinModelChartView.swift */,
-				1D6EAB9024C12C090081249D /* PumpSupportedIncrements.swift */,
-				E92094EE257C5FFB004D6192 /* SettingsPresentationMode.swift */,
-				1DEF977424C62F8400D630CB /* SupportedInsulinModelSettings.swift */,
-				E96DCB5924AF74AC007117BC /* SuspendThresholdEditor.swift */,
-				1D1FCE2A24BE704A000300A8 /* TherapySetting+Settings.swift */,
-				1D1A019D24B678BF0077D86E /* TherapySettingsView.swift */,
-				1D1FCE2424BD42EF000300A8 /* TherapySettingsViewModel.swift */,
-				E93C869F24C8F6E00073089B /* InsulinModelSelection.swift */,
-			);
-			path = "Settings Editors";
-			sourceTree = "<group>";
-		};
 		E9D95F9C24C8BC880079F47D /* Scripts */ = {
 			isa = PBXGroup;
 			children = (
@@ -3137,7 +3002,6 @@
 				892A5DAE2231E185008961AB /* HUDAssets.xcassets in Resources */,
 				43BA719720203EF30058961E /* CarbKit.storyboard in Resources */,
 				43BA7173201E492E0058961E /* DateAndDurationTableViewCell.xib in Resources */,
-				1D67E79D2563001800A82ED6 /* InformationScreens.xcassets in Resources */,
 				43BA7164201E49130058961E /* InsulinKit.storyboard in Resources */,
 				895FE08A22011F0C00FCF18A /* LabeledTextFieldTableViewCell.xib in Resources */,
 				892155192245FBEF009112BC /* InsulinSensitivityScalingTableViewCell.xib in Resources */,
@@ -3421,7 +3285,6 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				1D1438B825633E2100BE8F06 /* GlucoseTherapySettingInformationView.swift in Sources */,
 				898E6E6E2241ED9F0019E459 /* SuspendResumeTableViewCell.swift in Sources */,
 				B4C004D12416961300B40429 /* GuidePage.swift in Sources */,
 				898B4E7E246DEB920053C484 /* GuardrailConstrainedQuantityRangeView.swift in Sources */,
@@ -3432,7 +3295,6 @@
 				898B4E75246CCAB50053C484 /* Binding.swift in Sources */,
 				892155182245FBEF009112BC /* InsulinSensitivityScalingTableViewCell.swift in Sources */,
 				892155132245C516009112BC /* SegmentedGaugeBarView.swift in Sources */,
-				E9077D2A24ACDE2C0066A88D /* CorrectionRangeInformationView.swift in Sources */,
 				1D498E4724D892B0000627F2 /* Environment+Authenticate.swift in Sources */,
 				B4A2AAB3240832350066563F /* MultipleSelectionList.swift in Sources */,
 				B46B62AB23FF0822001E69BA /* LabeledValueView.swift in Sources */,
@@ -3450,10 +3312,8 @@
 				43F5034F210599DF009FA89A /* ValidatingIndicatorView.swift in Sources */,
 				C1E4B308242E995200E70CCB /* ActivityIndicator.swift in Sources */,
 				89FC6891245A2D680075CF59 /* ScheduleItemPicker.swift in Sources */,
-				1D1FCE2524BD42EF000300A8 /* TherapySettingsViewModel.swift in Sources */,
 				43BA718C201EEE5A0058961E /* NSData.swift in Sources */,
 				43F5035A21059AF7009FA89A /* AuthenticationTableViewCell.swift in Sources */,
-				E916F56924AD32F000BE3547 /* CorrectionRangeOverridesEditor.swift in Sources */,
 				C1E4B30A242E99A800E70CCB /* Image.swift in Sources */,
 				43BA718A201EE8CF0058961E /* NSTimeInterval.swift in Sources */,
 				B4A2AAB1240830A30066563F /* LabeledTextField.swift in Sources */,
@@ -3461,17 +3321,12 @@
 				B46B62A923FF05F8001E69BA /* LabeledNumberInput.swift in Sources */,
 				892155152245C57E009112BC /* SegmentedGaugeBarLayer.swift in Sources */,
 				C1DD512B259FD8A600DE27AE /* InsulinTypeChooser.swift in Sources */,
-				E9086B2D24B3A4AC0062F5C8 /* ChartsManager.swift in Sources */,
-				E9086B4824B5405E0062F5C8 /* ChartAxisValueDoubleUnit.swift in Sources */,
 				B429D66C24BF7204003E1B4A /* GlucoseTrend.swift in Sources */,
 				432CF86720D76AB90066B889 /* SettingsTableViewCell.swift in Sources */,
-				898B4E7B246DC6A70053C484 /* CorrectionRangeScheduleEditor.swift in Sources */,
 				898E6E6A224179530019E459 /* BasalScheduleTableViewController.swift in Sources */,
 				E9E5E56A24D5CCE800B5DFFE /* OverrideViewCell.swift in Sources */,
 				892A5DB42231E191008961AB /* LevelMaskView.swift in Sources */,
 				892A5DA02231E130008961AB /* CompletionNotifying.swift in Sources */,
-				E93C86A424C8F79C0073089B /* ChartLineModel+LoopKitUI.swift in Sources */,
-				E949E38F24B3711E00024DA0 /* InsulinModelInformationView.swift in Sources */,
 				895FE08B22011F0C00FCF18A /* EmojiInputHeaderView.swift in Sources */,
 				43BA7170201E49220058961E /* FoodTypeShortcutCell.swift in Sources */,
 				432CF86520D7692E0066B889 /* DeliveryLimitSettingsTableViewController.swift in Sources */,
@@ -3481,8 +3336,6 @@
 				89BE75C524649C8100B145D9 /* NewScheduleItemEditor.swift in Sources */,
 				89CAB36F24C9ECCA009EE3CE /* View+KeyboardAware.swift in Sources */,
 				E9086B2F24B3A5080062F5C8 /* ChartColorPalette.swift in Sources */,
-				89653C822473592600E1BAA5 /* CarbRatioScheduleEditor.swift in Sources */,
-				1D1FCE2B24BE704A000300A8 /* TherapySetting+Settings.swift in Sources */,
 				4369F08F208859E6000E3E45 /* PaddedTextField.swift in Sources */,
 				A9498D8823386CAF00DAA9B9 /* ServiceViewController.swift in Sources */,
 				892A5D9E2231E122008961AB /* StateColorPalette.swift in Sources */,
@@ -3492,7 +3345,6 @@
 				C1DE4C2125A253BD007065F8 /* Color.swift in Sources */,
 				898E6E702241EDB70019E459 /* PercentageTextFieldTableViewController.swift in Sources */,
 				89CAB36D24C9EC98009EE3CE /* Keyboard.swift in Sources */,
-				1DEF977524C62F8400D630CB /* SupportedInsulinModelSettings.swift in Sources */,
 				89186C0724BF7FC70003D0F3 /* Guardrail+UI.swift in Sources */,
 				432CF87420D774520066B889 /* NumberFormatter.swift in Sources */,
 				1F5DAB212118C95700048054 /* LocalizedString.swift in Sources */,
@@ -3500,23 +3352,17 @@
 				43BA7180201EE7090058961E /* SingleValueScheduleTableViewController.swift in Sources */,
 				E9DFB92C24E634E800468917 /* ExpandablePicker.swift in Sources */,
 				898E6E5D2241783C0019E459 /* SetConstrainedScheduleEntryTableViewCell.swift in Sources */,
-				89FC688F245A2D680075CF59 /* InsulinSensitivityScheduleEditor.swift in Sources */,
-				E96DCB5E24AF7DC7007117BC /* BasalRatesInformationView.swift in Sources */,
 				895FE09322011F4800FCF18A /* EmojiInputController.swift in Sources */,
 				43BA717E201EE7090058961E /* CommandResponseViewController.swift in Sources */,
 				C188B83422CC16AC0051760A /* InsulinSensitivityScheduleViewController.swift in Sources */,
 				43BA717A201E4F1D0058961E /* IdentifiableClass.swift in Sources */,
 				895FE08822011F0C00FCF18A /* DoubleRangeTableViewCell.swift in Sources */,
-				E9086B2924B39EDC0062F5C8 /* ChartsTableViewController.swift in Sources */,
 				43BA7187201EE7090058961E /* GlucoseRangeScheduleTableViewController.swift in Sources */,
 				B46B62AF23FF0BF6001E69BA /* SectionHeader.swift in Sources */,
 				43BA7183201EE7090058961E /* DailyQuantityScheduleTableViewController.swift in Sources */,
-				1D1FCE2324BD13A2000300A8 /* CorrectionRangeOverridesExpandableSetting.swift in Sources */,
 				E93BA06624A39DBC00C5D7E6 /* DismissibleHostingController.swift in Sources */,
 				43F503632106C761009FA89A /* ServiceAuthenticationUI.swift in Sources */,
-				1D6EAB9124C12C090081249D /* PumpSupportedIncrements.swift in Sources */,
 				899012C1246F1D8F007B88BA /* ExpandableSetting.swift in Sources */,
-				89FC6890245A2D680075CF59 /* QuantityScheduleEditor.swift in Sources */,
 				432CF86B20D76B9C0066B889 /* SetupIndicatorView.swift in Sources */,
 				898E6E722241EDC10019E459 /* DateAndDurationTableViewController.swift in Sources */,
 				43BA716D201E49220058961E /* DatePickerTableViewCell.swift in Sources */,
@@ -3524,8 +3370,6 @@
 				895FE08222011F0C00FCF18A /* LabeledTextFieldTableViewCell.swift in Sources */,
 				B43DA44224D9CD8500CAFF4E /* Environment+Colors.swift in Sources */,
 				892A5DB22231E191008961AB /* LoadingTableViewCell.swift in Sources */,
-				E96DCB5A24AF74AC007117BC /* SuspendThresholdEditor.swift in Sources */,
-				E96DCB5824AEF50F007117BC /* SuspendThresholdInformationView.swift in Sources */,
 				4369F094208BA001000E3E45 /* TextButtonTableViewCell.swift in Sources */,
 				89AC9DCD24529D9B004A6B8A /* TimePicker.swift in Sources */,
 				A9498D8B23386CC700DAA9B9 /* ServiceUI.swift in Sources */,
@@ -3536,17 +3380,12 @@
 				B46B62B323FF0E62001E69BA /* SelectableLabel.swift in Sources */,
 				89FC6893245A2D680075CF59 /* ScheduleItemView.swift in Sources */,
 				43BA716F201E49220058961E /* FoodEmojiDataSource.swift in Sources */,
-				E9077D2724ACD59F0066A88D /* InformationView.swift in Sources */,
-				E94141D024C8F31C0096C326 /* DeliveryLimitsEditor.swift in Sources */,
 				43F89C9F22BDFB10006BB54E /* UIActivityIndicatorView.swift in Sources */,
 				C1DD517825A016E700DE27AE /* InsulinTypeSetting.swift in Sources */,
 				892ADE002446C858007CE08C /* Card.swift in Sources */,
-				89653C8424738D2B00E1BAA5 /* BasalRateScheduleEditor.swift in Sources */,
 				898B4E77246DAE280053C484 /* GlucoseRangePicker.swift in Sources */,
 				432CF86D20D76C470066B889 /* SwitchTableViewCell.swift in Sources */,
-				E93C86A824C8F7F70073089B /* InsulinModelChartView.swift in Sources */,
 				43BA7188201EE85B0058961E /* HKUnit.swift in Sources */,
-				E93C86B224D080E00073089B /* CarbRatioInformationView.swift in Sources */,
 				89F6E30D2449713600CB9E15 /* CardStack.swift in Sources */,
 				89BE75C324649C4C00B145D9 /* RoundedCorners.swift in Sources */,
 				C1E4B306242E98E900E70CCB /* ProgressIndicatorView.swift in Sources */,
@@ -3559,7 +3398,6 @@
 				1DD1964E248AE88000420876 /* HorizontalSizeClassOverride.swift in Sources */,
 				892A5D9C2231E118008961AB /* UIAlertController.swift in Sources */,
 				43BA7181201EE7090058961E /* RepeatingScheduleValueTableViewCell.swift in Sources */,
-				1DC64C7C24BF6BFD004A63A1 /* CorrectionRangeOverridesExtension.swift in Sources */,
 				43BA716E201E49220058961E /* DecimalTextFieldTableViewCell.swift in Sources */,
 				891A3FC72247268F00378B27 /* Math.swift in Sources */,
 				895FE08722011F0C00FCF18A /* EmojiInputCell.swift in Sources */,
@@ -3567,10 +3405,8 @@
 				43A8EC3C210CEEA500A81379 /* CGMManagerUI.swift in Sources */,
 				43BA718B201EE93C0058961E /* TimeZone.swift in Sources */,
 				A991161423426A0A00A4B2E9 /* ServiceSetupNotifying.swift in Sources */,
-				89FC6892245A2D680075CF59 /* ScheduleEditor.swift in Sources */,
 				89CAB37124CB4DEC009EE3CE /* WarningView.swift in Sources */,
 				43BA717B201EE6A40058961E /* NibLoadable.swift in Sources */,
-				E916F56F24AE2FFE00BE3547 /* CorrectionRangeOverrideInformationView.swift in Sources */,
 				89BE75C124649C2E00B145D9 /* ModalHeaderButtonBar.swift in Sources */,
 				89186C0524BEC9CA0003D0F3 /* SegmentedControlTableViewCell.swift in Sources */,
 				89F6E315244A1AB600CB9E15 /* GlucoseValuePicker.swift in Sources */,
@@ -3585,8 +3421,6 @@
 				895FE09022011F4800FCF18A /* OverrideSelectionViewController.swift in Sources */,
 				89904032245B5CA500F1C0A2 /* Deletable.swift in Sources */,
 				43F5035721059A8A009FA89A /* ServiceCredential.swift in Sources */,
-				E93C86A224C8F7550073089B /* InsulinModelChart.swift in Sources */,
-				E93C86B624D08CAD0073089B /* InsulinSensitivityInformationView.swift in Sources */,
 				43BA7169201E49220058961E /* CarbEntryEditViewController.swift in Sources */,
 				892A5DA22231E137008961AB /* HUDProvider.swift in Sources */,
 				892A5DBC2231E20C008961AB /* Comparable.swift in Sources */,
@@ -3594,13 +3428,9 @@
 				43BA717D201EE7090058961E /* GlucoseRangeTableViewCell.swift in Sources */,
 				89BE75CB2464BC2000B145D9 /* AlertContent.swift in Sources */,
 				43BA7184201EE7090058961E /* TextFieldTableViewController.swift in Sources */,
-				1D1A019E24B678BF0077D86E /* TherapySettingsView.swift in Sources */,
-				E93C86A024C8F6E00073089B /* InsulinModelSelection.swift in Sources */,
-				E92094EF257C5FFB004D6192 /* SettingsPresentationMode.swift in Sources */,
 				895FE09122011F4800FCF18A /* AddEditOverrideTableViewController.swift in Sources */,
 				C1E4B305242E98E900E70CCB /* ProgressView.swift in Sources */,
 				C16DA84522E9330A008624C2 /* LoopUIPlugin.swift in Sources */,
-				E93C86A624C8F7D90073089B /* ChartSettings+LoopKitUI.swift in Sources */,
 				B46B62AD23FF0A87001E69BA /* LabeledDateView.swift in Sources */,
 				895FE06E22011E9A00FCF18A /* OverrideEmojiDataSource.swift in Sources */,
 				43BA716A201E49220058961E /* CarbEntryTableViewController.swift in Sources */,
@@ -3618,13 +3448,11 @@
 				892A5D9A2231E0E4008961AB /* SettingsNavigationViewController.swift in Sources */,
 				B46B62B123FF0CA6001E69BA /* DescriptiveText.swift in Sources */,
 				B40D07CB251BD89D00C1C6D7 /* DateAndDurationSteppableTableViewCell.swift in Sources */,
-				E949E38924AFC82F00024DA0 /* DeliveryLimitsInformationView.swift in Sources */,
 				1DC9240F2575EF9A004F132A /* QuantityFormatter+Guardrails.swift in Sources */,
 				89CAB36B24C9EC25009EE3CE /* DismissibleKeyboardTextField.swift in Sources */,
 				E9086B4A24B540B70062F5C8 /* DateFormatter.swift in Sources */,
 				89AC9DCB24529927004A6B8A /* QuantityPicker.swift in Sources */,
 				1D096BFA24C242300078B6B5 /* CheckmarkListItem.swift in Sources */,
-				E9086B4524B53CC50062F5C8 /* GlucoseChart.swift in Sources */,
 				1DECC3F52513F98D00F4056E /* UITextField.swift in Sources */,
 				B4C004D22416961300B40429 /* GuideNavigationButton.swift in Sources */,
 				89627B16244115A400BEB424 /* CardList.swift in Sources */,

+ 0 - 57
Dependecies/LoopKit/LoopKitUI/Charts/GlucoseChart.swift

@@ -1,57 +0,0 @@
-//
-//  GlucoseChart.swift
-//  LoopUI
-//
-//  Copyright © 2019 LoopKit Authors. All rights reserved.
-//
-
-import Foundation
-import HealthKit
-import LoopKit
-import SwiftCharts
-
-
-open class GlucoseChart {
-    public init() {
-    }
-
-    public var glucoseUnit: HKUnit = .milligramsPerDeciliter {
-        didSet {
-            if glucoseUnit != oldValue {
-                // Regenerate the glucose display points
-                let oldRange = glucoseDisplayRange
-                glucoseDisplayRange = oldRange
-            }
-        }
-    }
-
-    public var glucoseDisplayRange: ClosedRange<HKQuantity>? {
-        didSet {
-            if let range = glucoseDisplayRange {
-                glucoseDisplayRangePoints = [
-                    ChartPoint(x: ChartAxisValue(scalar: 0), y: ChartAxisValueDouble(range.lowerBound.doubleValue(for: glucoseUnit))),
-                    ChartPoint(x: ChartAxisValue(scalar: 0), y: ChartAxisValueDouble(range.upperBound.doubleValue(for: glucoseUnit)))
-                ]
-            } else {
-                glucoseDisplayRangePoints = []
-            }
-        }
-    }
-
-    public private(set) var glucoseDisplayRangePoints: [ChartPoint] = []
-
-    public func glucosePointsFromValues(_ glucoseValues: [GlucoseValue]) -> [ChartPoint] {
-        let unitFormatter = QuantityFormatter()
-        unitFormatter.unitStyle = .short
-        unitFormatter.setPreferredNumberFormatter(for: glucoseUnit)
-        let unitString = unitFormatter.string(from: glucoseUnit)
-        let dateFormatter = DateFormatter(timeStyle: .short)
-
-        return glucoseValues.map {
-            return ChartPoint(
-                x: ChartAxisValueDate(date: $0.startDate, formatter: dateFormatter),
-                y: ChartAxisValueDoubleUnit($0.quantity.doubleValue(for: glucoseUnit), unitString: unitString, formatter: unitFormatter.numberFormatter)
-            )
-        }
-    }
-}

+ 0 - 140
Dependecies/LoopKit/LoopKitUI/Charts/InsulinModelChart.swift

@@ -1,140 +0,0 @@
-//
-//  InsulinModelChart.swift
-//  LoopKitUI
-//
-//  Copyright © 2019 LoopKit Authors. All rights reserved.
-//
-
-import Foundation
-import LoopKit
-import SwiftCharts
-
-
-public class InsulinModelChart: GlucoseChart, ChartProviding {
-    /// The chart points for the selected model
-    public private(set) var selectedInsulinModelChartPoints: [ChartPoint] = [] {
-        didSet {
-            if let lastDate = selectedInsulinModelChartPoints.last?.x as? ChartAxisValueDate {
-                updateEndDate(lastDate.date)
-            }
-        }
-    }
-
-    public private(set) var unselectedInsulinModelChartPoints: [[ChartPoint]] = [] {
-        didSet {
-            for points in unselectedInsulinModelChartPoints {
-                if let lastDate = points.last?.x as? ChartAxisValueDate {
-                    updateEndDate(lastDate.date)
-                }
-            }
-        }
-    }
-
-    public private(set) var endDate: Date?
-
-    private func updateEndDate(_ date: Date) {
-        if endDate == nil || date > endDate! {
-            self.endDate = date
-        }
-    }
-}
-
-extension InsulinModelChart {
-    public func didReceiveMemoryWarning() {
-
-    }
-
-    public func generate(withFrame frame: CGRect, xAxisModel: ChartAxisModel, xAxisValues: [ChartAxisValue], axisLabelSettings: ChartLabelSettings, guideLinesLayerSettings: ChartGuideLinesLayerSettings, colors: ChartColorPalette, chartSettings: ChartSettings, labelsWidthY: CGFloat, gestureRecognizer: UIGestureRecognizer?, traitCollection: UITraitCollection) -> Chart
-    {
-        let yAxisValues = ChartAxisValuesStaticGenerator.generateYAxisValuesWithChartPoints(glucoseDisplayRangePoints,
-            minSegmentCount: 2,
-            maxSegmentCount: 5,
-            multiple: glucoseUnit.chartableIncrement / 2,
-            axisValueGenerator: {
-                ChartAxisValueDouble(round($0), labelSettings: axisLabelSettings)
-            },
-            addPaddingSegmentIfEdge: false
-        )
-
-        let yAxisModel = ChartAxisModel(axisValues: yAxisValues, lineColor: colors.axisLine, labelSpaceReservationMode: .fixed(labelsWidthY))
-
-        let coordsSpace = ChartCoordsSpaceLeftBottomSingleAxis(
-            chartSettings: chartSettings,
-            chartFrame: frame,
-            xModel: xAxisModel,
-            yModel: yAxisModel
-        )
-
-        // Grid lines
-        let gridLayer = ChartGuideLinesForValuesLayer(
-            xAxis: coordsSpace.xAxisLayer.axis,
-            yAxis: coordsSpace.yAxisLayer.axis,
-            settings: guideLinesLayerSettings,
-            axisValuesX: Array(xAxisValues.dropFirst().dropLast()),
-            axisValuesY: yAxisValues
-        )
-
-        // Selected line
-        var selectedLayer: ChartLayer?
-
-        if selectedInsulinModelChartPoints.count > 1 {
-            let lineModel = ChartLineModel.predictionLine(
-                points: selectedInsulinModelChartPoints,
-                color: colors.glucoseTint,
-                width: 2
-            )
-
-            selectedLayer = ChartPointsLineLayer(
-                xAxis: coordsSpace.xAxisLayer.axis,
-                yAxis: coordsSpace.yAxisLayer.axis,
-                lineModels: [lineModel]
-            )
-        }
-
-        var unselectedLineModels = [ChartLineModel]()
-
-        for points in unselectedInsulinModelChartPoints where points.count > 1 {
-            unselectedLineModels.append(ChartLineModel.predictionLine(
-                points: points,
-                color: UIColor.secondaryLabel,
-                width: 1
-            ))
-        }
-
-        // Unselected lines
-        var unselectedLayer: ChartLayer?
-
-        if !unselectedLineModels.isEmpty {
-            unselectedLayer = ChartPointsLineLayer(
-                xAxis: coordsSpace.xAxisLayer.axis,
-                yAxis: coordsSpace.yAxisLayer.axis,
-                lineModels: unselectedLineModels
-            )
-        }
-
-        let layers: [ChartLayer?] = [
-            gridLayer,
-            coordsSpace.xAxisLayer,
-            coordsSpace.yAxisLayer,
-            unselectedLayer,
-            selectedLayer
-        ]
-
-        return Chart(
-            frame: frame,
-            innerFrame: coordsSpace.chartInnerFrame,
-            settings: chartSettings,
-            layers: layers.compactMap { $0 }
-        )
-    }
-}
-
-extension InsulinModelChart {
-    public func setSelectedInsulinModelValues(_ values: [GlucoseValue]) {
-        self.selectedInsulinModelChartPoints = glucosePointsFromValues(values)
-    }
-
-    public func setUnselectedInsulinModelValues(_ values: [[GlucoseValue]]) {
-        self.unselectedInsulinModelChartPoints = values.map(glucosePointsFromValues)
-    }
-}

+ 0 - 23
Dependecies/LoopKit/LoopKitUI/Extensions/ChartLineModel+LoopKitUI.swift

@@ -1,23 +0,0 @@
-//
-//  ChartLineModel.swift
-//  Loop
-//
-//  Copyright © 2017 LoopKit Authors. All rights reserved.
-//
-
-import SwiftCharts
-
-
-extension ChartLineModel {
-    /// Creates a model configured with the dashed prediction line style
-    ///
-    /// - Parameters:
-    ///   - points: The points to construct the line
-    ///   - color: The line color
-    ///   - width: The line width
-    /// - Returns: A new line model
-    static func predictionLine(points: [T], color: UIColor, width: CGFloat) -> ChartLineModel {
-        // TODO: Bug in ChartPointsLineLayer requires a non-zero animation to draw the dash pattern
-        return self.init(chartPoints: points, lineColor: color, lineWidth: width, animDuration: 0.0001, animDelay: 0, dashPattern: [6, 5])
-    }
-}

+ 0 - 23
Dependecies/LoopKit/LoopKitUI/Extensions/ChartSettings+LoopKitUI.swift

@@ -1,23 +0,0 @@
-//
-//  ChartSettings+LoopKitUI.swift
-//  LoopKitUI
-//
-//  Created by Anna Quinlan on 7/20/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import SwiftCharts
-
-
-extension ChartSettings {
-    static var `default`: ChartSettings {
-        var settings = ChartSettings()
-        settings.top = 12
-        settings.bottom = 0
-        settings.trailing = 8
-        settings.axisTitleLabelsToLabelsSpacing = 0
-        settings.labelsToAxisSpacingX = 6
-        settings.clipInnerFrame = false
-        return settings
-    }
-}

+ 0 - 31
Dependecies/LoopKit/LoopKitUI/Models/ChartAxisValueDoubleUnit.swift

@@ -1,31 +0,0 @@
-//
-//  ChartAxisValueDoubleUnit.swift
-//  LoopKitUI
-//
-//  Created by Nate Racklyeft on 7/16/16.
-//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
-//
-
-import UIKit
-import SwiftCharts
-
-
-public final class ChartAxisValueDoubleUnit: ChartAxisValueDouble {
-    let unitString: String
-
-    public init(_ double: Double, unitString: String, formatter: NumberFormatter) {
-        self.unitString = unitString
-
-        super.init(double, formatter: formatter)
-    }
-
-    init(_ double: Double, unitString: String) {
-        self.unitString = unitString
-
-        super.init(double)
-    }
-
-    override public var description: String {
-        return formatter.string(from: scalar, unit: unitString) ?? ""
-    }
-}

+ 0 - 239
Dependecies/LoopKit/LoopKitUI/View Controllers/ChartsManager.swift

@@ -1,239 +0,0 @@
-//
-//  Chart.swift
-//  Naterade
-//
-//  Created by Nathan Racklyeft on 2/19/16.
-//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
-//
-
-import Foundation
-import HealthKit
-import LoopKit
-import SwiftCharts
-
-
-open class ChartsManager {
-
-    private lazy var timeFormatter: DateFormatter = {
-        let formatter = DateFormatter()
-        let dateFormat = DateFormatter.dateFormat(fromTemplate: "j", options: 0, locale: Locale.current)!
-        let isAmPmTimeFormat = dateFormat.firstIndex(of: "a") != nil
-        formatter.dateFormat = isAmPmTimeFormat
-            ? "h a"
-            : "H:mm"
-        return formatter
-    }()
-
-    public init(
-        colors: ChartColorPalette,
-        settings: ChartSettings,
-        axisLabelFont: UIFont = .systemFont(ofSize: 14), // caption1, but hard-coded until axis can scale with type preference
-        charts: [ChartProviding],
-        traitCollection: UITraitCollection
-    ) {
-        self.colors = colors
-        self.chartSettings = settings
-        self.charts = charts
-        self.traitCollection = traitCollection
-        self.chartsCache = Array(repeating: nil, count: charts.count)
-
-        axisLabelSettings = ChartLabelSettings(font: axisLabelFont, fontColor: colors.axisLabel)
-
-        guideLinesLayerSettings = ChartGuideLinesLayerSettings(linesColor: colors.grid)
-    }
-
-    // MARK: - Configuration
-
-    private let colors: ChartColorPalette
-
-    private let chartSettings: ChartSettings
-
-    private let labelsWidthY: CGFloat = 30
-
-    public let charts: [ChartProviding]
-
-    /// The amount of horizontal space reserved for fixed margins
-    public var fixedHorizontalMargin: CGFloat {
-        return chartSettings.leading + chartSettings.trailing + labelsWidthY + chartSettings.labelsToAxisSpacingY
-    }
-
-    private let axisLabelSettings: ChartLabelSettings
-
-    private let guideLinesLayerSettings: ChartGuideLinesLayerSettings
-
-    public var gestureRecognizer: UIGestureRecognizer?
-
-    // MARK: - UITraitEnvironment
-
-    public var traitCollection: UITraitCollection
-
-    public func didReceiveMemoryWarning() {
-
-        for chart in charts {
-            chart.didReceiveMemoryWarning()
-        }
-
-        xAxisValues = nil
-    }
-
-    // MARK: - Data
-
-    /// The earliest date on the X-axis
-    public var startDate = Date() {
-        didSet {
-            if startDate != oldValue {
-                xAxisValues = nil
-
-                // Set a new minimum end date
-                endDate = startDate.addingTimeInterval(.hours(3))
-            }
-        }
-    }
-
-    /// The latest date on the X-axis
-    private var endDate = Date() {
-        didSet {
-            if endDate != oldValue {
-                xAxisValues = nil
-            }
-        }
-    }
-
-    /// The latest allowed date on the X-axis
-    public var maxEndDate = Date.distantFuture {
-        didSet {
-            endDate = min(endDate, maxEndDate)
-        }
-    }
-
-    /// Updates the endDate using a new candidate date
-    ///
-    /// Dates are rounded up to the next hour.
-    ///
-    /// - Parameter date: The new candidate date
-    public func updateEndDate(_ date: Date) {
-        if date > endDate {
-            let components = DateComponents(minute: 0)
-            endDate = min(
-                maxEndDate,
-                Calendar.current.nextDate(
-                    after: date,
-                    matching: components,
-                    matchingPolicy: .strict,
-                    direction: .forward
-                ) ?? date
-            )
-        }
-    }
-
-    // MARK: - State
-
-    private var xAxisValues: [ChartAxisValue]? {
-        didSet {
-            if let xAxisValues = xAxisValues, xAxisValues.count > 1 {
-                xAxisModel = ChartAxisModel(axisValues: xAxisValues, lineColor: colors.axisLine, labelSpaceReservationMode: .fixed(20))
-            } else {
-                xAxisModel = nil
-            }
-
-            chartsCache.replaceAllElements(with: nil)
-        }
-    }
-
-    private var xAxisModel: ChartAxisModel?
-
-    private var chartsCache: [Chart?]
-
-    // MARK: - Generators
-
-    public func chart(atIndex index: Int, frame: CGRect) -> Chart? {
-        if let chart = chartsCache[index], chart.frame != frame {
-            chartsCache[index] = nil
-        }
-
-        if chartsCache[index] == nil, let xAxisModel = xAxisModel, let xAxisValues = xAxisValues {
-            chartsCache[index] = charts[index].generate(withFrame: frame, xAxisModel: xAxisModel, xAxisValues: xAxisValues, axisLabelSettings: axisLabelSettings, guideLinesLayerSettings: guideLinesLayerSettings, colors: colors, chartSettings: chartSettings, labelsWidthY: labelsWidthY, gestureRecognizer: gestureRecognizer, traitCollection: traitCollection)
-        }
-
-        return chartsCache[index]
-    }
-
-    public func invalidateChart(atIndex index: Int) {
-        chartsCache[index] = nil
-    }
-
-    // MARK: - Shared Axis
-
-    private func generateXAxisValues() {
-        if let endDate = charts.compactMap({ $0.endDate }).max() {
-            updateEndDate(endDate)
-        }
-
-        let points = [
-            ChartPoint(
-                x: ChartAxisValueDate(date: startDate, formatter: timeFormatter),
-                y: ChartAxisValue(scalar: 0)
-            ),
-            ChartPoint(
-                x: ChartAxisValueDate(date: endDate, formatter: timeFormatter),
-                y: ChartAxisValue(scalar: 0)
-            )
-        ]
-
-        let segments = ceil(endDate.timeIntervalSince(startDate).hours)
-
-        let xAxisValues = ChartAxisValuesStaticGenerator.generateXAxisValuesWithChartPoints(points,
-            minSegmentCount: segments - 1,
-            maxSegmentCount: segments + 1,
-            multiple: TimeInterval(hours: 1),
-            axisValueGenerator: {
-                ChartAxisValueDate(
-                    date: ChartAxisValueDate.dateFromScalar($0),
-                    formatter: timeFormatter,
-                    labelSettings: self.axisLabelSettings
-                )
-            },
-            addPaddingSegmentIfEdge: false
-        )
-        xAxisValues.first?.hidden = true
-        xAxisValues.last?.hidden = true
-
-        self.xAxisValues = xAxisValues
-    }
-
-    /// Runs any necessary steps before rendering charts
-    public func prerender() {
-        if xAxisValues == nil {
-            generateXAxisValues()
-        }
-    }
-}
-
-fileprivate extension Array {
-    mutating func replaceAllElements(with element: Element) {
-        self = Array(repeating: element, count: count)
-    }
-}
-
-public protocol ChartProviding {
-    /// Instructs the chart to clear its non-critical resources like caches
-    func didReceiveMemoryWarning()
-
-    /// The last date represented in the chart data
-    var endDate: Date? { get }
-
-    /// Creates a chart from the current data
-    ///
-    /// - Returns: A new chart object
-    func generate(withFrame frame: CGRect,
-        xAxisModel: ChartAxisModel,
-        xAxisValues: [ChartAxisValue],
-        axisLabelSettings: ChartLabelSettings,
-        guideLinesLayerSettings: ChartGuideLinesLayerSettings,
-        colors: ChartColorPalette,
-        chartSettings: ChartSettings,
-        labelsWidthY: CGFloat,
-        gestureRecognizer: UIGestureRecognizer?,
-        traitCollection: UITraitCollection
-    ) -> Chart
-}

+ 0 - 161
Dependecies/LoopKit/LoopKitUI/View Controllers/ChartsTableViewController.swift

@@ -1,161 +0,0 @@
-//
-//  ChartsTableViewController.swift
-//  LoopKitUI
-//
-//  Copyright © 2017 LoopKit Authors. All rights reserved.
-//
-
-import UIKit
-import HealthKit
-
-/// Abstract class providing boilerplate setup for chart-based table view controllers
-open class ChartsTableViewController: UITableViewController, UIGestureRecognizerDelegate {
-
-    public var preferredGlucoseUnit: HKUnit?
-
-    open override func viewDidLoad() {
-        super.viewDidLoad()
-        
-        if let unit = preferredGlucoseUnit {
-            self.charts.setGlucoseUnit(unit)
-        }
-
-        let gestureRecognizer = UILongPressGestureRecognizer()
-        gestureRecognizer.delegate = self
-        gestureRecognizer.minimumPressDuration = 0.3
-        gestureRecognizer.addTarget(self, action: #selector(handlePan(_:)))
-        charts.gestureRecognizer = gestureRecognizer
-        
-        NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: nil) { [weak self] _ in
-            guard let self = self else { return }
-            
-            if self.visible {
-                DispatchQueue.main.async {
-                    self.reloadData()
-                }
-            }
-        }
-    }
-
-    open override func didReceiveMemoryWarning() {
-        super.didReceiveMemoryWarning()
-
-        if !visible {
-            charts.didReceiveMemoryWarning()
-        }
-    }
-
-    open override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-
-        visible = true
-    }
-
-    open override func viewWillDisappear(_ animated: Bool) {
-        super.viewWillDisappear(animated)
-
-        visible = false
-    }
-
-    open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
-        super.viewWillTransition(to: size, with: coordinator)
-
-        reloadData(animated: false)
-    }
-
-    open override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
-        super.traitCollectionDidChange(previousTraitCollection)
-
-        charts.traitCollection = traitCollection
-    }
-
-    // MARK: - State
-    // This function should only be called from the main thread
-    public func unitPreferencesDidChange(to unit: HKUnit?) {
-        if let unit = unit {
-            self.charts.setGlucoseUnit(unit)
-            self.glucoseUnitDidChange()
-        }
-        self.reloadData()
-    }
-
-    open func glucoseUnitDidChange() {
-        // To override.
-    }
-
-    open func createChartsManager() -> ChartsManager {
-        fatalError("Subclasses must implement \(#function)")
-    }
-
-    lazy public private(set) var charts = createChartsManager()
-
-    // References to registered notification center observers
-    public var notificationObservers: [Any] = []
-
-    open var active: Bool = true {
-        didSet {
-            reloadData()
-        }
-    }
-
-    public var visible = false {
-        didSet {
-            reloadData()
-        }
-    }
-
-    // MARK: - Data loading
-
-    /// Refetches all data and updates the views. Must be called on the main queue.
-    ///
-    /// - Parameters:
-    ///   - animated: Whether the updating should be animated if possible
-    open func reloadData(animated: Bool = false) {
-
-    }
-
-    // MARK: - UIGestureRecognizer
-
-    public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
-        /// Only start the long-press recognition when it starts in a chart cell
-        let point = gestureRecognizer.location(in: tableView)
-        if let indexPath = tableView.indexPathForRow(at: point) {
-            if let cell = tableView.cellForRow(at: indexPath), cell is ChartTableViewCell {
-                return true
-            }
-        }
-
-        return false
-    }
-
-    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
-        return true
-    }
-
-    @objc func handlePan(_ gestureRecognizer: UIGestureRecognizer) {
-        switch gestureRecognizer.state {
-        case .possible, .changed:
-            // Follow your dreams!
-            break
-        case .began, .cancelled, .ended, .failed:
-            for case let row as ChartTableViewCell in self.tableView.visibleCells {
-                let forwards = gestureRecognizer.state == .began
-                UIView.animate(withDuration: forwards ? 0.2 : 0.5, delay: forwards ? 0 : 1, animations: {
-                    let alpha: CGFloat = forwards ? 0 : 1
-                    row.titleLabel?.alpha = alpha
-                    row.subtitleLabel?.alpha = alpha
-                })
-            }
-        @unknown default:
-            break
-        }
-    }
-}
-
-fileprivate extension ChartsManager {
-    func setGlucoseUnit(_ unit: HKUnit) {
-        for case let chart as GlucoseChart in charts {
-            chart.glucoseUnit = unit
-        }
-    }
-}

+ 0 - 40
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/BasalRatesInformationView.swift

@@ -1,40 +0,0 @@
-//
-//  BasalRatesInformationView.swift
-//  LoopKitUI
-//
-//  Created by Anna Quinlan on 7/3/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import SwiftUI
-import LoopKit
-
-public struct BasalRatesInformationView: View {
-    var onExit: (() -> Void)?
-    var mode: SettingsPresentationMode
-    
-    @Environment(\.presentationMode) var presentationMode
-    
-    public init(onExit: (() -> Void)?, mode: SettingsPresentationMode = .acceptanceFlow) {
-        self.onExit = onExit
-        self.mode = mode
-    }
-    
-    public var body: some View {
-        InformationView(
-            title: Text(TherapySetting.basalRate.title),
-            informationalContent: {text},
-            onExit: onExit ?? { self.presentationMode.wrappedValue.dismiss() },
-            mode: mode
-        )
-    }
-    
-    private var text: some View {
-        VStack(alignment: .leading, spacing: 25) {
-            Text(LocalizedString("Your Basal Rate of insulin is the number of units per hour that you want to use to cover your background insulin needs.", comment: "Information about basal rates"))
-            Text(LocalizedString("Loop supports 1 to 48 rates per day.", comment: "Information about max number of basal rates"))
-            Text(LocalizedString("The schedule starts at midnight and cannot contain a rate of 0 U/hr.", comment: "Information about basal rate scheduling"))
-        }
-        .foregroundColor(.secondary)
-    }
-}

+ 0 - 44
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/CarbRatioInformationView.swift

@@ -1,44 +0,0 @@
-//
-//  CarbRatioInformationView.swift
-//  LoopKitUI
-//
-//  Created by Anna Quinlan on 7/28/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import SwiftUI
-import LoopKit
-
-public struct CarbRatioInformationView: View {
-    var onExit: (() -> Void)?
-    var mode: SettingsPresentationMode
-    
-    @Environment(\.presentationMode) var presentationMode
-    @Environment(\.appName) private var appName
-
-    public init(
-        onExit: (() -> Void)?,
-        mode: SettingsPresentationMode = .acceptanceFlow
-    ){
-        self.onExit = onExit
-        self.mode = mode
-    }
-    
-    public var body: some View {
-        InformationView(
-            title: Text(TherapySetting.carbRatio.title),
-            informationalContent: {text},
-            onExit: onExit ?? { self.presentationMode.wrappedValue.dismiss() },
-            mode: mode
-        )
-    }
-    
-    private var text: some View {
-        VStack(alignment: .leading, spacing: 25) {
-            Text(TherapySetting.carbRatio.descriptiveText(appName: appName))
-            Text(LocalizedString("You can add different carb ratios for different times of day by using the ➕.", comment: "Description of how to add a ratio"))
-        }
-        .accentColor(.secondary)
-        .foregroundColor(.accentColor)
-    }
-}

+ 0 - 62
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/CorrectionRangeInformationView.swift

@@ -1,62 +0,0 @@
-//
-//  CorrectionRangeInformationView.swift
-//  LoopKitUI
-//
-//  Created by Anna Quinlan on 7/1/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import SwiftUI
-import LoopKit
-
-public struct CorrectionRangeInformationView: View {
-    var onExit: (() -> Void)?
-    var mode: SettingsPresentationMode
-    
-    @Environment(\.presentationMode) var presentationMode
-    @Environment(\.appName) var appName
-
-    public init(onExit: (() -> Void)? = nil, mode: SettingsPresentationMode = .acceptanceFlow) {
-        self.onExit = onExit
-        self.mode = mode
-    }
-    
-    public var body: some View {
-        GlucoseTherapySettingInformationView(
-            therapySetting: .glucoseTargetRange,
-            onExit: onExit,
-            mode: mode,
-            appName: appName,
-            text: AnyView(text)
-        )
-    }
-    
-    private var text: some View {
-        VStack(alignment: .leading, spacing: 25) {
-            Text(LocalizedString("If you've used a CGM before, you're likely familiar with target range as a wide range of values you'd like for your glucose notification alerts, such as 70-180 mg/dL or 90-200 mg/dL.", comment: "Information about target range"))
-            Text(LocalizedString("A Correction Range is different. This will be a narrower range.", comment: "Information about differences between target range and correction range"))
-            .bold()
-            Text(String(format: LocalizedString("For this range, choose the specific glucose value (or range of values) that you want %1$@ to aim for in adjusting your basal insulin.", comment: "Information about correction range format (1: app name)"), appName))
-            Text(LocalizedString("Your healthcare provider can help you choose a Correction Range that's right for you.", comment: "Disclaimer"))
-        }
-        .foregroundColor(.secondary)
-    }
-}
-
-struct CorrectionRangeInformationView_Previews: PreviewProvider {
-    static var previews: some View {
-        NavigationView {
-            CorrectionRangeInformationView()
-        }
-        .colorScheme(.light)
-        .previewDevice(PreviewDevice(rawValue: "iPhone SE 2"))
-        .previewDisplayName("SE light")
-        NavigationView {
-            CorrectionRangeInformationView()
-        }
-        .preferredColorScheme(.dark)
-        .colorScheme(.dark)
-        .previewDevice(PreviewDevice(rawValue: "iPhone 11 Pro Max"))
-        .previewDisplayName("11 Pro dark")
-    }
-}

+ 0 - 96
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/CorrectionRangeOverrideInformationView.swift

@@ -1,96 +0,0 @@
-//
-//  CorrectionRangeOverrideInformationView.swift
-//  LoopKitUI
-//
-//  Created by Anna Quinlan on 7/2/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import LoopKit
-import SwiftUI
-
-public struct CorrectionRangeOverrideInformationView: View {
-    let preset: CorrectionRangeOverrides.Preset
-    var onExit: (() -> Void)?
-    let mode: SettingsPresentationMode
-    
-    @Environment(\.presentationMode) var presentationMode
-    @Environment(\.carbTintColor) var carbTintColor
-    @Environment(\.glucoseTintColor) var glucoseTintColor
-    @Environment(\.appName) var appName
-
-    public init(
-        preset: CorrectionRangeOverrides.Preset,
-        onExit: (() -> Void)? = nil,
-        mode: SettingsPresentationMode = .acceptanceFlow
-    ) {
-        self.preset = preset
-        self.onExit = onExit
-        self.mode = mode
-    }
-    
-    public var body: some View {
-        GlucoseTherapySettingInformationView(
-            therapySetting: preset.therapySetting,
-            onExit: onExit,
-            mode: mode,
-            appName: appName,
-            text: AnyView(section(for: preset))
-        )
-    }
-    
-    private func section(for preset: CorrectionRangeOverrides.Preset) -> some View {
-        VStack(alignment: .leading, spacing: 15) {
-            description(for: preset)
-                .foregroundColor(.secondary)
-        }
-    }
-        
-    private func description(for preset: CorrectionRangeOverrides.Preset) -> some View {
-        switch preset {
-        case .preMeal:
-            return VStack(alignment: .leading, spacing: 20) {
-                Text(String(format: LocalizedString("Your Pre-Meal Range should be the glucose value (or range of values) you want %1$@ to target by the time you take your first bite of your meal. This range will be in effect when you activate the Pre-Meal Preset button.", comment: "Information about pre-meal range format (1: app name)"), appName))
-                Text(LocalizedString("This will typically be", comment: "Information about pre-meal range relative to correction range")) + Text(LocalizedString(" lower ", comment: "Information about pre-meal range relative to correction range")).bold().italic() + Text(LocalizedString("than your Correction Range.", comment: "Information about pre-meal range relative to correction range"))
-            }
-            .fixedSize(horizontal: false, vertical: true) // prevent text from being cut off
-        case .workout:
-            return VStack(alignment: .leading, spacing: 20) {
-                Text(String(format: LocalizedString("Workout Range is the glucose value or range of values you want %1$@ to target during activity. This range will be in effect when you activate the Workout Preset button.", comment: "Information about workout range format (1: app name)"), appName))
-                Text(LocalizedString("This will typically be", comment: "Information about workout range relative to correction range")) + Text(LocalizedString(" higher ", comment: "Information about workout range relative to correction range")).bold().italic() + Text(LocalizedString("than your Correction Range.", comment: "Information about workout range relative to correction range"))
-            }
-            .fixedSize(horizontal: false, vertical: true) // prevent text from being cut off
-        }
-    }
-}
-
-struct CorrectionRangeOverrideInformationView_Previews: PreviewProvider {
-    static var previews: some View {
-        NavigationView {
-            CorrectionRangeOverrideInformationView(preset: .preMeal)
-        }
-        .colorScheme(.light)
-        .previewDevice(PreviewDevice(rawValue: "iPhone SE 2"))
-        .previewDisplayName("Pre-Meal SE light")
-        NavigationView {
-            CorrectionRangeOverrideInformationView(preset: .workout)
-        }
-        .colorScheme(.light)
-        .previewDevice(PreviewDevice(rawValue: "iPhone SE 2"))
-        .previewDisplayName("Workout SE light")
-        NavigationView {
-            CorrectionRangeOverrideInformationView(preset: .preMeal)
-        }
-        .preferredColorScheme(.dark)
-        .colorScheme(.dark)
-        .previewDevice(PreviewDevice(rawValue: "iPhone 11 Pro Max"))
-        .previewDisplayName("Pre-Meal 11 Pro dark")
-        NavigationView {
-            CorrectionRangeOverrideInformationView(preset: .workout)
-        }
-        .preferredColorScheme(.dark)
-        .colorScheme(.dark)
-        .previewDevice(PreviewDevice(rawValue: "iPhone 11 Pro Max"))
-        .previewDisplayName("Workout 11 Pro dark")
-    }
-}

+ 0 - 67
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/DeliveryLimitsInformationView.swift

@@ -1,67 +0,0 @@
-//
-//  DeliveryLimitsInformationView.swift
-//  LoopKitUI
-//
-//  Created by Anna Quinlan on 7/3/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import SwiftUI
-import LoopKit
-
-public struct DeliveryLimitsInformationView: View {
-    var onExit: (() -> Void)?
-    var mode: SettingsPresentationMode
-    
-    @Environment(\.presentationMode) var presentationMode
-    @Environment(\.appName) var appName
-
-    public init(onExit: (() -> Void)?, mode: SettingsPresentationMode = .acceptanceFlow) {
-        self.onExit = onExit
-        self.mode = mode
-    }
-    
-    public var body: some View {
-        InformationView(
-            title: Text(TherapySetting.deliveryLimits.title),
-            informationalContent: {
-                VStack (alignment: .leading, spacing: 20) {
-                    deliveryLimitDescription
-                    maxBasalDescription
-                    maxBolusDescription
-                }
-                .fixedSize(horizontal: false, vertical: true) // prevent text from being cut off
-            },
-            onExit: onExit ?? { self.presentationMode.wrappedValue.dismiss() },
-            mode: mode
-        )
-    }
-    
-    private var deliveryLimitDescription: some View {
-        Text(LocalizedString("Delivery Limits are safety guardrails for your insulin delivery.", comment: "Information about delivery limits"))
-        .foregroundColor(.secondary)
-    }
-    
-    private var maxBasalDescription: some View {
-        VStack(alignment: .leading, spacing: 20) {
-            Text(DeliveryLimits.Setting.maximumBasalRate.title)
-            .font(.headline)
-            VStack(alignment: .leading, spacing: 20) {
-                Text(LocalizedString("Maximum Basal Rate is the maximum automatically adjusted basal rate that \(appName) is allowed to enact to help reach your correction range.", comment: "Information about maximum basal rate"))
-                Text(LocalizedString("Some users choose a value 2, 3, or 4 times their highest scheduled basal rate.", comment: "Information about typical maximum basal rates"))
-                Text(LocalizedString("Work with your healthcare provider to choose a value that is higher than your highest scheduled basal rate, but as conservative or aggressive as you feel comfortable.", comment: "Disclaimer"))
-            }
-            .foregroundColor(.secondary)
-        }
-    }
-    
-    private var maxBolusDescription: some View {
-        VStack(alignment: .leading, spacing: 20) {
-            Text(DeliveryLimits.Setting.maximumBolus.title)
-            .font(.headline)
-            Text(LocalizedString("Maximum Bolus is the highest bolus amount that you will allow \(appName) to recommend at one time to cover carbs or bring down high glucose.", comment: "Information about maximum bolus"))
-            .foregroundColor(.secondary)
-        }
-    }
-}
-

+ 0 - 102
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/GlucoseTherapySettingInformationView.swift

@@ -1,102 +0,0 @@
-//
-//  GlucoseTherapySettingInformationView.swift
-//  LoopKitUI
-//
-//  Created by Rick Pasetto on 11/16/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import HealthKit
-import SwiftUI
-import LoopKit
-
-public struct GlucoseTherapySettingInformationView: View {
-    var text: AnyView?
-    let onExit: (() -> Void)?
-    let mode: SettingsPresentationMode
-    let therapySetting: TherapySetting
-    let preferredUnit: HKUnit
-    let appName: String
-    
-    @Environment(\.presentationMode) var presentationMode
-
-    public init(
-        therapySetting: TherapySetting,
-        preferredUnit: HKUnit? = nil,
-        onExit: (() -> Void)?,
-        mode: SettingsPresentationMode = .acceptanceFlow,
-        appName: String,
-        text: AnyView? = nil
-    ){
-        self.therapySetting = therapySetting
-        self.preferredUnit = preferredUnit ?? .milligramsPerDeciliter
-        self.onExit = onExit
-        self.mode = mode
-        self.appName = appName
-        self.text = text
-    }
-    
-    public var body: some View {
-        InformationView(
-            title: Text(self.therapySetting.title),
-            informationalContent: {
-                illustration
-                bodyText
-            },
-            onExit: onExit ?? { self.presentationMode.wrappedValue.dismiss() },
-            mode: mode
-        )
-    }
-    
-    private var illustration: some View {
-        Image(frameworkImage: illustrationImageName)
-            .renderingMode(.original)
-            .resizable()
-            .aspectRatio(contentMode: ContentMode.fit)
-    }
-    
-    private var bodyText: some View {
-        VStack(alignment: .leading, spacing: 25) {
-            text ?? AnyView(Text(therapySetting.descriptiveText(appName: appName)))
-            Text(therapySetting.guardrailInformationText)
-        }
-        .accentColor(.secondary)
-        .foregroundColor(.accentColor)
-        .fixedSize(horizontal: false, vertical: true)
-    }
-    
-    private var illustrationImageName: String {
-        return "\(therapySetting) \(preferredUnit.description.replacingOccurrences(of: "/", with: ""))"
-    }
-}
-
-fileprivate extension TherapySetting {
-    // TODO: pass in preferredUnit instead of having both units.
-    var guardrailInformationText: String {
-        switch self {
-        case .glucoseTargetRange:
-            return lowHighText(for: Guardrail.correctionRange)
-        case .preMealCorrectionRangeOverride:
-            return lowHighText(lowerBoundString: LocalizedString("your Glucose Safety Limit", comment: "Lower bound pre-meal information text"),
-                               upperBoundString: Guardrail.premealCorrectionRangeMaximum.bothUnitsString)
-        case .workoutCorrectionRangeOverride:
-            return lowHighText(
-                lowerBoundString: String(format: LocalizedString("%1$@ or your Glucose Safety Limit, whichever is higher", comment: "Lower bound workout information text format (1: app name)"), Guardrail.unconstrainedWorkoutCorrectionRange.absoluteBounds.lowerBound.bothUnitsString),
-                upperBoundString: Guardrail.unconstrainedWorkoutCorrectionRange.absoluteBounds.upperBound.bothUnitsString)
-        case .suspendThreshold:
-            return lowHighText(for: Guardrail.suspendThreshold)
-        case .basalRate, .deliveryLimits, .insulinModel, .carbRatio, .insulinSensitivity, .none:
-            fatalError("Unexpected")
-        }
-    }
-       
-    func lowHighText(for guardrail: Guardrail<HKQuantity>) -> String {
-        return lowHighText(lowerBoundString: guardrail.absoluteBounds.lowerBound.bothUnitsString,
-                           upperBoundString: guardrail.absoluteBounds.upperBound.bothUnitsString)
-    }
-
-    func lowHighText(lowerBoundString: String, upperBoundString: String) -> String {
-        return String(format: LocalizedString("It can be set as low as %1$@. It can be set as high as %2$@.",
-                                              comment: "Guardrail info text format"), lowerBoundString, upperBoundString)
-    }
-}

+ 0 - 6
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/Contents.json

@@ -1,6 +0,0 @@
-{
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  }
-}

File diff suppressed because it is too large
+ 0 - 5240
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/glucoseTargetRange mgdL.imageset/Chart=Correction, Version=V7, Appearance=Dark, Unit=mgdL.pdf


二進制
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/glucoseTargetRange mgdL.imageset/Chart=Correction, Version=V7, Appearance=Light, Unit=mgdL.pdf


+ 0 - 26
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/glucoseTargetRange mgdL.imageset/Contents.json

@@ -1,26 +0,0 @@
-{
-  "images" : [
-    {
-      "filename" : "Chart=Correction, Version=V7, Appearance=Light, Unit=mgdL.pdf",
-      "idiom" : "universal"
-    },
-    {
-      "appearances" : [
-        {
-          "appearance" : "luminosity",
-          "value" : "dark"
-        }
-      ],
-      "filename" : "Chart=Correction, Version=V7, Appearance=Dark, Unit=mgdL.pdf",
-      "idiom" : "universal"
-    }
-  ],
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  },
-  "properties" : {
-    "preserves-vector-representation" : true,
-    "template-rendering-intent" : "template"
-  }
-}

File diff suppressed because it is too large
+ 0 - 5041
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/preMealCorrectionRangeOverride mgdL.imageset/Chart=Premeal, Version=V7, Appearance=Dark, Unit=mgdL.pdf


二進制
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/preMealCorrectionRangeOverride mgdL.imageset/Chart=Premeal, Version=V7, Appearance=Light, Unit=mgdL.pdf


+ 0 - 26
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/preMealCorrectionRangeOverride mgdL.imageset/Contents.json

@@ -1,26 +0,0 @@
-{
-  "images" : [
-    {
-      "filename" : "Chart=Premeal, Version=V7, Appearance=Light, Unit=mgdL.pdf",
-      "idiom" : "universal"
-    },
-    {
-      "appearances" : [
-        {
-          "appearance" : "luminosity",
-          "value" : "dark"
-        }
-      ],
-      "filename" : "Chart=Premeal, Version=V7, Appearance=Dark, Unit=mgdL.pdf",
-      "idiom" : "universal"
-    }
-  ],
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  },
-  "properties" : {
-    "preserves-vector-representation" : true,
-    "template-rendering-intent" : "template"
-  }
-}

File diff suppressed because it is too large
+ 0 - 3283
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/suspendThreshold mgdL.imageset/Chart=Glucose, Version=V7, Appearance=Dark, Unit=mgdL.pdf


File diff suppressed because it is too large
+ 0 - 3210
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/suspendThreshold mgdL.imageset/Chart=Glucose, Version=V7, Appearance=Light, Unit=mgdL.pdf


+ 0 - 26
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/suspendThreshold mgdL.imageset/Contents.json

@@ -1,26 +0,0 @@
-{
-  "images" : [
-    {
-      "filename" : "Chart=Glucose, Version=V7, Appearance=Light, Unit=mgdL.pdf",
-      "idiom" : "universal"
-    },
-    {
-      "appearances" : [
-        {
-          "appearance" : "luminosity",
-          "value" : "dark"
-        }
-      ],
-      "filename" : "Chart=Glucose, Version=V7, Appearance=Dark, Unit=mgdL.pdf",
-      "idiom" : "universal"
-    }
-  ],
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  },
-  "properties" : {
-    "preserves-vector-representation" : true,
-    "template-rendering-intent" : "template"
-  }
-}

File diff suppressed because it is too large
+ 0 - 5307
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/workoutCorrectionRangeOverride mgdL.imageset/Chart=Workout, Version=V7, Appearance=Dark, Unit=mgdL.pdf


二進制
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/workoutCorrectionRangeOverride mgdL.imageset/Chart=Workout, Version=V7, Appearance=Light, Unit=mgdL.pdf


+ 0 - 26
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationScreens.xcassets/workoutCorrectionRangeOverride mgdL.imageset/Contents.json

@@ -1,26 +0,0 @@
-{
-  "images" : [
-    {
-      "filename" : "Chart=Workout, Version=V7, Appearance=Light, Unit=mgdL.pdf",
-      "idiom" : "universal"
-    },
-    {
-      "appearances" : [
-        {
-          "appearance" : "luminosity",
-          "value" : "dark"
-        }
-      ],
-      "filename" : "Chart=Workout, Version=V7, Appearance=Dark, Unit=mgdL.pdf",
-      "idiom" : "universal"
-    }
-  ],
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  },
-  "properties" : {
-    "preserves-vector-representation" : true,
-    "template-rendering-intent" : "template"
-  }
-}

+ 0 - 91
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InformationView.swift

@@ -1,91 +0,0 @@
-//
-//  InformationView.swift
-//  LoopKitUI
-//
-//  Created by Anna Quinlan on 7/1/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import SwiftUI
-
-struct InformationView<InformationalContent: View> : View {
-    var informationalContent: InformationalContent
-    var title: Text
-    var buttonText: Text
-    var onExit: (() -> Void)
-    let mode: SettingsPresentationMode
-    
-    init(
-        title: Text,
-        buttonText: Text,
-        @ViewBuilder informationalContent: () -> InformationalContent,
-        onExit: @escaping () -> Void,
-        mode: SettingsPresentationMode
-    ) {
-        self.title = title
-        self.buttonText = buttonText
-        self.informationalContent = informationalContent()
-        self.onExit = onExit
-        self.mode = mode
-    }
-    
-    // Convenience initializer for info view w/next page button
-    init(
-        title: Text,
-        @ViewBuilder informationalContent: () -> InformationalContent,
-        onExit: @escaping () -> Void,
-        mode: SettingsPresentationMode = .acceptanceFlow
-    ) {
-        self.init(
-            title: title,
-            buttonText: Text(LocalizedString("Continue", comment: "Button to advance to setting editor")),
-            informationalContent: informationalContent,
-            onExit: onExit,
-            mode: mode
-        )
-    }
-    
-    var body: some View {
-        ScrollView {
-            bodyWithCancelButtonIfNeeded
-            .navigationBarTitle(title, displayMode: .large)
-            .padding()
-        }
-    }
-    
-    private var bodyWithCancelButtonIfNeeded: some View {
-        switch mode {
-        case .acceptanceFlow:
-            return AnyView(bodyWithBottomButton)
-        case .settings:
-            return AnyView(bodyWithCancelButton)
-        }
-    }
-    
-    private var bodyWithBottomButton: some View {
-        VStack(alignment: .leading, spacing: 20) {
-            informationalContent
-            Spacer()
-            nextPageButton
-        }
-    }
-    
-    private var bodyWithCancelButton: some View {
-        VStack(alignment: .leading, spacing: 20) {
-            informationalContent
-            Spacer()
-        }
-        .navigationBarItems(trailing: cancelButton)
-    }
-    
-    private var cancelButton: some View {
-        Button(action: onExit, label: { Text(LocalizedString("Close", comment: "Text to close informational page")) })
-    }
-    
-    private var nextPageButton: some View {
-        Button(action: onExit) {
-            buttonText
-            .actionButtonStyle(.primary)
-        }
-    }
-}

+ 0 - 62
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InsulinModelInformationView.swift

@@ -1,62 +0,0 @@
-//
-//  InsulinModelInformationView.swift
-//  LoopKitUI
-//
-//  Created by Anna Quinlan on 7/6/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import SwiftUI
-import LoopKit
-
-public struct InsulinModelInformationView: View {
-    var onExit: (() -> Void)?
-    var mode: SettingsPresentationMode
-    
-    @Environment(\.presentationMode) var presentationMode
-    @Environment(\.appName) private var appName
-    
-    public init(onExit: (() -> Void)?, mode: SettingsPresentationMode = .acceptanceFlow) {
-        self.onExit = onExit
-        self.mode = mode
-    }
-    
-    public var body: some View {
-        InformationView(
-            title: Text(TherapySetting.insulinModel.title),
-            informationalContent: {
-                VStack (alignment: .leading, spacing: 20) {
-                    diaInfo
-                    modelPeakInfo
-                }
-                .foregroundColor(.secondary)
-            },
-            onExit: onExit ?? { self.presentationMode.wrappedValue.dismiss() },
-            mode: mode
-        )
-    }
-    
-    private var diaInfo: Text {
-        Text(LocalizedString("\(appName) assumes that the insulin it has delivered is actively working to lower your glucose for 6 hours. This setting cannot be changed.", comment: "Information about insulin action duration"))
-    }
-    
-    private var modelPeakInfo: some View {
-        VStack (alignment: .leading, spacing: 20) {
-            Text(LocalizedString("You can choose how \(appName) measures rapid acting insulin's peak activity according to one of these two insulin models.", comment: "Information about insulin model"))
-            HStack(spacing: 10) {
-                bulletCircle
-                Text(LocalizedString("The rapid-acting adult model assumes peak activity at 75 minutes.", comment: "Information about adult insulin model"))
-            }
-            HStack(spacing: 10) {
-                bulletCircle
-                Text(LocalizedString("The rapid-acting child model assumes peak activity at 65 minutes.", comment: "Information about child insulin model"))
-            }
-        }
-    }
-    
-    private var bulletCircle: some View {
-        Image(systemName: "circle.fill")
-        .resizable()
-        .frame(width: 10, height: 10)
-    }
-}

+ 0 - 44
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/InsulinSensitivityInformationView.swift

@@ -1,44 +0,0 @@
-//
-//  InsulinSensitivityInformationView.swift
-//  LoopKitUI
-//
-//  Created by Anna Quinlan on 7/28/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import SwiftUI
-import LoopKit
-
-public struct InsulinSensitivityInformationView: View {
-    var onExit: (() -> Void)?
-    var mode: SettingsPresentationMode
-    
-    @Environment(\.presentationMode) var presentationMode
-    
-    public init(
-        onExit: (() -> Void)?,
-        mode: SettingsPresentationMode = .acceptanceFlow
-    ){
-        self.onExit = onExit
-        self.mode = mode
-    }
-    
-    public var body: some View {
-        InformationView(
-            title: Text(TherapySetting.insulinSensitivity.title),
-            informationalContent: {text},
-            onExit: onExit ?? { self.presentationMode.wrappedValue.dismiss() },
-            mode: mode
-        )
-    }
-    
-    private var text: some View {
-        VStack(alignment: .leading, spacing: 25) {
-            Text(LocalizedString("Your Insulin Sensitivity Factor (ISF) is the drop in glucose expected from one unit of insulin.", comment: "Description of insulin sensitivity factor"))
-            Text(LocalizedString("You can add different insulin sensitivities for different times of day by using the ➕.", comment: "Description of how to add a ratio"))
-        }
-        .accentColor(.secondary)
-        .foregroundColor(.accentColor)
-    }
-}
-

+ 0 - 54
Dependecies/LoopKit/LoopKitUI/Views/Information Screens/SuspendThresholdInformationView.swift

@@ -1,54 +0,0 @@
-//
-//  SuspendThresholdInformationView.swift
-//  LoopKitUI
-//
-//  Created by Anna Quinlan on 7/2/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import HealthKit
-import SwiftUI
-import LoopKit
-
-public struct SuspendThresholdInformationView: View {
-    var onExit: (() -> Void)?
-    var mode: SettingsPresentationMode
-    var preferredUnit: HKUnit = HKUnit.milligramsPerDeciliter
-    
-    @Environment(\.presentationMode) var presentationMode
-    @Environment(\.appName) var appName
-
-    public init(
-        onExit: (() -> Void)? = nil,
-        mode: SettingsPresentationMode = .acceptanceFlow
-    ){
-        self.onExit = onExit
-        self.mode = mode
-    }
-    
-    public var body: some View {
-        GlucoseTherapySettingInformationView(therapySetting: .suspendThreshold,
-                                             preferredUnit: preferredUnit,
-                                             onExit: onExit,
-                                             mode: mode,
-                                             appName: appName)
-    }
-}
-
-struct SuspendThresholdInformationView_Previews: PreviewProvider {
-    static var previews: some View {
-        NavigationView {
-            SuspendThresholdInformationView()
-        }
-        .colorScheme(.light)
-        .previewDevice(PreviewDevice(rawValue: "iPhone SE 2"))
-        .previewDisplayName("SE light")
-        NavigationView {
-            SuspendThresholdInformationView()
-        }
-        .preferredColorScheme(.dark)
-        .colorScheme(.dark)
-        .previewDevice(PreviewDevice(rawValue: "iPhone 11 Pro Max"))
-        .previewDisplayName("11 Pro dark")
-    }
-}

+ 0 - 224
Dependecies/LoopKit/LoopKitUI/Views/QuantityScheduleEditor.swift

@@ -1,224 +0,0 @@
-//
-//  QuantityScheduleEditor.swift
-//  LoopKitUI
-//
-//  Created by Michael Pangburn on 4/24/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import SwiftUI
-import HealthKit
-import LoopKit
-
-
-struct QuantityScheduleEditor<ActionAreaContent: View>: View {
-    enum QuantitySelectionMode {
-        /// A single picker for selecting quantity values.
-        case whole
-        // A two-component picker for selecting the whole and fractional quantity values independently.
-        case fractional
-    }
-
-    @Environment(\.guidanceColors) var guidanceColors
-    
-    var title: Text
-    var description: Text
-    var initialScheduleItems: [RepeatingScheduleValue<Double>]
-    @State var scheduleItems: [RepeatingScheduleValue<Double>]
-    var unit: HKUnit
-    var selectableValues: [Double]
-    var quantitySelectionMode: QuantitySelectionMode
-    var guardrail: Guardrail<HKQuantity>
-    var defaultFirstScheduleItemValue: HKQuantity
-    var scheduleItemLimit: Int
-    var confirmationAlertContent: AlertContent
-    var guardrailWarning: (_ crossedThresholds: [SafetyClassification.Threshold]) -> ActionAreaContent
-    var savingMechanism: SavingMechanism<DailyQuantitySchedule<Double>>
-    var mode: SettingsPresentationMode
-    var settingType: TherapySetting
-    
-    @State private var userDidTap: Bool = false
-
-    var body: some View {
-        ScheduleEditor(
-            title: title,
-            description: description,
-            scheduleItems: $scheduleItems,
-            initialScheduleItems: initialScheduleItems,
-            defaultFirstScheduleItemValue: defaultFirstScheduleItemValue.doubleValue(for: unit),
-            scheduleItemLimit: scheduleItemLimit,
-            saveConfirmation: saveConfirmation,
-            valueContent: { value, isEditing in
-                GuardrailConstrainedQuantityView(
-                    value: HKQuantity(unit: self.unit, doubleValue: value),
-                    unit: self.unit,
-                    guardrail: self.guardrail,
-                    isEditing: isEditing
-                )
-            },
-            valuePicker: { item, availableWidth in
-                if self.quantitySelectionMode == .whole {
-                    QuantityPicker(
-                        value: item.value.animation().withUnit(self.unit),
-                        unit: self.unit,
-                        guardrail: self.guardrail,
-                        selectableValues: self.selectableValues,
-                        guidanceColors: self.guidanceColors
-                    )
-                    .frame(width: availableWidth / 2)
-                    // Ensure overlaid unit label is not clipped
-                    .padding(.trailing, self.unitLabelWidth + self.unitLabelSpacing)
-                    .clipped()
-                } else {
-                    FractionalQuantityPicker(
-                        value: item.value.animation().withUnit(self.unit),
-                        unit: self.unit,
-                        guardrail: self.guardrail,
-                        selectableValues: self.selectableValues,
-                        usageContext: .component(availableWidth: availableWidth)
-                    )
-                }
-            },
-            actionAreaContent: {
-                instructionalContentIfNecessary
-                guardrailWarningIfNecessary
-            },
-            savingMechanism: savingMechanism.pullback { items in
-                DailyQuantitySchedule(unit: self.unit, dailyItems: items)!
-            },
-            mode: mode,
-            therapySettingType: settingType
-        )
-        .onTapGesture {
-            self.userDidTap = true
-        }
-    }
-
-    private var saveConfirmation: SaveConfirmation {
-        crossedThresholds.isEmpty ? .notRequired : .required(confirmationAlertContent)
-    }
-
-    private var unitLabelWidth: CGFloat {
-        let attributedUnitString = NSAttributedString(
-            string: unit.shortLocalizedUnitString(),
-            attributes: [.font: UIFont.preferredFont(forTextStyle: .body)]
-        )
-        return attributedUnitString.size().width
-    }
-
-    private var unitLabelSpacing: CGFloat { 8 }
-    
-    private var instructionalContentIfNecessary: some View {
-        return Group {
-            if mode == .acceptanceFlow && !userDidTap {
-                instructionalContent
-            }
-        }
-    }
-
-    private var instructionalContent: some View {
-        HStack { // to align with guardrail warning, if present
-            VStack (alignment: .leading, spacing: 20) {
-                Text(LocalizedString("You can edit a setting by tapping into any line item.", comment: "Description of how to edit setting"))
-                Text(LocalizedString("You can add entries for different times of day by using the ➕.", comment: "Description of how to add a range"))
-            }
-            .foregroundColor(.secondary)
-            .font(.subheadline)
-            Spacer()
-        }
-    }
-
-    private var guardrailWarningIfNecessary: some View {
-        let crossedThresholds = self.crossedThresholds
-        return Group {
-            if !crossedThresholds.isEmpty && (userDidTap || mode == .settings) {
-                guardrailWarning(crossedThresholds)
-            }
-        }
-    }
-
-    private var crossedThresholds: [SafetyClassification.Threshold] {
-        scheduleItems.lazy
-            .map { HKQuantity(unit: self.unit, doubleValue: $0.value) }
-            .compactMap { quantity in
-                switch guardrail.classification(for: quantity) {
-                case .withinRecommendedRange:
-                    return nil
-                case .outsideRecommendedRange(let threshold):
-                    return threshold
-                }
-        }
-    }
-}
-
-// MARK: - Initializers
-
-extension QuantityScheduleEditor {
-    init(
-        title: Text,
-        description: Text,
-        schedule: DailyQuantitySchedule<Double>?,
-        unit: HKUnit,
-        selectableValues: [Double],
-        guardrail: Guardrail<HKQuantity>,
-        quantitySelectionMode: QuantitySelectionMode = .whole,
-        defaultFirstScheduleItemValue: HKQuantity,
-        scheduleItemLimit: Int = 48,
-        confirmationAlertContent: AlertContent,
-        @ViewBuilder guardrailWarning: @escaping (_ thresholds: [SafetyClassification.Threshold]) -> ActionAreaContent,
-        onSave savingMechanism: SavingMechanism<DailyQuantitySchedule<Double>>,
-        mode: SettingsPresentationMode = .settings,
-        settingType: TherapySetting = .none
-    ) {
-        self.title = title
-        self.description = description
-        self.initialScheduleItems = schedule?.items ?? []
-        self._scheduleItems = State(initialValue: schedule?.items ?? [])
-        self.unit = unit
-        self.quantitySelectionMode = quantitySelectionMode
-        self.selectableValues = selectableValues
-        self.guardrail = guardrail
-        self.defaultFirstScheduleItemValue = defaultFirstScheduleItemValue
-        self.scheduleItemLimit = scheduleItemLimit
-        self.confirmationAlertContent = confirmationAlertContent
-        self.guardrailWarning = guardrailWarning
-        self.savingMechanism = savingMechanism
-        self.mode = mode
-        self.settingType = settingType
-    }
-
-    init(
-        title: Text,
-        description: Text,
-        schedule: DailyQuantitySchedule<Double>?,
-        unit: HKUnit,
-        guardrail: Guardrail<HKQuantity>,
-        selectableValueStride: HKQuantity,
-        quantitySelectionMode: QuantitySelectionMode = .whole,
-        defaultFirstScheduleItemValue: HKQuantity,
-        scheduleItemLimit: Int = 48,
-        confirmationAlertContent: AlertContent,
-        @ViewBuilder guardrailWarning: @escaping (_ thresholds: [SafetyClassification.Threshold]) -> ActionAreaContent,
-        onSave save: @escaping (DailyQuantitySchedule<Double>) -> Void,
-        mode: SettingsPresentationMode = .settings,
-        settingType: TherapySetting = .none
-    ) {
-        let selectableValues = guardrail.allValues(stridingBy: selectableValueStride, unit: unit)
-        self.init(
-            title: title,
-            description: description,
-            schedule: schedule,
-            unit: unit,
-            selectableValues: selectableValues,
-            guardrail: guardrail,
-            quantitySelectionMode: quantitySelectionMode,
-            defaultFirstScheduleItemValue: defaultFirstScheduleItemValue,
-            scheduleItemLimit: scheduleItemLimit,
-            confirmationAlertContent: confirmationAlertContent,
-            guardrailWarning: guardrailWarning,
-            onSave: .synchronous(save),
-            mode: mode,
-            settingType: settingType
-        )
-    }
-}

+ 0 - 435
Dependecies/LoopKit/LoopKitUI/Views/ScheduleEditor.swift

@@ -1,435 +0,0 @@
-//
-//  ScheduleEditor.swift
-//  LoopKitUI
-//
-//  Created by Michael Pangburn on 4/24/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import SwiftUI
-import HealthKit
-import LoopKit
-
-enum SavingMechanism<Value> {
-    case synchronous((_ value: Value) -> Void)
-    case asynchronous((_ value: Value, _ completion: @escaping (Error?) -> Void) -> Void)
-
-    func pullback<NewValue>(_ transform: @escaping (NewValue) -> Value) -> SavingMechanism<NewValue> {
-        switch self {
-        case .synchronous(let save):
-            return .synchronous { newValue in save(transform(newValue)) }
-        case .asynchronous(let save):
-            return .asynchronous { newValue, completion in
-                save(transform(newValue), completion)
-            }
-        }
-    }
-}
-
-enum SaveConfirmation {
-    case required(AlertContent)
-    case notRequired
-}
-
-struct ScheduleEditor<Value: Equatable, ValueContent: View, ValuePicker: View, ActionAreaContent: View>: View {
-    fileprivate enum PresentedAlert {
-        case saveConfirmation(AlertContent)
-        case saveError(Error)
-    }
-
-    var title: Text
-    var description: Text
-    var initialScheduleItems: [RepeatingScheduleValue<Value>]
-    @Binding var scheduleItems: [RepeatingScheduleValue<Value>]
-    var defaultFirstScheduleItemValue: Value
-    var scheduleItemLimit: Int
-    var saveConfirmation: SaveConfirmation
-    var valueContent: (_ value: Value, _ isEditing: Bool) -> ValueContent
-    var valuePicker: (_ item: Binding<RepeatingScheduleValue<Value>>, _ availableWidth: CGFloat) -> ValuePicker
-    var actionAreaContent: ActionAreaContent
-    var savingMechanism: SavingMechanism<[RepeatingScheduleValue<Value>]>
-    var mode: SettingsPresentationMode
-    var therapySettingType: TherapySetting
-    
-    @State var editingIndex: Int?
-
-    @State var isAddingNewItem = false {
-        didSet {
-            if isAddingNewItem {
-                editingIndex = nil
-            }
-        }
-    }
-
-    @State var tableDeletionState: TableDeletionState = .disabled {
-        didSet {
-            if tableDeletionState == .enabled {
-                editingIndex = nil
-            }
-        }
-    }
-
-    @State var isSyncing = false
-
-    @State private var presentedAlert: PresentedAlert?
-
-    @Environment(\.dismiss) var dismiss
-    @Environment(\.authenticate) var authenticate
-
-    init(
-        title: Text,
-        description: Text,
-        scheduleItems: Binding<[RepeatingScheduleValue<Value>]>,
-        initialScheduleItems: [RepeatingScheduleValue<Value>],
-        defaultFirstScheduleItemValue: Value,
-        scheduleItemLimit: Int = 48,
-        saveConfirmation: SaveConfirmation,
-        @ViewBuilder valueContent: @escaping (_ value: Value, _ isEditing: Bool) -> ValueContent,
-        @ViewBuilder valuePicker: @escaping (_ item: Binding<RepeatingScheduleValue<Value>>, _ availableWidth: CGFloat) -> ValuePicker,
-        @ViewBuilder actionAreaContent: () -> ActionAreaContent,
-        savingMechanism: SavingMechanism<[RepeatingScheduleValue<Value>]>,
-        mode: SettingsPresentationMode = .settings,
-        therapySettingType: TherapySetting = .none
-    ) {
-        self.title = title
-        self.description = description
-        self.initialScheduleItems = initialScheduleItems
-        self._scheduleItems = scheduleItems
-        self.defaultFirstScheduleItemValue = defaultFirstScheduleItemValue
-        self.scheduleItemLimit = scheduleItemLimit
-        self.saveConfirmation = saveConfirmation
-        self.valueContent = valueContent
-        self.valuePicker = valuePicker
-        self.actionAreaContent = actionAreaContent()
-        self.savingMechanism = savingMechanism
-        self.mode = mode
-        self.therapySettingType = therapySettingType
-    }
-
-    var body: some View {
-        ZStack {
-            configurationPage
-            .disabled(isSyncing || isAddingNewItem)
-            .zIndex(0)
-
-            if isAddingNewItem {
-                DarkenedOverlay()
-                    .zIndex(1)
-
-                NewScheduleItemEditor(
-                    isPresented: $isAddingNewItem,
-                    initialItem: initialNewScheduleItem,
-                    selectableTimes: scheduleItems.isEmpty
-                        ? .only(.hours(0))
-                        : .allExcept(Set(scheduleItems.map { $0.startTime })),
-                    valuePicker: valuePicker,
-                    onSave: { newItem in
-                        self.scheduleItems.append(newItem)
-                        self.scheduleItems.sort(by: { $0.startTime < $1.startTime })
-                    }
-                )
-                .transition(
-                    AnyTransition
-                        .move(edge: .bottom)
-                        .combined(with: .opacity)
-                )
-                .zIndex(2)
-            }
-        }
-    }
-    
-    private var configurationPage: some View {
-        switch mode {
-        case .acceptanceFlow:
-            return AnyView(page)
-        case .settings:
-            return AnyView(pageWithCancel)
-        }
-    }
-        
-    private var pageWithCancel: some View {
-        switch saveButtonState {
-        case .disabled, .loading:
-            return AnyView(page
-                .navigationBarBackButtonHidden(false)
-                .navigationBarItems(leading: EmptyView(), trailing: trailingNavigationItems)
-            )
-        case .enabled:
-            return AnyView(page
-                .navigationBarBackButtonHidden(true)
-                .navigationBarItems(leading: cancelButton, trailing: trailingNavigationItems)
-            )
-        }
-    }
-    
-    private var page: some View {
-        ConfigurationPage(
-            title: title,
-            actionButtonTitle: Text(mode.buttonText),
-            actionButtonState: saveButtonState,
-            cards: {
-                // TODO: Remove conditional when Swift 5.3 ships
-                // https://bugs.swift.org/browse/SR-11628
-                if true {
-                    Card {
-                        SettingDescription(text: description, informationalContent: {self.therapySettingType.helpScreen()})
-                        Splat(Array(scheduleItems.enumerated()), id: \.element.startTime) { index, item in
-                            self.itemView(for: item, at: index)
-                        }
-                    }
-                }
-            },
-            actionAreaContent: {
-                actionAreaContent
-            },
-            action: {
-                switch self.saveConfirmation {
-                case .required(let alertContent):
-                    self.presentedAlert = .saveConfirmation(alertContent)
-                case .notRequired:
-                    self.startSaving()
-                }
-            }
-        )
-        .alert(item: $presentedAlert, content: alert(for:))
-        .navigationBarTitle("", displayMode: .inline)
-        .navigationBarItems(
-            trailing: trailingNavigationItems
-        )
-    }
-
-    private var saveButtonState: ConfigurationPageActionButtonState {
-        if isSyncing {
-            return .loading
-        }
-
-        let isEnabled = !scheduleItems.isEmpty
-            && (scheduleItems != initialScheduleItems || mode == .acceptanceFlow)
-            && tableDeletionState == .disabled
-
-        return isEnabled ? .enabled : .disabled
-    }
-
-    private func itemView(for item: RepeatingScheduleValue<Value>, at index: Int) -> some View {
-        Deletable(
-            tableDeletionState: $tableDeletionState,
-            index: index,
-            isDeletable: index != 0,
-            onDelete: {
-                withAnimation {
-                    self.scheduleItems.remove(at: index)
-
-                    if self.scheduleItems.count == 1 {
-                        self.tableDeletionState = .disabled
-                    }
-                }
-            }
-        ) {
-            ScheduleItemView(
-                time: item.startTime,
-                isEditing: isEditing(index),
-                valueContent: {
-                    valueContent(item.value, isEditing(index).wrappedValue)
-                },
-                expandedContent: {
-                    ScheduleItemPicker(
-                        item: $scheduleItems[index],
-                        isTimeSelectable: { self.isTimeSelectable($0, at: index) },
-                        valuePicker: { self.valuePicker(self.$scheduleItems[index], $0) }
-                    )
-                }
-            )
-        }
-        .accessibility(identifier: "schedule_item_\(index)")
-    }
-
-    private func isEditing(_ index: Int) -> Binding<Bool> {
-        Binding(
-            get: { index == self.editingIndex },
-            set: { isNowEditing in
-                self.editingIndex = isNowEditing ? index : nil
-            }
-        )
-    }
-
-    private func isTimeSelectable(_ time: TimeInterval, at index: Int) -> Bool {
-        if index == scheduleItems.startIndex {
-            return time == .hours(0)
-        }
-
-        let priorTime = scheduleItems[index - 1].startTime
-        guard time > priorTime else {
-            return false
-        }
-
-        if index < scheduleItems.endIndex - 1 {
-            let nextTime = scheduleItems[index + 1].startTime
-            guard time < nextTime else {
-                return false
-            }
-        }
-
-        return true
-    }
-
-    private var initialNewScheduleItem: RepeatingScheduleValue<Value> {
-        assert(scheduleItems.count <= scheduleItemLimit)
-
-        if scheduleItems.isEmpty {
-            return RepeatingScheduleValue(startTime: .hours(0), value: defaultFirstScheduleItemValue)
-        }
-
-        if scheduleItems.last!.startTime == .hours(23.5) {
-            let firstItemFollowedByOpening = scheduleItems.adjacentPairs().first(where: { item, next in
-                next.startTime - item.startTime > .minutes(30)
-            })!.0
-            return RepeatingScheduleValue(
-                startTime: firstItemFollowedByOpening.startTime + .minutes(30),
-                value: firstItemFollowedByOpening.value
-            )
-        } else {
-            return RepeatingScheduleValue(
-                startTime: scheduleItems.last!.startTime + .minutes(30),
-                value: scheduleItems.last!.value
-            )
-        }
-    }
-
-    private var trailingNavigationItems: some View {
-        // TODO: SwiftUI's alignment of these buttons in the navigation bar is a little funky.
-        // Tapping 'Edit' then 'Done' can shift '+' slightly.
-        HStack(spacing: 24) {
-            if tableDeletionState == .disabled {
-                editButton
-            } else {
-                doneButton
-            }
-
-            addButton
-        }
-    }
-
-    var cancelButton: some View {
-        Button(action: { self.dismiss() } ) { Text(LocalizedString("Cancel", comment: "Cancel editing settings button title")) }
-    }
-
-    var editButton: some View {
-        Button(
-            action: {
-                withAnimation {
-                    self.tableDeletionState = .enabled
-                }
-            },
-            label: {
-                Text(LocalizedString("Edit", comment: "Text for edit button"))
-            }
-        )
-        .disabled(scheduleItems.count == 1)
-    }
-
-    var doneButton: some View {
-        Button(
-            action: {
-                withAnimation {
-                    self.tableDeletionState = .disabled
-                }
-            },
-            label: {
-                Text(LocalizedString("Done", comment: "Text for done button")).bold()
-            }
-        )
-    }
-
-    var addButton: some View {
-        Button(
-            action: {
-                withAnimation {
-                    self.isAddingNewItem = true
-                }
-            },
-            label: {
-                Image(systemName: "plus")
-                    .imageScale(.large)
-                    .contentShape(Rectangle())
-            }
-        )
-        .disabled(tableDeletionState != .disabled || scheduleItems.count >= scheduleItemLimit)
-    }
-
-    private func startSaving() {
-        guard mode == .settings else {
-            self.continueSaving()
-            return
-        }
-        
-        authenticate(therapySettingType.authenticationChallengeDescription) {
-            switch $0 {
-            case .success: self.continueSaving()
-            case .failure: break
-            }
-        }
-    }
-    
-    private func continueSaving() {
-
-        switch savingMechanism {
-        case .synchronous(let save):
-            save(scheduleItems)
-        case .asynchronous(let save):
-            withAnimation {
-                self.editingIndex = nil
-                self.isSyncing = true
-            }
-
-            save(scheduleItems) { error in
-                DispatchQueue.main.async {
-                    if let error = error {
-                        withAnimation {
-                            self.isSyncing = false
-                        }
-                        self.presentedAlert = .saveError(error)
-                    }
-                }
-            }
-        }
-    }
-
-    private func alert(for presentedAlert: PresentedAlert) -> SwiftUI.Alert {
-        switch presentedAlert {
-        case .saveConfirmation(let content):
-            return Alert(
-                title: content.title,
-                message: content.message,
-                primaryButton: .cancel(Text(LocalizedString("Go Back", comment: "Button text to return to editing a schedule after from alert popup when some schedule values are outside the recommended range"))),
-                secondaryButton: .default(
-                    Text(LocalizedString("Continue", comment: "Button text to confirm saving from alert popup when some schedule values are outside the recommended range")),
-                    action: startSaving
-                )
-            )
-        case .saveError(let error):
-            return Alert(
-                title: Text(LocalizedString("Unable to Save", comment: "Alert title when error occurs while saving a schedule")),
-                message: Text(error.localizedDescription)
-            )
-        }
-    }
-}
-
-struct DarkenedOverlay: View {
-    var body: some View {
-        Rectangle()
-            .fill(Color.black.opacity(0.3))
-            .edgesIgnoringSafeArea(.all)
-    }
-}
-
-extension ScheduleEditor.PresentedAlert: Identifiable {
-    var id: Int {
-        switch self {
-        case .saveConfirmation:
-            return 0
-        case .saveError:
-            return 1
-        }
-    }
-}

+ 0 - 173
Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/BasalRateScheduleEditor.swift

@@ -1,173 +0,0 @@
-//
-//  BasalRateScheduleEditor.swift
-//  LoopKitUI
-//
-//  Created by Michael Pangburn on 4/20/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import SwiftUI
-import HealthKit
-import LoopKit
-
-
-public struct BasalRateScheduleEditor: View {
-    var schedule: DailyQuantitySchedule<Double>?
-    var supportedBasalRates: [Double]
-    var guardrail: Guardrail<HKQuantity>
-    var maximumScheduleEntryCount: Int
-    var syncSchedule: PumpManager.SyncSchedule?
-    var save: (BasalRateSchedule) -> Void
-    let mode: SettingsPresentationMode
-    @Environment(\.appName) private var appName
-
-    /// - Precondition: `supportedBasalRates` is nonempty and sorted in ascending order.
-    public init(
-        schedule: BasalRateSchedule?,
-        supportedBasalRates: [Double],
-        maximumBasalRate: Double?,
-        maximumScheduleEntryCount: Int,
-        syncSchedule: PumpManager.SyncSchedule?,
-        onSave save: @escaping (BasalRateSchedule) -> Void,
-        mode: SettingsPresentationMode = .settings
-    ) {
-        self.schedule = schedule.map { schedule in
-            DailyQuantitySchedule(
-                unit: .internationalUnitsPerHour,
-                dailyItems: schedule.items
-            )!
-        }
-
-        if let maxBasal = maximumBasalRate {
-            let partitioningIndex = supportedBasalRates.partitioningIndex(where: { $0 > maxBasal })
-            self.supportedBasalRates = Array(supportedBasalRates[..<partitioningIndex])
-        } else {
-            self.supportedBasalRates = supportedBasalRates
-        }
-
-        self.guardrail = Guardrail.basalRate(supportedBasalRates: supportedBasalRates)
-        self.maximumScheduleEntryCount = maximumScheduleEntryCount
-        self.syncSchedule = syncSchedule
-        self.save = save
-        self.mode = mode
-        
-        self.supportedBasalRates.removeAll(where: {
-            !self.guardrail.absoluteBounds.contains(HKQuantity(unit: .internationalUnitsPerHour, doubleValue: $0))
-        })
-    }
-    
-    public init(
-        viewModel: TherapySettingsViewModel,
-        didSave: (() -> Void)? = nil
-    ) {
-        self.init(
-            schedule: viewModel.therapySettings.basalRateSchedule,
-            supportedBasalRates: viewModel.pumpSupportedIncrements!()!.basalRates ,
-            maximumBasalRate: viewModel.therapySettings.maximumBasalRatePerHour,
-            maximumScheduleEntryCount: viewModel.pumpSupportedIncrements!()!.maximumBasalScheduleEntryCount,
-            syncSchedule: viewModel.syncPumpSchedule?(),
-            onSave: { [weak viewModel] newBasalRates in
-                viewModel?.saveBasalRates(basalRates: newBasalRates)
-                didSave?()
-            },
-            mode: viewModel.mode
-        )
-    }
-
-    public var body: some View {
-        QuantityScheduleEditor(
-            title: Text(TherapySetting.basalRate.title),
-            description: description,
-            schedule: schedule,
-            unit: .internationalUnitsPerHour,
-            selectableValues: supportedBasalRates,
-            guardrail: guardrail,
-            quantitySelectionMode: .fractional,
-            defaultFirstScheduleItemValue: guardrail.absoluteBounds.lowerBound,
-            scheduleItemLimit: maximumScheduleEntryCount,
-            confirmationAlertContent: confirmationAlertContent,
-            guardrailWarning: {
-                BasalRateGuardrailWarning(
-                    crossedThresholds: $0,
-                    isZeroUnitRateSelectable: self.supportedBasalRates.first! == 0
-                )
-            },
-            onSave: savingMechanism,
-            mode: mode,
-            settingType: .basalRate
-        )
-    }
-    
-    private var description: Text {
-        Text(TherapySetting.basalRate.descriptiveText(appName: appName))
-    }
-
-    private var confirmationAlertContent: AlertContent {
-        AlertContent(
-            title: Text(LocalizedString("Save Basal Rates?", comment: "Alert title for confirming basal rates outside the recommended range")),
-            message: Text(TherapySetting.basalRate.guardrailSaveWarningCaption)
-        )
-    }
-    
-    private var savingMechanism: SavingMechanism<DailyQuantitySchedule<Double>> {
-        switch mode {
-        case .settings:
-            return .asynchronous { quantitySchedule, completion in
-                precondition(self.syncSchedule != nil)
-                self.syncSchedule?(quantitySchedule.items) { result in
-                    switch result {
-                    case .success(let syncedSchedule):
-                        DispatchQueue.main.async {
-                            self.save(syncedSchedule)
-                        }
-                        completion(nil)
-                    case .failure(let error):
-                        completion(error)
-                    }
-                }
-            }
-        case .acceptanceFlow:
-            // TODO: get timezone from pump
-            return .synchronous { quantitySchedule in
-                let schedule = BasalRateSchedule(dailyItems: quantitySchedule.items, timeZone: .currentFixed)!
-                self.save(schedule)
-            }
-        }
-    }
-}
-
-private struct BasalRateGuardrailWarning: View {
-    var crossedThresholds: [SafetyClassification.Threshold]
-    var isZeroUnitRateSelectable: Bool
-
-    var body: some View {
-        assert(!crossedThresholds.isEmpty)
-
-        let caption = self.isZeroUnitRateSelectable && crossedThresholds.allSatisfy({ $0 == .minimum })
-            ? Text(LocalizedString("A value of 0 U/hr means you will be scheduled to receive no basal insulin.", comment: "Warning text for basal rate of 0 U/hr"))
-            : nil
-
-        return GuardrailWarning(
-            title: crossedThresholds.count == 1 ? singularWarningTitle(for: crossedThresholds.first!) : multipleWarningTitle,
-            thresholds: crossedThresholds,
-            caption: caption
-        )
-    }
-
-    private func singularWarningTitle(for threshold: SafetyClassification.Threshold) -> Text {
-        switch threshold {
-        case .minimum where isZeroUnitRateSelectable:
-            return Text(LocalizedString("No Basal Insulin", comment: "Title text for the zero basal rate warning"))
-        case .minimum, .belowRecommended:
-            return Text(LocalizedString("Low Basal Rate", comment: "Title text for the low basal rate warning"))
-        case .aboveRecommended, .maximum:
-            return Text(LocalizedString("High Basal Rate", comment: "Title text for the high basal rate warning"))
-        }
-    }
-
-    private var multipleWarningTitle: Text {
-        isZeroUnitRateSelectable && crossedThresholds.allSatisfy({ $0 == .minimum })
-            ? Text(LocalizedString("No Basal Insulin", comment: "Title text for the zero basal rate warning"))
-            : Text(LocalizedString("Basal Rates", comment: "Title text for multi-value basal rate warning"))
-    }
-}

+ 0 - 112
Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/CarbRatioScheduleEditor.swift

@@ -1,112 +0,0 @@
-//
-//  CarbRatioScheduleEditor.swift
-//  LoopKitUI
-//
-//  Created by Michael Pangburn on 4/20/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import SwiftUI
-import HealthKit
-import LoopKit
-
-
-fileprivate extension HKUnit {
-    static let storedCarbRatioScheduleUnit = HKUnit.gram()
-    static let realCarbRatioScheduleUnit = HKUnit.gramsPerUnit
-}
-
-public struct CarbRatioScheduleEditor: View {
-    private var schedule: DailyQuantitySchedule<Double>?
-    private var mode: SettingsPresentationMode
-    private var save: (CarbRatioSchedule) -> Void
-    @Environment(\.appName) private var appName
-
-    public init(
-        schedule: CarbRatioSchedule?,
-        onSave save: @escaping (CarbRatioSchedule) -> Void,
-        mode: SettingsPresentationMode = .settings
-    ) {
-        // CarbRatioSchedule stores only the gram unit.
-        // For consistency across display & computation, convert to "real" g/U units.
-        self.schedule = schedule.map { schedule in
-            DailyQuantitySchedule(
-                unit: .realCarbRatioScheduleUnit,
-                dailyItems: schedule.items
-            )!
-        }
-        self.mode = mode
-        self.save = save
-    }
-    
-    public init(
-        viewModel: TherapySettingsViewModel,
-        didSave: (() -> Void)? = nil
-    ) {
-        self.init(
-            schedule: viewModel.therapySettings.carbRatioSchedule,
-            onSave: { [weak viewModel] in
-                viewModel?.saveCarbRatioSchedule(carbRatioSchedule: $0)
-                didSave?()
-            },
-            mode: viewModel.mode
-        )
-    }
-
-    public var body: some View  {
-        QuantityScheduleEditor(
-            title: Text(TherapySetting.carbRatio.title),
-            description: description,
-            schedule: schedule,
-            unit: .realCarbRatioScheduleUnit,
-            guardrail: .carbRatio,
-            selectableValueStride: HKQuantity(unit: .realCarbRatioScheduleUnit, doubleValue: 0.01),
-            quantitySelectionMode: .fractional,
-            defaultFirstScheduleItemValue: Guardrail.carbRatio.startingSuggestion ?? Guardrail.carbRatio.recommendedBounds.upperBound,
-            confirmationAlertContent: confirmationAlertContent,
-            guardrailWarning: CarbRatioGuardrailWarning.init(crossedThresholds:),
-            onSave: {
-                // Convert back to the expected gram-unit-only schedule.
-                self.save(DailyQuantitySchedule(unit: .storedCarbRatioScheduleUnit, dailyItems: $0.items)!)
-            },
-            mode: mode,
-            settingType: .carbRatio
-        )
-    }
-
-    private var description: Text {
-        Text(TherapySetting.carbRatio.descriptiveText(appName: appName))
-    }
-
-    private var confirmationAlertContent: AlertContent {
-        AlertContent(
-            title: Text(LocalizedString("Save Carb Ratios?", comment: "Alert title for confirming carb ratios outside the recommended range")),
-            message: Text(TherapySetting.carbRatio.guardrailSaveWarningCaption)
-        )
-    }
-}
-
-private struct CarbRatioGuardrailWarning: View {
-    var crossedThresholds: [SafetyClassification.Threshold]
-
-    var body: some View {
-        assert(!crossedThresholds.isEmpty)
-        return GuardrailWarning(
-            title: crossedThresholds.count == 1 ? singularWarningTitle(for: crossedThresholds.first!) : multipleWarningTitle,
-            thresholds: crossedThresholds
-        )
-    }
-
-    private func singularWarningTitle(for threshold: SafetyClassification.Threshold) -> Text {
-        switch threshold {
-        case .minimum, .belowRecommended:
-            return Text(LocalizedString("Low Carb Ratio", comment: "Title text for the low carb ratio warning"))
-        case .aboveRecommended, .maximum:
-            return Text(LocalizedString("High Carb Ratio", comment: "Title text for the high carb ratio warning"))
-        }
-    }
-
-    private var multipleWarningTitle: Text {
-        Text(LocalizedString("Carb Ratios", comment: "Title text for multi-value carb ratio warning"))
-    }
-}

+ 0 - 367
Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/CorrectionRangeOverridesEditor.swift

@@ -1,367 +0,0 @@
-//
-//  CorrectionRangeOverridesEditor.swift
-//  LoopKitUI
-//
-//  Created by Michael Pangburn on 5/15/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import SwiftUI
-import HealthKit
-import LoopKit
-
-public struct CorrectionRangeOverridesEditor: View {
-    let initialValue: CorrectionRangeOverrides
-    let preset: CorrectionRangeOverrides.Preset
-    let suspendThreshold: GlucoseThreshold?
-    let unit: HKUnit
-    var correctionRangeScheduleRange: ClosedRange<HKQuantity>
-    var minValue: HKQuantity?
-    var save: (_ overrides: CorrectionRangeOverrides) -> Void
-    var sensitivityOverridesEnabled: Bool
-    var mode: SettingsPresentationMode
-
-    @State private var userDidTap: Bool = false
-
-    @State var value: CorrectionRangeOverrides
-
-    @State var presetBeingEdited: CorrectionRangeOverrides.Preset? {
-        didSet {
-            if let presetBeingEdited = presetBeingEdited, value.ranges[presetBeingEdited] == nil {
-                value.ranges[presetBeingEdited] = initiallySelectedValue(for: presetBeingEdited)
-            }
-        }
-    }
-
-    @State var showingConfirmationAlert = false
-    @Environment(\.dismiss) var dismiss
-    @Environment(\.authenticate) var authenticate
-
-    fileprivate init(
-        value: CorrectionRangeOverrides,
-        preset: CorrectionRangeOverrides.Preset,
-        unit: HKUnit,
-        correctionRangeScheduleRange: ClosedRange<HKQuantity>,
-        minValue: HKQuantity?,
-        onSave save: @escaping (_ overrides: CorrectionRangeOverrides) -> Void,
-        sensitivityOverridesEnabled: Bool,
-        suspendThreshold: GlucoseThreshold?,
-        mode: SettingsPresentationMode = .settings
-    ) {
-        self._value = State(initialValue: value)
-        self.initialValue = value
-        self.preset = preset
-        self.unit = unit
-        self.correctionRangeScheduleRange = correctionRangeScheduleRange
-        self.minValue = minValue
-        self.save = save
-        self.sensitivityOverridesEnabled = sensitivityOverridesEnabled
-        self.suspendThreshold = suspendThreshold
-        self.mode = mode
-    }
-    
-    public init(
-        viewModel: TherapySettingsViewModel,
-        preset: CorrectionRangeOverrides.Preset,
-        didSave: (() -> Void)? = nil
-    ) {
-        self.init(
-            value: CorrectionRangeOverrides(
-                preMeal: viewModel.therapySettings.preMealTargetRange,
-                workout: viewModel.therapySettings.workoutTargetRange,
-                unit: viewModel.therapySettings.glucoseUnit!
-            ),
-            preset: preset,
-            unit: viewModel.therapySettings.glucoseUnit!,
-            correctionRangeScheduleRange: viewModel.therapySettings.glucoseTargetRangeSchedule!.scheduleRange(),
-            minValue: viewModel.therapySettings.suspendThreshold?.quantity,
-            onSave: { [weak viewModel] overrides in
-                let glucoseUnit = viewModel?.therapySettings.glucoseUnit ?? .milligramsPerDeciliter
-                switch preset {
-                case .preMeal:
-                    viewModel?.saveCorrectionRangeOverride(preMeal: overrides.preMeal, unit: glucoseUnit)
-                case .workout:
-                    viewModel?.saveCorrectionRangeOverride(workout: overrides.workout, unit: glucoseUnit)
-                }
-                didSave?()
-            },
-            sensitivityOverridesEnabled: viewModel.sensitivityOverridesEnabled,
-            suspendThreshold: viewModel.therapySettings.suspendThreshold,
-            mode: viewModel.mode
-        )
-    }
-
-    public var body: some View {
-        switch mode {
-        case .settings: return AnyView(contentWithCancel)
-        case .acceptanceFlow: return AnyView(content)
-        }
-    }
-    
-    private var contentWithCancel: some View {
-        if value == initialValue {
-            return AnyView(content
-                .navigationBarBackButtonHidden(false)
-                .navigationBarItems(leading: EmptyView())
-            )
-        } else {
-            return AnyView(content
-                .navigationBarBackButtonHidden(true)
-                .navigationBarItems(leading: cancelButton)
-            )
-        }
-    }
-    
-    private var cancelButton: some View {
-        Button(action: { self.dismiss() } ) { Text(LocalizedString("Cancel", comment: "Cancel editing settings button title")) }
-    }
-    
-    private var content: some View {
-        ConfigurationPage(
-            title: Text(preset.therapySetting.title),
-            actionButtonTitle: Text(mode.buttonText),
-            actionButtonState: value != initialValue || mode == .acceptanceFlow ? .enabled : .disabled,
-            cards: {
-                // TODO: Figure out why I need to explicitly return a CardStack with 1 card here
-                CardStack(cards: [card(for: preset)])
-            },
-            actionAreaContent: {
-                instructionalContentIfNecessary
-                guardrailWarningIfNecessary
-            },
-            action: {
-                if self.crossedThresholds.isEmpty {
-                    self.startSaving()
-                } else {
-                    self.showingConfirmationAlert = true
-                }
-            }
-        )
-        .alert(isPresented: $showingConfirmationAlert, content: confirmationAlert)
-        .navigationBarTitle("", displayMode: .inline)
-        .onTapGesture {
-            self.userDidTap = true
-        }
-    }
-
-    private func card(for preset: CorrectionRangeOverrides.Preset) -> Card {
-        Card {
-            SettingDescription(text: description(of: preset), informationalContent: { preset.therapySetting.helpScreen() })
-            CorrectionRangeOverridesExpandableSetting(
-                isEditing: Binding(
-                    get: { self.presetBeingEdited == preset },
-                    set: { isEditing in
-                        withAnimation {
-                            self.presetBeingEdited = isEditing ? preset : nil
-                        }
-                }),
-                value: $value,
-                preset: preset,
-                unit: unit,
-                suspendThreshold: suspendThreshold,
-                correctionRangeScheduleRange: correctionRangeScheduleRange,
-                expandedContent: {
-                    GlucoseRangePicker(
-                        range: Binding(
-                            get: { self.value.ranges[preset] ?? self.initiallySelectedValue(for: preset) },
-                            set: { newValue in
-                                withAnimation {
-                                    self.value.ranges[preset] = newValue
-                                }
-                        }
-                        ),
-                        unit: self.unit,
-                        minValue: self.selectableBounds(for: preset).lowerBound,
-                        maxValue: self.selectableBounds(for: preset).upperBound,
-                        guardrail: self.guardrail(for: preset)
-                    )
-                    .accessibility(identifier: "\(self.accessibilityIdentifier(for: preset))_picker")
-            })
-        }
-    }
-
-    private func description(of preset: CorrectionRangeOverrides.Preset) -> Text {
-        switch preset {
-        case .preMeal:
-            return Text(preset.descriptiveText)
-        case .workout:
-            return Text(preset.descriptiveText)
-        }
-    }
-    
-    private func guardrail(for preset: CorrectionRangeOverrides.Preset) -> Guardrail<HKQuantity> {
-        return Guardrail.correctionRangeOverride(for: preset, correctionRangeScheduleRange: correctionRangeScheduleRange,
-                                                 suspendThreshold: suspendThreshold)
-    }
-    
-    private var instructionalContentIfNecessary: some View {
-        return Group {
-            if mode == .acceptanceFlow && !userDidTap {
-                instructionalContent
-            }
-        }
-    }
-
-    private var instructionalContent: some View {
-        HStack { // to align with guardrail warning, if present
-            Text(LocalizedString("You can edit a setting by tapping into any line item.", comment: "Description of how to edit setting"))
-            .foregroundColor(.secondary)
-            .font(.subheadline)
-            Spacer()
-        }
-    }
-
-    private func selectableBounds(for preset: CorrectionRangeOverrides.Preset) -> ClosedRange<HKQuantity> {
-        guardrail(for: preset).absoluteBounds
-    }
-
-    private func initiallySelectedValue(for preset: CorrectionRangeOverrides.Preset) -> ClosedRange<HKQuantity> {
-        guardrail(for: preset).recommendedBounds.clamped(to: selectableBounds(for: preset))
-    }
-
-    private var guardrailWarningIfNecessary: some View {
-        let crossedThresholds = self.crossedThresholds
-        return Group {
-            if !crossedThresholds.isEmpty && (userDidTap || mode == .settings) {
-                CorrectionRangeOverridesGuardrailWarning(crossedThresholds: crossedThresholds, preset: preset)
-            }
-        }
-    }
-
-    private var crossedThresholds: [SafetyClassification.Threshold] {
-        guard let range = value.ranges[preset] else { return [] }
-        
-        let guardrail = self.guardrail(for: preset)
-        let thresholds: [SafetyClassification.Threshold] = [range.lowerBound, range.upperBound].compactMap { bound in
-            switch guardrail.classification(for: bound) {
-            case .withinRecommendedRange:
-                return nil
-            case .outsideRecommendedRange(let threshold):
-                return threshold
-            }
-        }
-        
-        return thresholds
-    }
-
-    private func confirmationAlert() -> SwiftUI.Alert {
-        let title: Text
-        switch preset {
-        case .preMeal:
-            title = Text(LocalizedString("Save Pre-Meal Range?", comment: "Alert title for confirming pre-meal range overrides outside the recommended range"))
-        case .workout:
-            title = Text(LocalizedString("Save Workout Range?", comment: "Alert title for confirming workout range overrides outside the recommended range"))
-        }
-        
-        return SwiftUI.Alert(
-            title: title,
-            // For the message, preMeal and workout are the same
-            message: Text(TherapySetting.preMealCorrectionRangeOverride.guardrailSaveWarningCaption),
-            primaryButton: .cancel(Text(LocalizedString("Go Back", comment: "Text for go back action on confirmation alert"))),
-            secondaryButton: .default(
-                Text(LocalizedString("Continue", comment: "Text for continue action on confirmation alert")),
-                action: startSaving
-            )
-        )
-    }
-    
-    private func startSaving() {
-        guard mode == .settings else {
-            self.continueSaving()
-            return
-        }
-        authenticate(preset.therapySetting.authenticationChallengeDescription) {
-            switch $0 {
-            case .success: self.continueSaving()
-            case .failure: break
-            }
-        }
-    }
-    
-    private func continueSaving() {
-        self.save(self.value)
-    }
-
-    private func accessibilityIdentifier(for preset: CorrectionRangeOverrides.Preset) -> String {
-        switch preset {
-        case .preMeal:
-            return "pre-meal"
-        case .workout:
-            return "workout"
-        }
-    }
-}
-
-private struct CorrectionRangeOverridesGuardrailWarning: View {
-    var crossedThresholds: [SafetyClassification.Threshold]
-    var preset: CorrectionRangeOverrides.Preset
-    
-    var body: some View {
-        assert(!crossedThresholds.isEmpty)
-        return GuardrailWarning(
-            title: title,
-            thresholds: crossedThresholds,
-            caption: caption
-        )
-    }
-
-    private var title: Text {
-        if crossedThresholds.count == 1 {
-            return singularWarningTitle(for: crossedThresholds.first!)
-        } else {
-            return multipleWarningTitle
-        }
-    }
-
-    private func singularWarningTitle(for threshold: SafetyClassification.Threshold) -> Text {
-        switch threshold {
-        case .minimum, .belowRecommended:
-            switch preset {
-            case .preMeal:
-                return Text(LocalizedString("Low Pre-Meal Value", comment: "Title text for the low pre-meal value warning"))
-            case .workout:
-                return Text(LocalizedString("Low Workout Value", comment: "Title text for the low workout value warning"))
-            }
-        case .aboveRecommended, .maximum:
-            switch preset {
-            case .preMeal:
-                return Text(LocalizedString("High Pre-Meal Value", comment: "Title text for the low pre-meal value warning"))
-            case .workout:
-                return Text(LocalizedString("High Workout Value", comment: "Title text for the high workout value warning"))
-            }
-        }
-    }
-
-    private var multipleWarningTitle: Text {
-        switch preset {
-        case .preMeal:
-            return Text(LocalizedString("Pre-Meal Values", comment: "Title text for multi-value pre-meal value warning"))
-        case .workout:
-            return Text(LocalizedString("Workout Values", comment: "Title text for multi-value workout value warning"))
-        }
-    }
-
-    var caption: Text? {
-        guard
-            preset == .preMeal,
-            crossedThresholds.allSatisfy({ $0 == .aboveRecommended || $0 == .maximum })
-        else {
-            return nil
-        }
-        
-        return Text(crossedThresholds.count > 1 ? TherapySetting.preMealCorrectionRangeOverride.guardrailCaptionForOutsideValues : TherapySetting.preMealCorrectionRangeOverride.guardrailCaptionForHighValue)
-    }
-}
-
-public extension CorrectionRangeOverrides.Preset {
-    
-    var descriptiveText: String {
-        switch self {
-        case .preMeal:
-            return LocalizedString("Temporarily lower your glucose target before a meal to impact post-meal glucose spikes.", comment: "Description of pre-meal mode")
-        case .workout:
-            return LocalizedString("Temporarily raise your glucose target before, during, or after physical activity to reduce the risk of low glucose events.", comment: "Description of workout mode")
-        }
-    }
-
-}

+ 0 - 50
Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/CorrectionRangeOverridesExpandableSetting.swift

@@ -1,50 +0,0 @@
-//
-//  CorrectionRangeOverridesExpandableSetting.swift
-//  LoopKitUI
-//
-//  Created by Rick Pasetto on 7/13/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import SwiftUI
-import HealthKit
-import LoopKit
-
-
-public struct CorrectionRangeOverridesExpandableSetting<ExpandedContent: View>: View {
-    @Environment(\.carbTintColor) var carbTintColor
-    @Environment(\.glucoseTintColor) var glucoseTintColor
-    @Binding var isEditing: Bool
-    @Binding var value: CorrectionRangeOverrides
-    let preset: CorrectionRangeOverrides.Preset
-    let unit: HKUnit
-    let suspendThreshold: GlucoseThreshold?
-    var correctionRangeScheduleRange: ClosedRange<HKQuantity>
-    var expandedContent: () -> ExpandedContent
-
-    public var body: some View {
-        ExpandableSetting(
-            isEditing: $isEditing,
-            leadingValueContent: {
-                HStack {
-                    preset.icon(usingCarbTintColor: carbTintColor, orGlucoseTintColor: glucoseTintColor)
-                    Text(preset.title)
-                }
-            },
-            trailingValueContent: {
-                GuardrailConstrainedQuantityRangeView(
-                    range: value.ranges[preset],
-                    unit: unit,
-                    guardrail: self.guardrail(for: preset),
-                    isEditing: isEditing,
-                    forceDisableAnimations: true
-                )
-            },
-            expandedContent: expandedContent
-        )
-    }
-
-    private func guardrail(for preset: CorrectionRangeOverrides.Preset) -> Guardrail<HKQuantity> {
-        return Guardrail.correctionRangeOverride(for: preset, correctionRangeScheduleRange: correctionRangeScheduleRange, suspendThreshold: suspendThreshold)
-    }
-}

+ 0 - 29
Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/CorrectionRangeOverridesExtension.swift

@@ -1,29 +0,0 @@
-//
-//  CorrectionRangeOverridesExtension.swift
-//  LoopKitUI
-//
-//  Created by Rick Pasetto on 7/15/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import LoopKit
-import SwiftUI
-
-extension CorrectionRangeOverrides.Preset {
-    public func icon(usingCarbTintColor carbTintColor: Color,
-                     orGlucoseTintColor glucoseTintColor: Color) -> some View
-    {
-        switch self {
-        case .preMeal:
-            return icon(named: "Pre-Meal", tinted: carbTintColor)
-        case .workout:
-            return icon(named: "workout", tinted: glucoseTintColor)
-        }
-    }
-        
-    private func icon(named name: String, tinted color: Color) -> some View {
-        Image(name)
-            .renderingMode(.template)
-            .foregroundColor(color)
-    }
-}

+ 0 - 194
Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/CorrectionRangeScheduleEditor.swift

@@ -1,194 +0,0 @@
-//
-//  CorrectionRangeScheduleEditor.swift
-//  LoopKitUI
-//
-//  Created by Michael Pangburn on 5/14/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import SwiftUI
-import HealthKit
-import LoopKit
-
-
-public struct CorrectionRangeScheduleEditor: View {
-    var initialSchedule: GlucoseRangeSchedule?
-    @State var scheduleItems: [RepeatingScheduleValue<DoubleRange>]
-    var unit: HKUnit
-    var minValue: HKQuantity?
-    var save: (GlucoseRangeSchedule) -> Void
-    let guardrail = Guardrail.correctionRange
-    let mode: SettingsPresentationMode
-    @Environment(\.appName) private var appName
-    @State private var userDidTap: Bool = false
-    
-    fileprivate init(
-        schedule: GlucoseRangeSchedule?,
-        unit: HKUnit,
-        minValue: HKQuantity?,
-        onSave save: @escaping (GlucoseRangeSchedule) -> Void,
-        mode: SettingsPresentationMode = .settings
-    ) {
-        self.initialSchedule = schedule
-        self._scheduleItems = State(initialValue: schedule?.items ?? [])
-        self.unit = unit
-        self.minValue = minValue
-        self.save = save
-        self.mode = mode
-    }
-    
-    public init(
-           viewModel: TherapySettingsViewModel,
-           didSave: (() -> Void)? = nil
-    ) {
-        self.init(
-            schedule: viewModel.therapySettings.glucoseTargetRangeSchedule,
-            unit: viewModel.therapySettings.glucoseTargetRangeSchedule?.unit ?? viewModel.preferredGlucoseUnit,
-            minValue: Guardrail.minCorrectionRangeValue(suspendThreshold: viewModel.therapySettings.suspendThreshold),
-            onSave: { [weak viewModel] newSchedule in
-                viewModel?.saveCorrectionRange(range: newSchedule)
-                didSave?()
-            },
-            mode: viewModel.mode
-        )
-    }
-
-    public var body: some View {
-        ScheduleEditor(
-            title: Text(TherapySetting.glucoseTargetRange.title),
-            description: description,
-            scheduleItems: $scheduleItems,
-            initialScheduleItems: initialSchedule?.items ?? [],
-            defaultFirstScheduleItemValue: defaultFirstScheduleItemValue,
-            saveConfirmation: saveConfirmation,
-            valueContent: { range, isEditing in
-                GuardrailConstrainedQuantityRangeView(range: range.quantityRange(for: self.unit), unit: self.unit, guardrail: self.guardrail, isEditing: isEditing)
-            },
-            valuePicker: { scheduleItem, availableWidth in
-                GlucoseRangePicker(
-                    range: Binding(
-                        get: { scheduleItem.wrappedValue.value.quantityRange(for: self.unit) },
-                        set: { quantityRange in
-                            withAnimation {
-                                scheduleItem.wrappedValue.value = quantityRange.doubleRange(for: self.unit)
-                            }
-                        }
-                    ),
-                    unit: self.unit,
-                    minValue: self.minValue,
-                    guardrail: self.guardrail,
-                    usageContext: .component(availableWidth: availableWidth)
-                )
-            },
-            actionAreaContent: {
-                instructionalContentIfNecessary
-                guardrailWarningIfNecessary
-            },
-            savingMechanism: .synchronous { items in
-                let quantitySchedule = DailyQuantitySchedule(unit: self.unit, dailyItems: items)!
-                let rangeSchedule = GlucoseRangeSchedule(rangeSchedule: quantitySchedule, override: self.initialSchedule?.override)
-                self.save(rangeSchedule)
-            },
-            mode: mode,
-            therapySettingType: .glucoseTargetRange
-        )
-        .onTapGesture {
-            self.userDidTap = true
-        }
-    }
-
-    var defaultFirstScheduleItemValue: DoubleRange {
-        switch unit {
-        case .milligramsPerDeciliter:
-            return DoubleRange(minValue: 100, maxValue: 115)
-        case .millimolesPerLiter:
-            return DoubleRange(minValue: 5.6, maxValue: 6.7)
-        default:
-            fatalError("Unsupposed glucose unit \(unit)")
-        }
-    }
-
-    var description: Text {
-        Text(TherapySetting.glucoseTargetRange.descriptiveText(appName: appName))
-    }
-
-    var saveConfirmation: SaveConfirmation {
-        crossedThresholds.isEmpty ? .notRequired : .required(confirmationAlertContent)
-    }
-    
-    var instructionalContentIfNecessary: some View {
-        return Group {
-            if mode == .acceptanceFlow && !userDidTap {
-                instructionalContent
-            }
-        }
-    }
-    
-    var instructionalContent: some View {
-        HStack { // to align with guardrail warning, if present
-            VStack(alignment: .leading, spacing: 20) {
-                Text(LocalizedString("You can edit a setting by tapping into any line item.", comment: "Description of how to edit setting"))
-                Text(LocalizedString("You can add different ranges for different times of day by using the ➕.", comment: "Description of how to add a configuration range"))
-            }
-            .foregroundColor(.secondary)
-            .font(.subheadline)
-            Spacer()
-        }
-    }
-
-    var guardrailWarningIfNecessary: some View {
-        let crossedThresholds = self.crossedThresholds
-        return Group {
-            if !crossedThresholds.isEmpty && (userDidTap || mode == .settings) {
-                CorrectionRangeGuardrailWarning(crossedThresholds: crossedThresholds)
-            }
-        }
-    }
-
-    var crossedThresholds: [SafetyClassification.Threshold] {
-        scheduleItems.flatMap { (item) -> [SafetyClassification.Threshold] in
-            let lowerBound = HKQuantity(unit: unit, doubleValue: item.value.minValue)
-            let upperBound = HKQuantity(unit: unit, doubleValue: item.value.maxValue)
-            return [lowerBound, upperBound].compactMap { (bound) -> SafetyClassification.Threshold? in
-                switch guardrail.classification(for: bound) {
-                case .withinRecommendedRange:
-                    return nil
-                case .outsideRecommendedRange(let threshold):
-                    return threshold
-                }
-            }
-        }
-    }
-
-    private var confirmationAlertContent: AlertContent {
-        AlertContent(
-            title: Text(LocalizedString("Save Correction Range(s)?", comment: "Alert title for confirming correction ranges outside the recommended range")),
-            message: Text(TherapySetting.glucoseTargetRange.guardrailSaveWarningCaption)
-        )
-    }
-}
-
-private struct CorrectionRangeGuardrailWarning: View {
-    var crossedThresholds: [SafetyClassification.Threshold]
-
-    var body: some View {
-        assert(!crossedThresholds.isEmpty)
-        return GuardrailWarning(
-            title: crossedThresholds.count == 1 ? singularWarningTitle(for: crossedThresholds.first!) : multipleWarningTitle,
-            thresholds: crossedThresholds
-        )
-    }
-
-    private func singularWarningTitle(for threshold: SafetyClassification.Threshold) -> Text {
-        switch threshold {
-        case .minimum, .belowRecommended:
-            return Text(LocalizedString("Low Correction Value", comment: "Title text for the low correction value warning"))
-        case .aboveRecommended, .maximum:
-            return Text(LocalizedString("High Correction Value", comment: "Title text for the high correction value warning"))
-        }
-    }
-
-    private var multipleWarningTitle: Text {
-        Text(LocalizedString("Correction Values", comment: "Title text for multi-value correction value warning"))
-    }
-}

+ 0 - 368
Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/DeliveryLimitsEditor.swift

@@ -1,368 +0,0 @@
-//
-//  DeliveryLimitsEditor.swift
-//  LoopKitUI
-//
-//  Created by Michael Pangburn on 6/22/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import SwiftUI
-import HealthKit
-import LoopKit
-
-
-public struct DeliveryLimitsEditor: View {
-    let initialValue: DeliveryLimits
-    let supportedBasalRates: [Double]
-    let selectableMaxBasalRates: [Double]
-    let scheduledBasalRange: ClosedRange<Double>?
-    let supportedBolusVolumes: [Double]
-    let selectableBolusVolumes: [Double]
-    let save: (_ deliveryLimits: DeliveryLimits) -> Void
-    let mode: SettingsPresentationMode
-    
-    @State var value: DeliveryLimits
-    @State private var userDidTap: Bool = false
-    @State var settingBeingEdited: DeliveryLimits.Setting?
-
-    @State var showingConfirmationAlert = false
-    @Environment(\.dismiss) var dismiss
-    @Environment(\.authenticate) var authenticate
-    @Environment(\.appName) var appName
-
-    private let lowestCarbRatio: Double?
-
-    public init(
-        value: DeliveryLimits,
-        supportedBasalRates: [Double],
-        scheduledBasalRange: ClosedRange<Double>?,
-        supportedBolusVolumes: [Double],
-        lowestCarbRatio: Double?,
-        onSave save: @escaping (_ deliveryLimits: DeliveryLimits) -> Void,
-        mode: SettingsPresentationMode = .settings
-    ) {
-        self._value = State(initialValue: value)
-        self.initialValue = value
-        self.supportedBasalRates = supportedBasalRates
-        self.selectableMaxBasalRates = Guardrail.selectableMaxBasalRates(supportedBasalRates: supportedBasalRates, scheduledBasalRange: scheduledBasalRange, lowestCarbRatio: lowestCarbRatio)
-        self.scheduledBasalRange = scheduledBasalRange
-        self.supportedBolusVolumes = supportedBolusVolumes
-        self.selectableBolusVolumes = Guardrail.selectableBolusVolumes(supportedBolusVolumes: supportedBolusVolumes)
-        self.save = save
-        self.mode = mode
-        self.lowestCarbRatio = lowestCarbRatio
-    }
-    
-    public init(
-           viewModel: TherapySettingsViewModel,
-           didSave: (() -> Void)? = nil
-    ) {
-        precondition(viewModel.pumpSupportedIncrements != nil)
-        
-        let maxBasal = viewModel.therapySettings.maximumBasalRatePerHour.map {
-            HKQuantity(unit: .internationalUnitsPerHour, doubleValue: $0)
-        }
-
-        let maxBolus = viewModel.therapySettings.maximumBolus.map {
-            HKQuantity(unit: .internationalUnit(), doubleValue: $0)
-        }
-        
-        self.init(
-            value: DeliveryLimits(maximumBasalRate: maxBasal, maximumBolus: maxBolus),
-            supportedBasalRates: viewModel.pumpSupportedIncrements!()!.basalRates,
-            scheduledBasalRange: viewModel.therapySettings.basalRateSchedule?.valueRange(),
-            supportedBolusVolumes: viewModel.pumpSupportedIncrements!()!.bolusVolumes,
-            lowestCarbRatio: viewModel.therapySettings.carbRatioSchedule?.lowestValue(),
-            onSave: { [weak viewModel] newLimits in
-                viewModel?.saveDeliveryLimits(limits: newLimits)
-                didSave?()
-            },
-            mode: viewModel.mode
-        )
-    }
-
-    public var body: some View {
-        switch mode {
-        case .settings: return AnyView(contentWithCancel)
-        case .acceptanceFlow: return AnyView(content)
-        }
-    }
-    
-    private var contentWithCancel: some View {
-        if value == initialValue {
-            return AnyView(content
-                .navigationBarBackButtonHidden(false)
-                .navigationBarItems(leading: EmptyView())
-            )
-        } else {
-            return AnyView(content
-                .navigationBarBackButtonHidden(true)
-                .navigationBarItems(leading: cancelButton)
-            )
-        }
-    }
-    
-    private var cancelButton: some View {
-        Button(action: { self.dismiss() } ) { Text(LocalizedString("Cancel", comment: "Cancel editing settings button title")) }
-    }
-    
-    private var content: some View {
-        ConfigurationPage(
-            title: Text(TherapySetting.deliveryLimits.title),
-            actionButtonTitle: Text(mode.buttonText),
-            actionButtonState: saveButtonState,
-            cards: {
-                maximumBasalRateCard
-                maximumBolusCard
-            },
-            actionAreaContent: {
-                instructionalContentIfNecessary
-                guardrailWarningIfNecessary
-            },
-            action: {
-                if self.crossedThresholds.isEmpty {
-                    self.startSaving()
-                } else {
-                    self.showingConfirmationAlert = true
-                }
-            }
-        )
-        .alert(isPresented: $showingConfirmationAlert, content: confirmationAlert)
-        .navigationBarTitle("", displayMode: .inline)
-        .onTapGesture {
-            self.userDidTap = true
-        }
-    }
-
-    var saveButtonState: ConfigurationPageActionButtonState {
-        guard value.maximumBasalRate != nil, value.maximumBolus != nil else {
-            return .disabled
-        }
-        
-        if mode == .acceptanceFlow {
-            return .enabled
-        }
-
-        return value == initialValue && mode != .acceptanceFlow ? .disabled : .enabled
-    }
-
-    var maximumBasalRateGuardrail: Guardrail<HKQuantity> {
-        return Guardrail.maximumBasalRate(supportedBasalRates: supportedBasalRates, scheduledBasalRange: scheduledBasalRange, lowestCarbRatio: lowestCarbRatio)
-    }
-
-    var maximumBasalRateCard: Card {
-        Card {
-            SettingDescription(text: Text(DeliveryLimits.Setting.maximumBasalRate.localizedDescriptiveText(appName: appName)),
-                               informationalContent: { TherapySetting.deliveryLimits.helpScreen() })
-            ExpandableSetting(
-                isEditing: Binding(
-                    get: { self.settingBeingEdited == .maximumBasalRate },
-                    set: { isEditing in
-                        withAnimation {
-                            self.settingBeingEdited = isEditing ? .maximumBasalRate : nil
-                        }
-                    }
-                ),
-                leadingValueContent: {
-                    Text(DeliveryLimits.Setting.maximumBasalRate.title)
-                },
-                trailingValueContent: {
-                    GuardrailConstrainedQuantityView(
-                        value: value.maximumBasalRate,
-                        unit: .internationalUnitsPerHour,
-                        guardrail: maximumBasalRateGuardrail,
-                        isEditing: settingBeingEdited == .maximumBasalRate,
-                        forceDisableAnimations: true
-                    )
-                },
-                expandedContent: {
-                    FractionalQuantityPicker(
-                        value: Binding(
-                            get: { self.value.maximumBasalRate ?? self.maximumBasalRateGuardrail.startingSuggestion ?? self.maximumBasalRateGuardrail.recommendedBounds.upperBound },
-                            set: { newValue in
-                                withAnimation {
-                                    self.value.maximumBasalRate = newValue
-                                }
-                            }
-                        ),
-                        unit: .internationalUnitsPerHour,
-                        guardrail: self.maximumBasalRateGuardrail,
-                        selectableValues: self.selectableMaxBasalRates,
-                        usageContext: .independent
-                    )
-                    .accessibility(identifier: "max_basal_picker")
-                }
-            )
-        }
-    }
-
-    var maximumBolusGuardrail: Guardrail<HKQuantity> {
-        return Guardrail.maximumBolus(supportedBolusVolumes: supportedBolusVolumes)
-    }
-
-    var maximumBolusCard: Card {
-        Card {
-            SettingDescription(text: Text(DeliveryLimits.Setting.maximumBolus.localizedDescriptiveText(appName: appName)),
-                               informationalContent: { TherapySetting.deliveryLimits.helpScreen() })
-            ExpandableSetting(
-                isEditing: Binding(
-                    get: { self.settingBeingEdited == .maximumBolus },
-                    set: { isEditing in
-                        withAnimation {
-                            self.settingBeingEdited = isEditing ? .maximumBolus : nil
-                        }
-                    }
-                ),
-                leadingValueContent: {
-                    Text(DeliveryLimits.Setting.maximumBolus.title)
-                },
-                trailingValueContent: {
-                    GuardrailConstrainedQuantityView(
-                        value: value.maximumBolus,
-                        unit: .internationalUnit(),
-                        guardrail: maximumBolusGuardrail,
-                        isEditing: settingBeingEdited == .maximumBolus,
-                        forceDisableAnimations: true
-                    )
-                },
-                expandedContent: {
-                    FractionalQuantityPicker(
-                        value: Binding(
-                            get: { self.value.maximumBolus ?? self.maximumBolusGuardrail.startingSuggestion ?? self.maximumBolusGuardrail.recommendedBounds.upperBound },
-                            set: { newValue in
-                                withAnimation {
-                                    self.value.maximumBolus = newValue
-                                }
-                            }
-                        ),
-                        unit: .internationalUnit(),
-                        guardrail: self.maximumBolusGuardrail,
-                        selectableValues: self.selectableBolusVolumes,
-                        usageContext: .independent
-                    )
-                    .accessibility(identifier: "max_bolus_picker")
-                }
-            )
-        }
-    }
-    
-    private var instructionalContentIfNecessary: some View {
-        return Group {
-            if mode == .acceptanceFlow && !userDidTap {
-                instructionalContent
-            }
-        }
-    }
-
-    private var instructionalContent: some View {
-        HStack { // to align with guardrail warning, if present
-            Text(LocalizedString("You can edit a setting by tapping into any line item.", comment: "Description of how to edit setting"))
-            .foregroundColor(.secondary)
-            .font(.subheadline)
-            Spacer()
-        }
-    }
-
-    private var guardrailWarningIfNecessary: some View {
-        let crossedThresholds = self.crossedThresholds
-        return Group {
-            if !crossedThresholds.isEmpty && (userDidTap || mode == .settings) {
-                DeliveryLimitsGuardrailWarning(crossedThresholds: crossedThresholds, value: value)
-            }
-        }
-    }
-
-    private var crossedThresholds: [DeliveryLimits.Setting: SafetyClassification.Threshold] {
-        var crossedThresholds: [DeliveryLimits.Setting: SafetyClassification.Threshold] = [:]
-
-        switch value.maximumBasalRate.map(maximumBasalRateGuardrail.classification(for:)) {
-        case nil, .withinRecommendedRange:
-            break
-        case .outsideRecommendedRange(let threshold):
-            crossedThresholds[.maximumBasalRate] = threshold
-        }
-
-        switch value.maximumBolus.map(maximumBolusGuardrail.classification(for:)) {
-        case nil, .withinRecommendedRange:
-            break
-        case .outsideRecommendedRange(let threshold):
-            crossedThresholds[.maximumBolus] = threshold
-        }
-
-        return crossedThresholds
-    }
-
-    private func confirmationAlert() -> SwiftUI.Alert {
-        SwiftUI.Alert(
-            title: Text(LocalizedString("Save Delivery Limits?", comment: "Alert title for confirming delivery limits outside the recommended range")),
-            message: Text(TherapySetting.deliveryLimits.guardrailSaveWarningCaption),
-            primaryButton: .cancel(Text(LocalizedString("Go Back", comment: "Text for go back action on confirmation alert"))),
-            secondaryButton: .default(
-                Text(LocalizedString("Continue", comment: "Text for continue action on confirmation alert")),
-                action: startSaving
-            )
-        )
-    }
-
-    private func startSaving() {
-        guard mode == .settings else {
-            self.continueSaving()
-            return
-        }
-        authenticate(TherapySetting.deliveryLimits.authenticationChallengeDescription) {
-            switch $0 {
-            case .success: self.continueSaving()
-            case .failure: break
-            }
-        }
-    }
-    
-    private func continueSaving() {
-        self.save(self.value)
-    }
-}
-
-
-struct DeliveryLimitsGuardrailWarning: View {
-    let crossedThresholds: [DeliveryLimits.Setting: SafetyClassification.Threshold]
-    let value: DeliveryLimits
-    var body: some View {
-        switch crossedThresholds.count {
-        case 0:
-            preconditionFailure("A guardrail warning requires at least one crossed threshold")
-        case 1:
-            let (setting, threshold) = crossedThresholds.first!
-            let title: Text, caption: Text?
-            switch setting {
-            case .maximumBasalRate:
-                switch threshold {
-                case .minimum, .belowRecommended:
-                    title = Text(LocalizedString("Low Maximum Basal Rate", comment: "Title text for low maximum basal rate warning"))
-                    caption = Text(TherapySetting.deliveryLimits.guardrailCaptionForLowValue)
-                case .aboveRecommended, .maximum:
-                    title = Text(LocalizedString("High Maximum Basal Rate", comment: "Title text for high maximum basal rate warning"))
-                    caption = Text(TherapySetting.deliveryLimits.guardrailCaptionForHighValue)
-                }
-            case .maximumBolus:
-                switch threshold {
-                case .minimum, .belowRecommended:
-                    title = Text(LocalizedString("Low Maximum Bolus", comment: "Title text for low maximum bolus warning"))
-                    caption = Text(TherapySetting.deliveryLimits.guardrailCaptionForLowValue)
-                case .aboveRecommended, .maximum:
-                    title = Text(LocalizedString("High Maximum Bolus", comment: "Title text for high maximum bolus warning"))
-                    caption = nil
-                }
-            }
-
-            return GuardrailWarning(title: title, threshold: threshold, caption: caption)
-        case 2:
-            return GuardrailWarning(
-                title: Text(LocalizedString("Delivery Limits", comment: "Title text for crossed thresholds guardrail warning")),
-                thresholds: Array(crossedThresholds.values),
-                caption: Text(TherapySetting.deliveryLimits.guardrailCaptionForOutsideValues)
-            )
-        default:
-            preconditionFailure("Unreachable: only two delivery limit settings exist")
-        }
-    }
-}

+ 0 - 46
Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/InsulinModelChartView.swift

@@ -1,46 +0,0 @@
-//
-//  InsulinModelChartView.swift
-//  LoopKitUI
-//
-//  Created by Michael Pangburn on 7/15/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import SwiftUI
-import HealthKit
-import LoopKit
-
-
-struct InsulinModelChartView: UIViewRepresentable {
-    let chartManager: ChartsManager
-    var glucoseUnit: HKUnit
-    var selectedInsulinModelValues: [GlucoseValue]
-    var unselectedInsulinModelValues: [[GlucoseValue]]
-    var glucoseDisplayRange: ClosedRange<HKQuantity>
-
-    func makeUIView(context: Context) -> ChartContainerView {
-        let view = ChartContainerView()
-        view.chartGenerator = { [chartManager] frame in
-            chartManager.chart(atIndex: 0, frame: frame)?.view
-        }
-        return view
-    }
-
-    func updateUIView(_ chartContainerView: ChartContainerView, context: Context) {
-        chartManager.invalidateChart(atIndex: 0)
-        insulinModelChart.glucoseUnit = glucoseUnit
-        insulinModelChart.setSelectedInsulinModelValues(selectedInsulinModelValues)
-        insulinModelChart.setUnselectedInsulinModelValues(unselectedInsulinModelValues)
-        insulinModelChart.glucoseDisplayRange = glucoseDisplayRange
-        chartManager.prerender()
-        chartContainerView.reloadChart()
-    }
-
-    private var insulinModelChart: InsulinModelChart {
-        guard chartManager.charts.count == 1, let insulinModelChart = chartManager.charts.first as? InsulinModelChart else {
-            fatalError("Expected exactly one insulin model chart in ChartsManager")
-        }
-
-        return insulinModelChart
-    }
-}

+ 0 - 262
Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/InsulinModelSelection.swift

@@ -1,262 +0,0 @@
-//
-//  InsulinModelSelection.swift
-//  Loop
-//
-//  Created by Michael Pangburn on 7/14/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import HealthKit
-import SwiftUI
-import LoopKit
-
-public struct InsulinModelSelection: View {
-    @Environment(\.appName) private var appName   
-    @Environment(\.dismiss) var dismiss
-    @Environment(\.authenticate) var authenticate
-
-    let initialValue: InsulinModelSettings
-    @State var value: InsulinModelSettings
-    let insulinSensitivitySchedule: InsulinSensitivitySchedule
-    let glucoseUnit: HKUnit
-    let supportedModelSettings: SupportedInsulinModelSettings
-    let mode: SettingsPresentationMode
-    let save: (_ insulinModelSettings: InsulinModelSettings) -> Void
-    let chartManager: ChartsManager
-
-    static let defaultInsulinSensitivitySchedule = InsulinSensitivitySchedule(unit: .milligramsPerDeciliter, dailyItems: [RepeatingScheduleValue<Double>(startTime: 0, value: 40)])!
-    
-    public init(
-        value: InsulinModelSettings,
-        insulinSensitivitySchedule: InsulinSensitivitySchedule?,
-        glucoseUnit: HKUnit,
-        supportedModelSettings: SupportedInsulinModelSettings,
-        chartColors: ChartColorPalette,
-        onSave save: @escaping (_ insulinModelSettings: InsulinModelSettings) -> Void,
-        mode: SettingsPresentationMode
-    ){
-        self._value = State(initialValue: value)
-        self.initialValue = value
-        self.insulinSensitivitySchedule = insulinSensitivitySchedule ?? Self.defaultInsulinSensitivitySchedule
-        self.save = save
-        self.glucoseUnit = glucoseUnit
-        self.supportedModelSettings = supportedModelSettings
-        self.mode = mode
-        self.chartManager = {
-            let chartManager = ChartsManager(
-                colors: chartColors,
-                settings: .default,
-                axisLabelFont: .systemFont(ofSize: 12),
-                charts: [InsulinModelChart()],
-                traitCollection: .current
-            )
-            
-            chartManager.startDate = Calendar.current.nextDate(
-                after: Date(),
-                matching: DateComponents(minute: 0),
-                matchingPolicy: .strict,
-                direction: .backward
-                ) ?? Date()
-            
-            return chartManager
-        }()
-    }
-
-    public init(
-           viewModel: TherapySettingsViewModel,
-           didSave: (() -> Void)? = nil
-    ) {
-        self.init(
-            value: viewModel.therapySettings.insulinModelSettings ?? InsulinModelSettings.exponentialPreset(.rapidActingAdult),
-            insulinSensitivitySchedule: viewModel.therapySettings.insulinSensitivitySchedule,
-            glucoseUnit: viewModel.therapySettings.insulinSensitivitySchedule?.unit ?? viewModel.preferredGlucoseUnit,
-            supportedModelSettings: viewModel.supportedInsulinModelSettings,
-            chartColors: viewModel.chartColors,
-            onSave: { [weak viewModel] insulinModelSettings in
-                viewModel?.saveInsulinModel(insulinModelSettings: insulinModelSettings)
-                didSave?()
-            },
-            mode: viewModel.mode
-        )
-    }
-
-    public var body: some View {
-        switch mode {
-        case .acceptanceFlow: return AnyView(content)
-        case .settings: return AnyView(contentWithCancel)
-        }
-    }
-    
-    private var contentWithCancel: some View {
-        if value == initialValue {
-            return AnyView(content
-                .navigationBarBackButtonHidden(false)
-                .navigationBarItems(leading: EmptyView())
-            )
-        } else {
-            return AnyView(content
-                .navigationBarBackButtonHidden(true)
-                .navigationBarItems(leading: cancelButton)
-            )
-        }
-    }
-    
-    private var cancelButton: some View {
-        Button(action: { self.dismiss() } ) { Text(LocalizedString("Cancel", comment: "Cancel editing settings button title")) }
-    }
-    
-    private var content: some View {
-        VStack(spacing: 0) {
-            list
-            Button(action: { self.startSaving() }) {
-                Text(mode.buttonText)
-                    .actionButtonStyle(.primary)
-                    .padding()
-            }
-            .disabled(value == initialValue && mode != .acceptanceFlow)
-            // Styling to mimic the floating button of a ConfigurationPage
-            .padding(.bottom)
-            .background(Color(.secondarySystemGroupedBackground).shadow(radius: 5))
-        }
-        .navigationBarTitle(Text(TherapySetting.insulinModel.title), displayMode: .large)
-        .supportedInterfaceOrientations(.portrait)
-        .edgesIgnoringSafeArea(.bottom)
-    }
-    
-    private var list: some View {
-        List {
-            Section {
-                SettingDescription(
-                    text: insulinModelSettingDescription,
-                    informationalContent: {
-                        TherapySetting.insulinModel.helpScreen()
-                    }
-                )
-                .padding(4)
-                .padding(.top, 4)
-
-                VStack {
-                    InsulinModelChartView(
-                        chartManager: chartManager,
-                        glucoseUnit: glucoseUnit,
-                        selectedInsulinModelValues: selectedInsulinModelValues,
-                        unselectedInsulinModelValues: unselectedInsulinModelValues,
-                        glucoseDisplayRange: endingGlucoseQuantity...startingGlucoseQuantity
-                    )
-                    .frame(height: 170)
-
-                    CheckmarkListItem(
-                        title: Text(InsulinModelSettings.exponentialPreset(.rapidActingAdult).title),
-                        description: Text(InsulinModelSettings.exponentialPreset(.rapidActingAdult).subtitle),
-                        isSelected: isSelected(.exponentialPreset(.rapidActingAdult))
-                    )
-                    .padding(.vertical, 4)
-                }
-
-                CheckmarkListItem(
-                    title: Text(InsulinModelSettings.exponentialPreset(.rapidActingChild).title),
-                    description: Text(InsulinModelSettings.exponentialPreset(.rapidActingChild).subtitle),
-                    isSelected: isSelected(.exponentialPreset(.rapidActingChild))
-                )
-                .padding(.vertical, 4)
-                .padding(.bottom, 4)
-
-            }
-            .buttonStyle(PlainButtonStyle()) // Disable row highlighting on selection
-        }
-        .insetGroupedListStyle()
-    }
-
-    var insulinModelSettingDescription: Text {
-        let spellOutFormatter = NumberFormatter()
-        spellOutFormatter.numberStyle = .spellOut
-        let modelCountString = spellOutFormatter.string(from: selectableInsulinModelSettings.count as NSNumber)!
-        return Text(String(format: LocalizedString("For fast acting insulin, %1$@ assumes it is actively working for 6 hours. You can choose from %2$@ different models for how the app measures the insulin’s peak activity.", comment: "Insulin model setting description (1: app name) (2: number of models)"), appName, modelCountString))
-    }
-
-    var insulinModelChart: InsulinModelChart {
-        chartManager.charts.first! as! InsulinModelChart
-    }
-
-    var selectableInsulinModelSettings: [InsulinModelSettings] {
-        var options: [InsulinModelSettings] =  [
-            .exponentialPreset(.rapidActingAdult),
-            .exponentialPreset(.rapidActingChild)
-        ]
-
-        return options
-    }
-
-    private var selectedInsulinModelValues: [GlucoseValue] {
-        oneUnitBolusEffectPrediction(using: value)
-    }
-
-    private var unselectedInsulinModelValues: [[GlucoseValue]] {
-        selectableInsulinModelSettings
-            .filter { $0 != value }
-            .map { oneUnitBolusEffectPrediction(using: $0) }
-    }
-
-    private func oneUnitBolusEffectPrediction(using modelSettings: InsulinModelSettings) -> [GlucoseValue] {
-        let bolus = DoseEntry(type: .bolus, startDate: chartManager.startDate, value: 1, unit: .units, insulinType: .novolog)
-        let startingGlucoseSample = HKQuantitySample(type: HKQuantityType.quantityType(forIdentifier: .bloodGlucose)!, quantity: startingGlucoseQuantity, start: chartManager.startDate, end: chartManager.startDate)
-        let effects = [bolus].glucoseEffects(insulinModelSettings: modelSettings, insulinSensitivity: insulinSensitivitySchedule)
-        return LoopMath.predictGlucose(startingAt: startingGlucoseSample, effects: effects)
-    }
-
-    private var startingGlucoseQuantity: HKQuantity {
-        let startingGlucoseValue = insulinSensitivitySchedule.quantity(at: chartManager.startDate).doubleValue(for: glucoseUnit) + glucoseUnit.glucoseExampleTargetValue
-        return HKQuantity(unit: glucoseUnit, doubleValue: startingGlucoseValue)
-    }
-
-    private var endingGlucoseQuantity: HKQuantity {
-        HKQuantity(unit: glucoseUnit, doubleValue: glucoseUnit.glucoseExampleTargetValue)
-    }
-
-    private func isSelected(_ settings: InsulinModelSettings) -> Binding<Bool> {
-        Binding(
-            get: { self.value == settings },
-            set: { isSelected in
-                if isSelected {
-                    withAnimation {
-                        self.value = settings
-                    }
-                }
-            }
-        )
-    }
-
-    private func startSaving() {
-        guard mode == .settings else {
-            self.continueSaving()
-            return
-        }
-        authenticate(TherapySetting.insulinModel.authenticationChallengeDescription) {
-            switch $0 {
-            case .success: self.continueSaving()
-            case .failure: break
-            }
-        }
-    }
-    
-    private func continueSaving() {
-        self.save(self.value)
-    }
-
-    var dismissButton: some View {
-        Button(action: dismiss) {
-            Text(LocalizedString("Close", comment: "Button text to close a modal"))
-        }
-    }
-}
-
-fileprivate extension HKUnit {
-    /// An example value for the "ideal" target
-    var glucoseExampleTargetValue: Double {
-        if self == .milligramsPerDeciliter {
-            return 100
-        } else {
-            return 5.5
-        }
-    }
-}

+ 0 - 128
Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/InsulinSensitivityScheduleEditor.swift

@@ -1,128 +0,0 @@
-//
-//  InsulinSensitivityScheduleEditor.swift
-//  LoopKitUI
-//
-//  Created by Michael Pangburn on 4/20/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import SwiftUI
-import HealthKit
-import LoopKit
-
-
-public struct InsulinSensitivityScheduleEditor: View {
-    private var schedule: DailyQuantitySchedule<Double>?
-    private var glucoseUnit: HKUnit
-    private var save: (InsulinSensitivitySchedule) -> Void
-    private var mode: SettingsPresentationMode
-    @Environment(\.appName) private var appName
-
-    public init(
-        schedule: InsulinSensitivitySchedule?,
-        mode: SettingsPresentationMode = .settings,
-        glucoseUnit: HKUnit,
-        onSave save: @escaping (InsulinSensitivitySchedule) -> Void
-    ) {
-        // InsulinSensitivitySchedule stores only the glucose unit.
-        // For consistency across display & computation, convert to "real" <glucose unit>/U units.
-        self.schedule = schedule.map { schedule in
-            DailyQuantitySchedule(
-                unit: glucoseUnit.unitDivided(by: .internationalUnit()),
-                dailyItems: schedule.items
-            )!
-        }
-        self.glucoseUnit = glucoseUnit
-        self.save = save
-        self.mode = mode
-    }
-    
-    public init(
-        viewModel: TherapySettingsViewModel,
-        didSave: (() -> Void)? = nil
-    ) {
-        self.init(
-            schedule: viewModel.therapySettings.insulinSensitivitySchedule,
-            mode: viewModel.mode,
-            glucoseUnit: viewModel.therapySettings.glucoseUnit!,
-            onSave: { [weak viewModel] in
-                viewModel?.saveInsulinSensitivitySchedule(insulinSensitivitySchedule: $0)
-                didSave?()
-            }
-        )
-    }
-
-    public var body: some View {
-        QuantityScheduleEditor(
-            title: Text(TherapySetting.insulinSensitivity.title),
-            description: description,
-            schedule: schedule,
-            unit: sensitivityUnit,
-            guardrail: .insulinSensitivity,
-            selectableValueStride: stride,
-            defaultFirstScheduleItemValue: Guardrail.insulinSensitivity.startingSuggestion ?? Guardrail.insulinSensitivity.recommendedBounds.upperBound,
-            confirmationAlertContent: confirmationAlertContent,
-            guardrailWarning: InsulinSensitivityGuardrailWarning.init(crossedThresholds:),
-            onSave: {
-                // Convert back to the expected glucose-unit-only schedule.
-                self.save(DailyQuantitySchedule(unit: self.glucoseUnit, dailyItems: $0.items)!)
-            },
-            mode: mode,
-            settingType: .insulinSensitivity
-        )
-    }
-
-    private var description: Text {
-        Text(TherapySetting.insulinSensitivity.descriptiveText(appName: appName))
-    }
-
-    private var sensitivityUnit: HKUnit {
-         glucoseUnit.unitDivided(by: .internationalUnit())
-    }
-
-    private var stride: HKQuantity {
-        let doubleValue: Double
-        switch glucoseUnit {
-        case .milligramsPerDeciliter:
-            doubleValue = 1
-        case .millimolesPerLiter:
-            doubleValue = 0.1
-        case let otherUnit:
-            fatalError("Unsupported glucose unit \(otherUnit)")
-        }
-
-        return HKQuantity(unit: sensitivityUnit, doubleValue: doubleValue)
-    }
-
-    private var confirmationAlertContent: AlertContent {
-        AlertContent(
-            title: Text(LocalizedString("Save Insulin Sensitivities?", comment: "Alert title for confirming insulin sensitivities outside the recommended range")),
-            message: Text(TherapySetting.insulinSensitivity.guardrailSaveWarningCaption)
-        )
-    }
-}
-
-private struct InsulinSensitivityGuardrailWarning: View {
-    var crossedThresholds: [SafetyClassification.Threshold]
-
-    var body: some View {
-        assert(!crossedThresholds.isEmpty)
-        return GuardrailWarning(
-            title: crossedThresholds.count == 1 ? singularWarningTitle(for: crossedThresholds.first!) : multipleWarningTitle,
-            thresholds: crossedThresholds
-        )
-    }
-
-    private func singularWarningTitle(for threshold: SafetyClassification.Threshold) -> Text {
-        switch threshold {
-        case .minimum, .belowRecommended:
-            return Text(LocalizedString("Low Insulin Sensitivity", comment: "Title text for the low insulin sensitivity warning"))
-        case .aboveRecommended, .maximum:
-            return Text(LocalizedString("High Insulin Sensitivity", comment: "Title text for the high insulin sensitivity warning"))
-        }
-    }
-
-    private var multipleWarningTitle: Text {
-        Text(LocalizedString("Insulin Sensitivities", comment: "Title text for multi-value insulin sensitivity warning"))
-    }
-}

+ 0 - 18
Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/PumpSupportedIncrements.swift

@@ -1,18 +0,0 @@
-//
-//  PumpSupportedIncrements.swift
-//  LoopKitUI
-//
-//  Created by Rick Pasetto on 7/16/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-public struct PumpSupportedIncrements {
-    let basalRates: [Double]
-    let bolusVolumes: [Double]
-    let maximumBasalScheduleEntryCount: Int
-    public init(basalRates: [Double], bolusVolumes: [Double], maximumBasalScheduleEntryCount: Int) {
-        self.basalRates = basalRates
-        self.bolusVolumes = bolusVolumes
-        self.maximumBasalScheduleEntryCount = maximumBasalScheduleEntryCount
-    }
-}

+ 0 - 27
Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/SettingsPresentationMode.swift

@@ -1,27 +0,0 @@
-//
-//  SettingsPresentationMode.swift
-//  LoopKitUI
-//
-//  Created by Anna Quinlan on 7/21/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-/// Represents the different modes that settings screens might be represented in
-public enum SettingsPresentationMode {
-    /// Presentation is in the onboarding acceptance flow
-    case acceptanceFlow
-    /// Presentation is under the settings ("gear icon") screen
-    case settings
-}
-
-extension SettingsPresentationMode {
-    /// Text for the button at the bottom of the settings screen
-    var buttonText: String {
-        switch self {
-        case .acceptanceFlow:
-            return LocalizedString("Confirm Setting", comment: "The button text for confirming the setting")
-        case .settings:
-            return LocalizedString("Save", comment: "The button text for saving on a configuration page")
-        }
-    }
-}

+ 0 - 16
Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/SupportedInsulinModelSettings.swift

@@ -1,16 +0,0 @@
-//
-//  SupportedInsulinModelSettings.swift
-//  LoopKitUI
-//
-//  Created by Rick Pasetto on 7/20/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-public struct SupportedInsulinModelSettings {
-    public let fiaspModelEnabled: Bool
-    public let walshModelEnabled: Bool
-    public init(fiaspModelEnabled: Bool, walshModelEnabled: Bool) {
-        self.fiaspModelEnabled = fiaspModelEnabled
-        self.walshModelEnabled = walshModelEnabled
-    }
-}

+ 0 - 251
Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/SuspendThresholdEditor.swift

@@ -1,251 +0,0 @@
-//
-//  SuspendThresholdEditor.swift
-//  LoopKitUI
-//
-//  Created by Michael Pangburn on 4/10/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import SwiftUI
-import HealthKit
-import LoopKit
-
-
-public struct SuspendThresholdEditor: View {
-    var initialValue: HKQuantity?
-    var unit: HKUnit
-    var maxValue: HKQuantity?
-    var save: (_ suspendThreshold: HKQuantity) -> Void
-    let mode: SettingsPresentationMode
-    
-    @State private var userDidTap: Bool = false
-    @State var value: HKQuantity
-    @State var isEditing = false
-    @State var showingConfirmationAlert = false
-    @Environment(\.dismiss) var dismiss
-    @Environment(\.authenticate) var authenticate
-    @Environment(\.appName) private var appName
-
-    let guardrail = Guardrail.suspendThreshold
-
-    public init(
-        value: HKQuantity?,
-        unit: HKUnit,
-        maxValue: HKQuantity?,
-        onSave save: @escaping (_ suspendThreshold: HKQuantity) -> Void,
-        mode: SettingsPresentationMode = .settings
-    ) {
-        self._value = State(initialValue: value ?? Self.defaultValue(for: unit))
-        self.initialValue = value
-        self.unit = unit
-        self.maxValue = maxValue
-        self.save = save
-        self.mode = mode
-    }
-    
-    public init(
-           viewModel: TherapySettingsViewModel,
-           didSave: (() -> Void)? = nil
-    ) {
-        let unit = viewModel.therapySettings.glucoseUnit ?? viewModel.preferredGlucoseUnit
-        self.init(
-            value: viewModel.therapySettings.suspendThreshold?.quantity,
-            unit: unit,
-            maxValue: Guardrail.maxSuspendThresholdValue(
-                correctionRangeSchedule: viewModel.therapySettings.glucoseTargetRangeSchedule,
-                preMealTargetRange: viewModel.therapySettings.preMealTargetRange?.quantityRange(for: unit),
-                workoutTargetRange: viewModel.therapySettings.workoutTargetRange?.quantityRange(for: unit)
-            ),
-            onSave: { [weak viewModel] newValue in
-                guard let viewModel = viewModel else {
-                    return
-                }
-                let newThreshold = GlucoseThreshold(unit: viewModel.preferredGlucoseUnit, value: newValue.doubleValue(for: viewModel.preferredGlucoseUnit))
-                viewModel.saveSuspendThreshold(value: newThreshold)
-                didSave?()
-            },
-            mode: viewModel.mode
-        )
-    }
-
-    private static func defaultValue(for unit: HKUnit) -> HKQuantity {
-        switch unit {
-        case .milligramsPerDeciliter:
-            return HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 80)
-        case .millimolesPerLiter:
-            return HKQuantity(unit: .millimolesPerLiter, doubleValue: 4.5)
-        default:
-            fatalError("Unsupported glucose unit \(unit)")
-        }
-    }
-
-    public var body: some View {
-        switch mode {
-        case .settings: return AnyView(contentWithCancel)
-        case .acceptanceFlow: return AnyView(content)
-        }
-    }
-    
-    private var contentWithCancel: some View {
-        if value == initialValue {
-            return AnyView(content
-                .navigationBarBackButtonHidden(false)
-                .navigationBarItems(leading: EmptyView())
-            )
-        } else {
-            return AnyView(content
-                .navigationBarBackButtonHidden(true)
-                .navigationBarItems(leading: cancelButton)
-            )
-        }
-    }
-    
-    private var cancelButton: some View {
-        Button(action: { self.dismiss() } ) { Text(LocalizedString("Cancel", comment: "Cancel editing settings button title")) }
-    }
-    
-    private var content: some View {
-        ConfigurationPage(
-            title: Text(TherapySetting.suspendThreshold.title),
-            actionButtonTitle: Text(mode.buttonText),
-            actionButtonState: saveButtonState,
-            cards: {
-                // TODO: Remove conditional when Swift 5.3 ships
-                // https://bugs.swift.org/browse/SR-11628
-                if true {
-                    Card {
-                        SettingDescription(text: description, informationalContent: { TherapySetting.suspendThreshold.helpScreen() })
-                        ExpandableSetting(
-                            isEditing: $isEditing,
-                            valueContent: {
-                                GuardrailConstrainedQuantityView(
-                                    value: value,
-                                    unit: unit,
-                                    guardrail: guardrail,
-                                    isEditing: isEditing,
-                                    // Workaround for strange animation behavior on appearance
-                                    forceDisableAnimations: true
-                                )
-                            },
-                            expandedContent: {
-                                GlucoseValuePicker(
-                                    value: self.$value.animation(),
-                                    unit: self.unit,
-                                    guardrail: self.guardrail,
-                                    bounds: self.guardrail.absoluteBounds.lowerBound...(self.maxValue ?? self.guardrail.absoluteBounds.upperBound)
-                                )
-                                // Prevent the picker from expanding the card's width on small devices
-                                .frame(maxWidth: UIScreen.main.bounds.width - 48)
-                                .clipped()
-                            }
-                        )
-                    }
-                }
-            },
-            actionAreaContent: {
-                instructionalContentIfNecessary
-                if warningThreshold != nil && (userDidTap || mode != .acceptanceFlow) {
-                    SuspendThresholdGuardrailWarning(safetyClassificationThreshold: warningThreshold!)
-                }
-            },
-            action: {
-                if self.warningThreshold == nil {
-                    self.startSaving()
-                } else {
-                    self.showingConfirmationAlert = true
-                }
-            }
-        )
-        .alert(isPresented: $showingConfirmationAlert, content: confirmationAlert)
-        .navigationBarTitle("", displayMode: .inline)
-        .onTapGesture {
-            self.userDidTap = true
-        }
-    }
-
-    var description: Text {
-        Text(TherapySetting.suspendThreshold.descriptiveText(appName: appName))
-    }
-    
-    private var instructionalContentIfNecessary: some View {
-        return Group {
-            if mode == .acceptanceFlow && !userDidTap {
-                instructionalContent
-            }
-        }
-    }
-
-    private var instructionalContent: some View {
-        HStack { // to align with guardrail warning, if present
-            Text(LocalizedString("You can edit the setting by tapping into the line item.", comment: "Description of how to edit setting"))
-            .foregroundColor(.secondary)
-            .font(.subheadline)
-            Spacer()
-        }
-    }
-
-    private var saveButtonState: ConfigurationPageActionButtonState {
-        initialValue == nil || value != initialValue! || mode == .acceptanceFlow ? .enabled : .disabled
-    }
-
-    private var warningThreshold: SafetyClassification.Threshold? {
-        switch guardrail.classification(for: value) {
-        case .withinRecommendedRange:
-            return nil
-        case .outsideRecommendedRange(let threshold):
-            return threshold
-        }
-    }
-
-    private func confirmationAlert() -> SwiftUI.Alert {
-        SwiftUI.Alert(
-            title: Text(LocalizedString("Save Glucose Safety Limit?", comment: "Alert title for confirming a glucose safety limit outside the recommended range")),
-            message: Text(TherapySetting.suspendThreshold.guardrailSaveWarningCaption),
-            primaryButton: .cancel(Text(LocalizedString("Go Back", comment: "Text for go back action on confirmation alert"))),
-            secondaryButton: .default(
-                Text(LocalizedString("Continue", comment: "Text for continue action on confirmation alert")),
-                action: startSaving
-            )
-        )
-    }
-    
-    private func startSaving() {
-        guard mode == .settings else {
-            self.continueSaving()
-            return
-        }
-        authenticate(TherapySetting.suspendThreshold.authenticationChallengeDescription) {
-            switch $0 {
-            case .success: self.continueSaving()
-            case .failure: break
-            }
-        }
-    }
-    
-    private func continueSaving() {
-        self.save(self.value)
-    }
-}
-
-struct SuspendThresholdGuardrailWarning: View {
-    var safetyClassificationThreshold: SafetyClassification.Threshold
-
-    var body: some View {
-        GuardrailWarning(title: title, threshold: safetyClassificationThreshold)
-    }
-
-    private var title: Text {
-        switch safetyClassificationThreshold {
-        case .minimum, .belowRecommended:
-            return Text(LocalizedString("Low Glucose Safety Limit", comment: "Title text for the low glucose safety limit warning"))
-        case .aboveRecommended, .maximum:
-            return Text(LocalizedString("High Glucose Safety Limit", comment: "Title text for the high glucose safety limit warning"))
-        }
-    }
-}
-
-struct SuspendThresholdView_Previews: PreviewProvider {
-    static var previews: some View {
-        SuspendThresholdEditor(value: nil, unit: .milligramsPerDeciliter, maxValue: nil, onSave: { _ in })
-    }
-}

+ 0 - 47
Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/TherapySetting+Settings.swift

@@ -1,47 +0,0 @@
-//
-//  TherapySetting+Settings.swift
-//  LoopKitUI
-//
-//  Created by Rick Pasetto on 7/14/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import LoopKit
-import SwiftUI
-
-extension TherapySetting {
-    
-    public var authenticationChallengeDescription: String {
-        switch self {
-        default:
-            // Currently, this is the same no matter what the setting is.
-            return LocalizedString("Authenticate to save therapy setting", comment: "Authentication hint string for therapy settings")
-        }
-    }
-    
-    public func helpScreen() -> some View {
-        switch self {
-        case .glucoseTargetRange:
-            return AnyView(CorrectionRangeInformationView(onExit: nil, mode: .settings))
-        case .preMealCorrectionRangeOverride:
-            return AnyView(CorrectionRangeOverrideInformationView(preset: .preMeal, onExit: nil, mode: .settings))
-        case .workoutCorrectionRangeOverride:
-            return AnyView(CorrectionRangeOverrideInformationView(preset: .workout, onExit: nil, mode: .settings))
-        case .suspendThreshold:
-            return AnyView(SuspendThresholdInformationView(onExit: nil, mode: .settings))
-        case .basalRate:
-            return AnyView(BasalRatesInformationView(onExit: nil, mode: .settings))
-        case .deliveryLimits:
-            return AnyView(DeliveryLimitsInformationView(onExit: nil, mode: .settings))
-        case .insulinModel:
-            return AnyView(InsulinModelInformationView(onExit: nil, mode: .settings))
-        case .carbRatio:
-            return AnyView(CarbRatioInformationView(onExit: nil, mode: .settings))
-        case .insulinSensitivity:
-            return AnyView(InsulinSensitivityInformationView(onExit: nil, mode: .settings))
-        case .none:
-            return AnyView(Text("To be implemented"))
-        }
-    }
-}
-

+ 0 - 589
Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/TherapySettingsView.swift

@@ -1,589 +0,0 @@
-//
-//  TherapySettingsView.swift
-//  LoopKitUI
-//
-//  Created by Rick Pasetto on 7/7/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import AVFoundation
-import HealthKit
-import LoopKit
-import SwiftUI
-
-public struct TherapySettingsView: View {
-    @Environment(\.dismiss) var dismiss
-    @Environment(\.appName) private var appName
-
-    public struct ActionButton {
-        public init(localizedString: String, action: @escaping () -> Void) {
-            self.localizedString = localizedString
-            self.action = action
-        }
-        let localizedString: String
-        let action: () -> Void
-    }
-    
-    @ObservedObject var viewModel: TherapySettingsViewModel
-        
-    private let actionButton: ActionButton?
-        
-    public init(viewModel: TherapySettingsViewModel,
-                actionButton: ActionButton? = nil) {
-        self.viewModel = viewModel
-        self.actionButton = actionButton
-    }
-        
-    public var body: some View {
-        switch viewModel.mode {
-        case .acceptanceFlow: return AnyView(content)
-        case .settings: return AnyView(navigationViewWrappedContent)
-        }
-    }
-    
-    private var content: some View {
-        List {
-            Group {
-                if viewModel.mode == .acceptanceFlow && viewModel.prescription != nil {
-                    // At start of acceptance flow
-                    prescriptionSection
-                } else if viewModel.mode == .acceptanceFlow && viewModel.prescription == nil {
-                    // At end of acceptance flow
-                    summaryHeaderSection
-                }
-                suspendThresholdSection
-                correctionRangeSection
-                preMealCorrectionRangeSection
-                if !viewModel.sensitivityOverridesEnabled {
-                    workoutCorrectionRangeSection
-                }
-                carbRatioSection
-                basalRatesSection
-                deliveryLimitsSection
-                insulinModelSection
-                insulinSensitivitiesSection
-            }
-            lastItem
-        }
-        .insetGroupedListStyle()
-        .onAppear() {
-            UITableView.appearance().separatorStyle = .singleLine // Add lines between rows
-        }
-        .navigationBarTitle(Text(LocalizedString("Therapy Settings", comment: "Therapy Settings screen title")), displayMode: .large)
-    }
-    
-    private var navigationViewWrappedContent: some View {
-        NavigationView {
-            content
-                .navigationBarItems(trailing: dismissButton)
-        }
-    }
-    
-    private var dismissButton: some View {
-        Button(action: {
-            self.dismiss()
-        }) {
-            Text(LocalizedString("Done", comment: "Text for dismiss button")).bold()
-        }
-    }
-    
-    @ViewBuilder private var lastItem: some View {
-        if viewModel.mode == .acceptanceFlow {
-            if actionButton != nil {
-                Button(action: actionButton!.action) {
-                    Text(actionButton!.localizedString)
-                }
-                .buttonStyle(ActionButtonStyle(.primary))
-                .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
-            }
-        } else {
-            supportSection
-        }
-    }
-}
-
-// MARK: Sections
-extension TherapySettingsView {
-    
-    private var prescriptionSection: some View {
-        Section(header: Spacer()) {
-            VStack(alignment: .leading) {
-                Spacer()
-                Text(LocalizedString("Prescription", comment: "title for prescription section"))
-                    .bold()
-                Spacer()
-                DescriptiveText(label: prescriptionDescriptiveText)
-                Spacer()
-            }
-        }
-    }
-    
-    private var summaryHeaderSection: some View {
-        Section(header: Spacer()) {
-            VStack(alignment: .leading) {
-                Spacer()
-                Text(LocalizedString("Review and Save Settings", comment: "title for summary description section"))
-                    .bold()
-                    .foregroundColor(.white)
-                Spacer()
-                VStack (alignment: .leading, spacing: 10) {
-                    DescriptiveText(label: summaryHeaderReviewText, color: .white)
-                    DescriptiveText(label: summaryHeaderEditText, color: .white)
-                }
-                Spacer()
-            }
-        }
-        .listRowBackground(Color.accentColor)
-    }
-    
-    private var summaryHeaderReviewText: String {
-        String(format: LocalizedString("Review your therapy settings below. If you’d like to edit any of these settings, tap Back to go back to that screen.", comment: "Description of how to interact with summary screen"))
-    }
-    
-    private var summaryHeaderEditText: String {
-        String(format: LocalizedString("If these settings look good to you, tap Save Settings to continue.", comment: "Description of how to interact with summary screen"))
-    }
-    
-    private var prescriptionDescriptiveText: String {
-        String(format: LocalizedString("Submitted by %1$@, %2$@", comment: "Format for prescription descriptive text (1: providerName, 2: datePrescribed)"),
-               viewModel.prescription!.providerName,
-               DateFormatter.localizedString(from: viewModel.prescription!.datePrescribed, dateStyle: .short, timeStyle: .none))
-    }
-    
-    private var suspendThresholdSection: some View {
-        section(for: .suspendThreshold, header: viewModel.prescription == nil ? AnyView(Spacer()) : AnyView(EmptyView())) {
-            if let glucoseUnit = self.glucoseUnit {
-                HStack {
-                    Spacer()
-                    GuardrailConstrainedQuantityView(
-                        value: self.viewModel.therapySettings.suspendThreshold?.quantity,
-                        unit: glucoseUnit,
-                        guardrail: .suspendThreshold,
-                        isEditing: false,
-                        // Workaround for strange animation behavior on appearance
-                        forceDisableAnimations: true
-                    )
-                }
-            }
-        }
-    }
-    
-    private var correctionRangeSection: some View {
-        section(for: .glucoseTargetRange) {
-            if let glucoseUnit = self.glucoseUnit, let schedule = self.viewModel.therapySettings.glucoseTargetRangeSchedule {
-                ForEach(schedule.items, id: \.self) { value in
-                    ScheduleRangeItem(time: value.startTime,
-                                      range: value.value,
-                                      unit: glucoseUnit,
-                                      guardrail: .correctionRange)
-                }
-            }
-        }
-    }
-    
-    private var preMealCorrectionRangeSection: some View {
-        section(for: .preMealCorrectionRangeOverride) {
-            if let glucoseUnit = self.glucoseUnit, let schedule = self.viewModel.therapySettings.glucoseTargetRangeSchedule {
-                CorrectionRangeOverridesRangeItem(
-                    preMealTargetRange: self.viewModel.therapySettings.preMealTargetRange,
-                    workoutTargetRange: self.viewModel.therapySettings.workoutTargetRange,
-                    unit: glucoseUnit,
-                    preset: CorrectionRangeOverrides.Preset.preMeal,
-                    suspendThreshold: self.viewModel.therapySettings.suspendThreshold,
-                    correctionRangeScheduleRange: schedule.scheduleRange()
-                )
-            }
-        }
-    }
-    
-    private var workoutCorrectionRangeSection: some View {
-        section(for: .workoutCorrectionRangeOverride) {
-            if let glucoseUnit = self.glucoseUnit, let schedule = self.viewModel.therapySettings.glucoseTargetRangeSchedule {
-                CorrectionRangeOverridesRangeItem(
-                    preMealTargetRange: self.viewModel.therapySettings.preMealTargetRange,
-                    workoutTargetRange: self.viewModel.therapySettings.workoutTargetRange,
-                    unit: glucoseUnit,
-                    preset: CorrectionRangeOverrides.Preset.workout,
-                    suspendThreshold: self.viewModel.therapySettings.suspendThreshold,
-                    correctionRangeScheduleRange: schedule.scheduleRange()
-                )
-            }
-        }
-    }
-
-    private var basalRatesSection: some View {
-        section(for: .basalRate) {
-            if self.viewModel.therapySettings.basalRateSchedule != nil && self.viewModel.pumpSupportedIncrements?() != nil {
-                ForEach(self.viewModel.therapySettings.basalRateSchedule!.items, id: \.self) { value in
-                    ScheduleValueItem(time: value.startTime,
-                                      value: value.value,
-                                      unit: .internationalUnitsPerHour,
-                                      guardrail: Guardrail.basalRate(supportedBasalRates: self.viewModel.pumpSupportedIncrements!()!.basalRates))
-                }
-            }
-        }
-    }
-    
-    private var deliveryLimitsSection: some View {
-        section(for: .deliveryLimits) {
-            self.maxBasalRateItem
-            self.maxBolusItem
-        }
-    }
-    
-    private var maxBasalRateItem: some View {
-        HStack {
-            Text(DeliveryLimits.Setting.maximumBasalRate.title)
-            Spacer()
-            if self.viewModel.pumpSupportedIncrements?() != nil {
-                GuardrailConstrainedQuantityView(
-                    value: self.viewModel.therapySettings.maximumBasalRatePerHour.map { HKQuantity(unit: .internationalUnitsPerHour, doubleValue: $0) },
-                    unit: .internationalUnitsPerHour,
-                    guardrail: Guardrail.maximumBasalRate(
-                        supportedBasalRates: self.viewModel.pumpSupportedIncrements!()!.basalRates,
-                        scheduledBasalRange: self.viewModel.therapySettings.basalRateSchedule?.valueRange(),
-                        lowestCarbRatio: self.viewModel.therapySettings.carbRatioSchedule?.lowestValue()),
-                    isEditing: false,
-                    // Workaround for strange animation behavior on appearance
-                    forceDisableAnimations: true
-                )
-            }
-        }
-        .accessibilityElement(children: .combine)
-    }
-    
-    private var maxBolusItem: some View {
-        HStack {
-            Text(DeliveryLimits.Setting.maximumBolus.title)
-            Spacer()
-            if self.viewModel.pumpSupportedIncrements?() != nil {
-                GuardrailConstrainedQuantityView(
-                    value: self.viewModel.therapySettings.maximumBolus.map { HKQuantity(unit: .internationalUnit(), doubleValue: $0) },
-                    unit: .internationalUnit(),
-                    guardrail: Guardrail.maximumBolus(supportedBolusVolumes: self.viewModel.pumpSupportedIncrements!()!.bolusVolumes),
-                    isEditing: false,
-                    // Workaround for strange animation behavior on appearance
-                    forceDisableAnimations: true
-                )
-            }
-        }
-        .accessibilityElement(children: .combine)
-    }
-        
-    private var insulinModelSection: some View {
-        section(for: .insulinModel) {
-            if self.viewModel.therapySettings.insulinModelSettings != nil {
-                // Spacing and paddings here is my best guess based on the design...
-                VStack(alignment: .leading, spacing: 4) {
-                    Text(self.viewModel.therapySettings.insulinModelSettings!.title)
-                        .font(.body)
-                        .padding(.top, 5)
-                    Text(self.viewModel.therapySettings.insulinModelSettings!.subtitle)
-                        .font(.footnote)
-                        .foregroundColor(.secondary)
-                        .padding(.bottom, 8)
-                }
-                .accessibilityElement(children: .combine)
-            }
-        }
-    }
-
-    private var carbRatioSection: some View {
-        section(for: .carbRatio) {
-            if self.viewModel.therapySettings.carbRatioSchedule != nil {
-                ForEach(self.viewModel.therapySettings.carbRatioSchedule!.items, id: \.self) { value in
-                    ScheduleValueItem(time: value.startTime,
-                                      value: value.value,
-                                      unit: .gramsPerUnit,
-                                      guardrail: Guardrail.carbRatio)
-                }
-            }
-        }
-    }
-    
-    private var insulinSensitivitiesSection: some View {
-        section(for: .insulinSensitivity) {
-            if let sensitivityUnit = self.sensitivityUnit, let schedule = self.viewModel.therapySettings.insulinSensitivitySchedule {
-                ForEach(schedule.items, id: \.self) { value in
-                    ScheduleValueItem(time: value.startTime,
-                                      value: value.value,
-                                      unit: sensitivityUnit,
-                                      guardrail: Guardrail.insulinSensitivity)
-                }
-            }
-        }
-    }
-    
-    private var supportSection: some View {
-        Section(header: SectionHeader(label: LocalizedString("Support", comment: "Title for support section"))) {
-            NavigationLink(destination: Text("Therapy Settings Support Placeholder")) {
-                Text("Get help with Therapy Settings", comment: "Support button for Therapy Settings")
-            }
-        }
-    }
-}
-
-// MARK: Utilities
-extension TherapySettingsView {
-    
-    private var glucoseUnit: HKUnit? {
-        viewModel.therapySettings.glucoseTargetRangeSchedule?.unit
-    }
-    
-    private var sensitivityUnit: HKUnit? {
-        glucoseUnit?.unitDivided(by: .internationalUnit())
-    }
-    
-    private func section<Content>(for therapySetting: TherapySetting,
-                                  @ViewBuilder content: @escaping () -> Content) -> some View where Content: View {
-        SectionWithTapToEdit(isEnabled: viewModel.mode != .acceptanceFlow,
-                             header: EmptyView(),
-                             title: therapySetting.title,
-                             descriptiveText: therapySetting.descriptiveText(appName: appName),
-                             destination: screen(for: therapySetting),
-                             content: content)
-    }
-
-    private func section<Content, Header>(for therapySetting: TherapySetting,
-                                          header: Header,
-                                          @ViewBuilder content: @escaping () -> Content) -> some View where Content: View, Header: View {
-        SectionWithTapToEdit(isEnabled: viewModel.mode != .acceptanceFlow,
-                             header: header,
-                             title: therapySetting.title,
-                             descriptiveText: therapySetting.descriptiveText(appName: appName),
-                             destination: screen(for: therapySetting),
-                             content: content)
-    }
-}
-
-typealias HKQuantityGuardrail = Guardrail<HKQuantity>
-
-struct ScheduleRangeItem: View {
-    let time: TimeInterval
-    let range: DoubleRange
-    let unit: HKUnit
-    let guardrail: HKQuantityGuardrail
-    
-    public var body: some View {
-        ScheduleItemView(time: time,
-                         isEditing: .constant(false),
-                         valueContent: {
-                            GuardrailConstrainedQuantityRangeView(range: range.quantityRange(for: unit), unit: unit, guardrail: guardrail, isEditing: false)
-                         },
-                         expandedContent: { EmptyView() })
-    }
-}
-
-struct ScheduleValueItem: View {
-    let time: TimeInterval
-    let value: Double
-    let unit: HKUnit
-    let guardrail: HKQuantityGuardrail
-    
-    public var body: some View {
-        ScheduleItemView(time: time,
-                         isEditing: .constant(false),
-                         valueContent: {
-                            GuardrailConstrainedQuantityView(value: HKQuantity(unit: unit, doubleValue: value), unit: unit, guardrail: guardrail, isEditing: false)
-                         },
-                         expandedContent: { EmptyView() })
-    }
-}
-
-struct CorrectionRangeOverridesRangeItem: View {
-    let preMealTargetRange: DoubleRange?
-    let workoutTargetRange: DoubleRange?
-    let unit: HKUnit
-    let preset: CorrectionRangeOverrides.Preset
-    let suspendThreshold: GlucoseThreshold?
-    let correctionRangeScheduleRange: ClosedRange<HKQuantity>
-    
-    public var body: some View {
-        CorrectionRangeOverridesExpandableSetting(
-            isEditing: .constant(false),
-            value: .constant(CorrectionRangeOverrides(
-                preMeal: preMealTargetRange,
-                workout: workoutTargetRange,
-                unit: unit
-            )),
-            preset: preset,
-            unit: unit,
-            suspendThreshold: suspendThreshold,
-            correctionRangeScheduleRange: correctionRangeScheduleRange,
-            expandedContent: { EmptyView() })
-    }
-}
-
-struct SectionWithTapToEdit<Header, Content, NavigationDestination>: View where Header: View, Content: View, NavigationDestination: View  {
-    let isEnabled: Bool
-    let header: Header
-    let title: String
-    let descriptiveText: String
-    let destination: (_ goBack: @escaping () -> Void) -> NavigationDestination
-    let content: () -> Content
-
-    @State var isActive: Bool = false
-    
-    private func onFinish() {
-        // Dispatching here fixes an issue on iOS 14.2 where schedule editors do not dismiss. It does not fix iOS 14.0 and 14.1
-        DispatchQueue.main.async {
-            self.isActive = false
-        }
-    }
-
-    public var body: some View {
-        Section(header: header) {
-            VStack(alignment: .leading) {
-                Spacer()
-                Text(title)
-                    .bold()
-                Spacer()
-                ZStack(alignment: .leading) {
-                    DescriptiveText(label: descriptiveText)
-                    if isEnabled {
-                        NavigationLink(destination: destination(onFinish), isActive: $isActive) {
-                            EmptyView()
-                        }
-                    }
-                }
-                Spacer()
-            }
-            content()
-        }
-        .contentShape(Rectangle()) // make the whole card tappable
-        .highPriorityGesture(
-            TapGesture()
-                .onEnded { _ in
-                    self.isActive = true
-        })
-    }
-}
-
-// MARK: Navigation
-
-private extension TherapySettingsView {
-    
-    func screen(for setting: TherapySetting) -> (_ goBack: @escaping () -> Void) -> AnyView {
-        switch setting {
-        case .suspendThreshold:
-            if viewModel.therapySettings.glucoseUnit != nil {
-                return { goBack in
-                    AnyView(SuspendThresholdEditor(viewModel: self.viewModel, didSave: goBack).environment(\.dismiss, goBack))
-                }
-            }
-        case .glucoseTargetRange:
-            if viewModel.therapySettings.glucoseUnit != nil {
-                return { goBack in
-                    AnyView(CorrectionRangeScheduleEditor(viewModel: self.viewModel, didSave: goBack).environment(\.dismiss, goBack))
-                }
-            }
-        case .preMealCorrectionRangeOverride:
-            if self.viewModel.therapySettings.glucoseUnit != nil {
-                return { goBack in
-                    AnyView(CorrectionRangeOverridesEditor(viewModel: self.viewModel, preset: .preMeal, didSave: goBack).environment(\.dismiss, goBack))
-                }
-            }
-        case .workoutCorrectionRangeOverride:
-            if self.viewModel.therapySettings.glucoseUnit != nil {
-                return { goBack in
-                    AnyView(CorrectionRangeOverridesEditor(viewModel: self.viewModel, preset: .workout, didSave: goBack).environment(\.dismiss, goBack))
-                }
-            }
-        case .basalRate:
-            if self.viewModel.pumpSupportedIncrements?() != nil {
-                return { goBack in
-                    AnyView(BasalRateScheduleEditor(viewModel: self.viewModel, didSave: goBack).environment(\.dismiss, goBack))
-                }
-            }
-        case .deliveryLimits:
-            if self.viewModel.pumpSupportedIncrements?() != nil {
-                return { goBack in
-                    AnyView(DeliveryLimitsEditor(viewModel: self.viewModel, didSave: goBack).environment(\.dismiss, goBack))
-                }
-            }
-        case .insulinModel:
-            if self.viewModel.therapySettings.glucoseUnit != nil && self.viewModel.therapySettings.insulinModelSettings != nil {
-                return { goBack in
-                    AnyView(InsulinModelSelection(viewModel: self.viewModel, didSave: goBack).environment(\.dismiss, goBack))
-                }
-            }
-        case .carbRatio:
-            return { goBack in
-                AnyView(CarbRatioScheduleEditor(viewModel: self.viewModel, didSave: goBack).environment(\.dismiss, goBack))
-            }
-        case .insulinSensitivity:
-            if self.viewModel.therapySettings.glucoseUnit != nil {
-                return { goBack in
-                    return AnyView(InsulinSensitivityScheduleEditor(viewModel: self.viewModel, didSave: goBack).environment(\.dismiss, goBack))
-                }
-            }
-        case .none:
-            break
-        }
-        return { _ in AnyView(Text("\(setting.title)")) }
-    }
-}
-
-// MARK: Previews
-
-public struct TherapySettingsView_Previews: PreviewProvider {
-
-    static let preview_glucoseScheduleItems = [
-        RepeatingScheduleValue(startTime: 0, value: DoubleRange(80...90)),
-        RepeatingScheduleValue(startTime: 1800, value: DoubleRange(90...100)),
-        RepeatingScheduleValue(startTime: 3600, value: DoubleRange(100...110))
-    ]
-
-    static let preview_therapySettings = TherapySettings(
-        glucoseTargetRangeSchedule: GlucoseRangeSchedule(unit: .milligramsPerDeciliter, dailyItems: preview_glucoseScheduleItems),
-        preMealTargetRange: DoubleRange(88...99),
-        workoutTargetRange: DoubleRange(99...111),
-        maximumBasalRatePerHour: 55,
-        maximumBolus: 4,
-        suspendThreshold: GlucoseThreshold.init(unit: .milligramsPerDeciliter, value: 60),
-        insulinSensitivitySchedule: InsulinSensitivitySchedule(unit: HKUnit.milligramsPerDeciliter.unitDivided(by: HKUnit.internationalUnit()), dailyItems: []),
-        carbRatioSchedule: nil,
-        basalRateSchedule: BasalRateSchedule(dailyItems: [RepeatingScheduleValue(startTime: 0, value: 0.2), RepeatingScheduleValue(startTime: 1800, value: 0.75)]))
-
-    static let preview_supportedBasalRates = [0.2, 0.5, 0.75, 1.0]
-    static let preview_supportedBolusVolumes = [5.0, 10.0, 15.0]
-
-    static func preview_viewModel(mode: SettingsPresentationMode) -> TherapySettingsViewModel {
-        TherapySettingsViewModel(mode: mode,
-                                 therapySettings: preview_therapySettings,
-                                 preferredGlucoseUnit: .milligramsPerDeciliter,
-                                 supportedInsulinModelSettings: SupportedInsulinModelSettings(fiaspModelEnabled: true, walshModelEnabled: true),
-                                 pumpSupportedIncrements: { PumpSupportedIncrements(basalRates: preview_supportedBasalRates,
-                                                                                  bolusVolumes: preview_supportedBolusVolumes,
-                                                                                  maximumBasalScheduleEntryCount: 24) } ,
-                                 chartColors: ChartColorPalette(axisLine: .clear, axisLabel: .secondaryLabel, grid: .systemGray3, glucoseTint: .systemTeal, insulinTint: .systemOrange))
-    }
-
-    public static var previews: some View {
-        Group {
-            TherapySettingsView(viewModel: preview_viewModel(mode: .acceptanceFlow))
-                .colorScheme(.light)
-                .previewDevice(PreviewDevice(rawValue: "iPhone SE 2"))
-                .previewDisplayName("SE light (onboarding)")
-            TherapySettingsView(viewModel: preview_viewModel(mode: .settings))
-                .colorScheme(.light)
-                .previewDevice(PreviewDevice(rawValue: "iPhone SE 2"))
-                .previewDisplayName("SE light (settings)")
-            TherapySettingsView(viewModel: preview_viewModel(mode: .settings))
-                .colorScheme(.dark)
-                .previewDevice(PreviewDevice(rawValue: "iPhone XS Max"))
-                .previewDisplayName("XS Max dark (settings)")
-            TherapySettingsView(viewModel: TherapySettingsViewModel(mode: .settings,
-                                                                    therapySettings: TherapySettings(),
-                                                                    preferredGlucoseUnit: .milligramsPerDeciliter,
-                                                                    chartColors: ChartColorPalette(axisLine: .clear,
-                                                                                                   axisLabel: .secondaryLabel,
-                                                                                                   grid: .systemGray3,
-                                                                                                   glucoseTint: .systemTeal,
-                                                                                                   insulinTint: .systemOrange)))
-                .colorScheme(.light)
-                .previewDevice(PreviewDevice(rawValue: "iPhone SE 2"))
-                .previewDisplayName("SE light (Empty TherapySettings)")
-        }
-    }
-}

+ 0 - 113
Dependecies/LoopKit/LoopKitUI/Views/Settings Editors/TherapySettingsViewModel.swift

@@ -1,113 +0,0 @@
-//
-//  TherapySettingsViewModel.swift
-//  LoopKitUI
-//
-//  Created by Rick Pasetto on 7/13/20.
-//  Copyright © 2020 LoopKit Authors. All rights reserved.
-//
-
-import Combine
-import LoopKit
-import HealthKit
-import SwiftUI
-
-public class TherapySettingsViewModel: ObservableObject {
-    public typealias SaveCompletion = (TherapySetting, TherapySettings) -> Void
-    
-    public let mode: SettingsPresentationMode
-    
-    @Published public var therapySettings: TherapySettings
-    public var supportedInsulinModelSettings: SupportedInsulinModelSettings
-    private let didSave: SaveCompletion?
-
-    private let initialTherapySettings: TherapySettings
-    let pumpSupportedIncrements: (() -> PumpSupportedIncrements?)?
-    let syncPumpSchedule: (() -> PumpManager.SyncSchedule?)?
-    let sensitivityOverridesEnabled: Bool
-    public var prescription: Prescription?
-    
-    let preferredGlucoseUnit: HKUnit
-
-    lazy private var cancellables = Set<AnyCancellable>()
-    
-    public let chartColors: ChartColorPalette
-
-    public init(mode: SettingsPresentationMode,
-                therapySettings: TherapySettings,
-                preferredGlucoseUnit: HKUnit,
-                supportedInsulinModelSettings: SupportedInsulinModelSettings = SupportedInsulinModelSettings(fiaspModelEnabled: true, walshModelEnabled: true),
-                pumpSupportedIncrements: (() -> PumpSupportedIncrements?)? = nil,
-                syncPumpSchedule: (() -> PumpManager.SyncSchedule?)? = nil,
-                sensitivityOverridesEnabled: Bool = false,
-                prescription: Prescription? = nil,
-                chartColors: ChartColorPalette,
-                didSave: SaveCompletion? = nil) {
-        self.mode = mode
-        self.therapySettings = therapySettings
-        self.initialTherapySettings = therapySettings
-        self.preferredGlucoseUnit = preferredGlucoseUnit
-        self.pumpSupportedIncrements = pumpSupportedIncrements
-        self.syncPumpSchedule = syncPumpSchedule
-        self.sensitivityOverridesEnabled = sensitivityOverridesEnabled
-        self.prescription = prescription
-        self.supportedInsulinModelSettings = supportedInsulinModelSettings
-        self.chartColors = chartColors
-        self.didSave = didSave
-    }
-    
-    var deliveryLimits: DeliveryLimits {
-        return DeliveryLimits(maximumBasalRate: therapySettings.maximumBasalRatePerHour.map { HKQuantity(unit: .internationalUnitsPerHour, doubleValue: $0) },
-                              maximumBolus: therapySettings.maximumBolus.map { HKQuantity(unit: .internationalUnit(), doubleValue: $0) } )
-    }
-    
-    /// Reset to initial
-    public func reset() {
-        therapySettings = initialTherapySettings
-    }
-    
-    public func saveCorrectionRange(range: GlucoseRangeSchedule) {
-        therapySettings.glucoseTargetRangeSchedule = range
-        didSave?(TherapySetting.glucoseTargetRange, therapySettings)
-    }
-        
-    public func saveCorrectionRangeOverride(preMeal: ClosedRange<HKQuantity>?, unit: HKUnit) {
-        therapySettings.preMealTargetRange = preMeal?.doubleRange(for: unit)
-        didSave?(TherapySetting.preMealCorrectionRangeOverride, therapySettings)
-    }
-    
-    public func saveCorrectionRangeOverride(workout: ClosedRange<HKQuantity>?, unit: HKUnit) {
-        therapySettings.workoutTargetRange = workout?.doubleRange(for: unit)
-        didSave?(TherapySetting.workoutCorrectionRangeOverride, therapySettings)
-    }
-    
-    public func saveSuspendThreshold(value: GlucoseThreshold) {
-        therapySettings.suspendThreshold = value
-        didSave?(TherapySetting.suspendThreshold, therapySettings)
-    }
-    
-    public func saveBasalRates(basalRates: BasalRateSchedule) {
-        therapySettings.basalRateSchedule = basalRates
-        didSave?(TherapySetting.basalRate, therapySettings)
-    }
-    
-    public func saveDeliveryLimits(limits: DeliveryLimits) {
-        therapySettings.maximumBasalRatePerHour = limits.maximumBasalRate?.doubleValue(for: .internationalUnitsPerHour)
-        therapySettings.maximumBolus = limits.maximumBolus?.doubleValue(for: .internationalUnit())
-        didSave?(TherapySetting.deliveryLimits, therapySettings)
-    }
-    
-    public func saveInsulinModel(insulinModelSettings: InsulinModelSettings) {
-        therapySettings.insulinModelSettings = insulinModelSettings
-        didSave?(TherapySetting.insulinModel, therapySettings)
-    }
-    
-    public func saveCarbRatioSchedule(carbRatioSchedule: CarbRatioSchedule) {
-        therapySettings.carbRatioSchedule = carbRatioSchedule
-        didSave?(TherapySetting.carbRatio, therapySettings)
-    }
-    
-    public func saveInsulinSensitivitySchedule(insulinSensitivitySchedule: InsulinSensitivitySchedule) {
-        therapySettings.insulinSensitivitySchedule = insulinSensitivitySchedule
-        didSave?(TherapySetting.insulinSensitivity, therapySettings)
-    }
-}

File diff suppressed because it is too large
+ 0 - 1736
Dependecies/SwiftCharts/SwiftCharts.xcodeproj/project.pbxproj


+ 0 - 7
Dependecies/SwiftCharts/SwiftCharts.xcodeproj/project.xcworkspace/contents.xcworkspacedata

@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Workspace
-   version = "1.0">
-   <FileRef
-      location = "self:SwiftCharts.xcodeproj">
-   </FileRef>
-</Workspace>

+ 0 - 8
Dependecies/SwiftCharts/SwiftCharts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist

@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>IDEDidComputeMac32BitWarning</key>
-	<true/>
-</dict>
-</plist>

+ 0 - 87
Dependecies/SwiftCharts/SwiftCharts.xcodeproj/xcshareddata/xcschemes/Examples.xcscheme

@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Scheme
-   LastUpgradeVersion = "1240"
-   version = "1.3">
-   <BuildAction
-      parallelizeBuildables = "YES"
-      buildImplicitDependencies = "YES">
-      <BuildActionEntries>
-         <BuildActionEntry
-            buildForTesting = "YES"
-            buildForRunning = "YES"
-            buildForProfiling = "YES"
-            buildForArchiving = "YES"
-            buildForAnalyzing = "YES">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "06342AC01B8AAD7F001C9F5D"
-               BuildableName = "Examples.app"
-               BlueprintName = "Examples"
-               ReferencedContainer = "container:SwiftCharts.xcodeproj">
-            </BuildableReference>
-         </BuildActionEntry>
-      </BuildActionEntries>
-   </BuildAction>
-   <TestAction
-      buildConfiguration = "Debug"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      shouldUseLaunchSchemeArgsEnv = "YES">
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "06342AC01B8AAD7F001C9F5D"
-            BuildableName = "Examples.app"
-            BlueprintName = "Examples"
-            ReferencedContainer = "container:SwiftCharts.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-      <Testables>
-      </Testables>
-   </TestAction>
-   <LaunchAction
-      buildConfiguration = "Debug"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      launchStyle = "0"
-      useCustomWorkingDirectory = "NO"
-      ignoresPersistentStateOnLaunch = "NO"
-      debugDocumentVersioning = "YES"
-      debugServiceExtension = "internal"
-      allowLocationSimulation = "YES">
-      <BuildableProductRunnable
-         runnableDebuggingMode = "0">
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "06342AC01B8AAD7F001C9F5D"
-            BuildableName = "Examples.app"
-            BlueprintName = "Examples"
-            ReferencedContainer = "container:SwiftCharts.xcodeproj">
-         </BuildableReference>
-      </BuildableProductRunnable>
-   </LaunchAction>
-   <ProfileAction
-      buildConfiguration = "Release"
-      shouldUseLaunchSchemeArgsEnv = "YES"
-      savedToolIdentifier = ""
-      useCustomWorkingDirectory = "NO"
-      debugDocumentVersioning = "YES">
-      <BuildableProductRunnable
-         runnableDebuggingMode = "0">
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "06342AC01B8AAD7F001C9F5D"
-            BuildableName = "Examples.app"
-            BlueprintName = "Examples"
-            ReferencedContainer = "container:SwiftCharts.xcodeproj">
-         </BuildableReference>
-      </BuildableProductRunnable>
-   </ProfileAction>
-   <AnalyzeAction
-      buildConfiguration = "Debug">
-   </AnalyzeAction>
-   <ArchiveAction
-      buildConfiguration = "Release"
-      revealArchiveInOrganizer = "YES">
-   </ArchiveAction>
-</Scheme>

+ 0 - 76
Dependecies/SwiftCharts/SwiftCharts.xcodeproj/xcshareddata/xcschemes/SwiftCharts tvOS.xcscheme

@@ -1,76 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Scheme
-   LastUpgradeVersion = "1240"
-   version = "1.3">
-   <BuildAction
-      parallelizeBuildables = "YES"
-      buildImplicitDependencies = "YES">
-      <BuildActionEntries>
-         <BuildActionEntry
-            buildForTesting = "YES"
-            buildForRunning = "YES"
-            buildForProfiling = "YES"
-            buildForArchiving = "YES"
-            buildForAnalyzing = "YES">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "22E7020E1BF5B8EC00C19675"
-               BuildableName = "SwiftCharts.framework"
-               BlueprintName = "SwiftCharts tvOS"
-               ReferencedContainer = "container:SwiftCharts.xcodeproj">
-            </BuildableReference>
-         </BuildActionEntry>
-      </BuildActionEntries>
-   </BuildAction>
-   <TestAction
-      buildConfiguration = "Debug"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      shouldUseLaunchSchemeArgsEnv = "YES">
-      <Testables>
-      </Testables>
-   </TestAction>
-   <LaunchAction
-      buildConfiguration = "Debug"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      launchStyle = "0"
-      useCustomWorkingDirectory = "NO"
-      ignoresPersistentStateOnLaunch = "NO"
-      debugDocumentVersioning = "YES"
-      debugServiceExtension = "internal"
-      allowLocationSimulation = "YES">
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "22E7020E1BF5B8EC00C19675"
-            BuildableName = "SwiftCharts.framework"
-            BlueprintName = "SwiftCharts tvOS"
-            ReferencedContainer = "container:SwiftCharts.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-   </LaunchAction>
-   <ProfileAction
-      buildConfiguration = "Release"
-      shouldUseLaunchSchemeArgsEnv = "YES"
-      savedToolIdentifier = ""
-      useCustomWorkingDirectory = "NO"
-      debugDocumentVersioning = "YES">
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "22E7020E1BF5B8EC00C19675"
-            BuildableName = "SwiftCharts.framework"
-            BlueprintName = "SwiftCharts tvOS"
-            ReferencedContainer = "container:SwiftCharts.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-   </ProfileAction>
-   <AnalyzeAction
-      buildConfiguration = "Debug">
-   </AnalyzeAction>
-   <ArchiveAction
-      buildConfiguration = "Release"
-      revealArchiveInOrganizer = "YES">
-   </ArchiveAction>
-</Scheme>

+ 0 - 109
Dependecies/SwiftCharts/SwiftCharts.xcodeproj/xcshareddata/xcschemes/SwiftCharts.xcscheme

@@ -1,109 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Scheme
-   LastUpgradeVersion = "1240"
-   version = "1.3">
-   <BuildAction
-      parallelizeBuildables = "YES"
-      buildImplicitDependencies = "YES">
-      <BuildActionEntries>
-         <BuildActionEntry
-            buildForTesting = "YES"
-            buildForRunning = "YES"
-            buildForProfiling = "YES"
-            buildForArchiving = "YES"
-            buildForAnalyzing = "YES">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "06405DA51B8AA74700A689FF"
-               BuildableName = "SwiftCharts.framework"
-               BlueprintName = "SwiftCharts"
-               ReferencedContainer = "container:SwiftCharts.xcodeproj">
-            </BuildableReference>
-         </BuildActionEntry>
-         <BuildActionEntry
-            buildForTesting = "YES"
-            buildForRunning = "YES"
-            buildForProfiling = "NO"
-            buildForArchiving = "NO"
-            buildForAnalyzing = "YES">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "06405DB01B8AA74700A689FF"
-               BuildableName = "SwiftChartsTests.xctest"
-               BlueprintName = "SwiftChartsTests"
-               ReferencedContainer = "container:SwiftCharts.xcodeproj">
-            </BuildableReference>
-         </BuildActionEntry>
-      </BuildActionEntries>
-   </BuildAction>
-   <TestAction
-      buildConfiguration = "Debug"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      shouldUseLaunchSchemeArgsEnv = "YES">
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "06405DA51B8AA74700A689FF"
-            BuildableName = "SwiftCharts.framework"
-            BlueprintName = "SwiftCharts"
-            ReferencedContainer = "container:SwiftCharts.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-      <Testables>
-         <TestableReference
-            skipped = "NO">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "06405DB01B8AA74700A689FF"
-               BuildableName = "SwiftChartsTests.xctest"
-               BlueprintName = "SwiftChartsTests"
-               ReferencedContainer = "container:SwiftCharts.xcodeproj">
-            </BuildableReference>
-         </TestableReference>
-      </Testables>
-   </TestAction>
-   <LaunchAction
-      buildConfiguration = "Release"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      launchStyle = "0"
-      useCustomWorkingDirectory = "NO"
-      ignoresPersistentStateOnLaunch = "NO"
-      debugDocumentVersioning = "YES"
-      debugServiceExtension = "internal"
-      allowLocationSimulation = "YES">
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "06405DA51B8AA74700A689FF"
-            BuildableName = "SwiftCharts.framework"
-            BlueprintName = "SwiftCharts"
-            ReferencedContainer = "container:SwiftCharts.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-   </LaunchAction>
-   <ProfileAction
-      buildConfiguration = "Release"
-      shouldUseLaunchSchemeArgsEnv = "YES"
-      savedToolIdentifier = ""
-      useCustomWorkingDirectory = "NO"
-      debugDocumentVersioning = "YES">
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "06405DA51B8AA74700A689FF"
-            BuildableName = "SwiftCharts.framework"
-            BlueprintName = "SwiftCharts"
-            ReferencedContainer = "container:SwiftCharts.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-   </ProfileAction>
-   <AnalyzeAction
-      buildConfiguration = "Debug">
-   </AnalyzeAction>
-   <ArchiveAction
-      buildConfiguration = "Release"
-      revealArchiveInOrganizer = "YES">
-   </ArchiveAction>
-</Scheme>

+ 10 - 16
FreeAPS.xcodeproj/project.pbxproj

@@ -139,9 +139,6 @@
 		38887DFB25F61F7600944304 /* RileyLinkKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 38887DDD25F61F7500944304 /* RileyLinkKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
 		38887DFC25F61F7600944304 /* RileyLinkKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 38887DDE25F61F7500944304 /* RileyLinkKitUI.framework */; };
 		38887DFD25F61F7600944304 /* RileyLinkKitUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 38887DDE25F61F7500944304 /* RileyLinkKitUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
-		38887DFE25F61F7600944304 /* SwiftCharts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 38887DDF25F61F7500944304 /* SwiftCharts.framework */; };
-		38887DFF25F61F7600944304 /* SwiftCharts.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 38887DDF25F61F7500944304 /* SwiftCharts.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
-		38887E2125F6209B00944304 /* SwiftCharts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 38887E2025F6209B00944304 /* SwiftCharts.framework */; };
 		388E595C25AD948C0019842D /* FreeAPSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 388E595B25AD948C0019842D /* FreeAPSApp.swift */; };
 		388E596025AD948E0019842D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 388E595F25AD948E0019842D /* Assets.xcassets */; };
 		388E596C25AD95110019842D /* OpenAPS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 388E596B25AD95110019842D /* OpenAPS.swift */; };
@@ -151,10 +148,10 @@
 		388E5A6025B6F2310019842D /* Autosens.swift in Sources */ = {isa = PBXBuildFile; fileRef = 388E5A5F25B6F2310019842D /* Autosens.swift */; };
 		389442CB25F65F7100FA1F27 /* NightscoutTreatment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 389442CA25F65F7100FA1F27 /* NightscoutTreatment.swift */; };
 		3895E4C625B9E00D00214B37 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3895E4C525B9E00D00214B37 /* Preferences.swift */; };
-		389FE32725F3ABE6002E92E0 /* CareKitUI in Frameworks */ = {isa = PBXBuildFile; productRef = 389FE32625F3ABE6002E92E0 /* CareKitUI */; };
 		389FE32A25F3AC44002E92E0 /* GlucoseChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 389FE32925F3AC44002E92E0 /* GlucoseChartView.swift */; };
 		38A00B1F25FC00F7006BC0B0 /* Autotune.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38A00B1E25FC00F7006BC0B0 /* Autotune.swift */; };
 		38A00B2325FC2B55006BC0B0 /* LRUCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38A00B2225FC2B55006BC0B0 /* LRUCache.swift */; };
+		38A00B2E25FCD582006BC0B0 /* Charts in Frameworks */ = {isa = PBXBuildFile; productRef = 38A00B2D25FCD582006BC0B0 /* Charts */; };
 		38A0363B25ECF07E00FCBB52 /* GlucoseStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38A0363A25ECF07E00FCBB52 /* GlucoseStorage.swift */; };
 		38A0364225ED069400FCBB52 /* TempBasal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38A0364125ED069400FCBB52 /* TempBasal.swift */; };
 		38A13D3225E28B4B00EAA382 /* PumpHistoryEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38A13D3125E28B4B00EAA382 /* PumpHistoryEvent.swift */; };
@@ -272,7 +269,6 @@
 				38887DED25F61F7500944304 /* Crypto.framework in Embed Frameworks */,
 				38887DE525F61F7500944304 /* LoopTestingKit.framework in Embed Frameworks */,
 				38887DE125F61F7500944304 /* LoopKit.framework in Embed Frameworks */,
-				38887DFF25F61F7600944304 /* SwiftCharts.framework in Embed Frameworks */,
 				38887DEF25F61F7500944304 /* MinimedKit.framework in Embed Frameworks */,
 				38887DF325F61F7600944304 /* NightscoutUploadKit.framework in Embed Frameworks */,
 				38887DFB25F61F7600944304 /* RileyLinkKit.framework in Embed Frameworks */,
@@ -532,6 +528,7 @@
 				3811DE1025C9D37700A708ED /* Swinject in Frameworks */,
 				383948D325CD4D6D00E91849 /* Disk in Frameworks */,
 				38887DF825F61F7600944304 /* RileyLinkBLEKit.framework in Frameworks */,
+				38A00B2E25FCD582006BC0B0 /* Charts in Frameworks */,
 				38887DEC25F61F7500944304 /* Crypto.framework in Frameworks */,
 				38B17B6625DD90E0005CAE3D /* SwiftDate in Frameworks */,
 				38887DEA25F61F7500944304 /* MKRingProgressView.framework in Frameworks */,
@@ -542,9 +539,6 @@
 				38887DFC25F61F7600944304 /* RileyLinkKitUI.framework in Frameworks */,
 				38887DEE25F61F7500944304 /* MinimedKit.framework in Frameworks */,
 				38887DE025F61F7500944304 /* LoopKit.framework in Frameworks */,
-				38887E2125F6209B00944304 /* SwiftCharts.framework in Frameworks */,
-				38887DFE25F61F7600944304 /* SwiftCharts.framework in Frameworks */,
-				389FE32725F3ABE6002E92E0 /* CareKitUI in Frameworks */,
 				38887DE225F61F7500944304 /* LoopKitUI.framework in Frameworks */,
 				38887DE625F61F7500944304 /* MockKit.framework in Frameworks */,
 				38887DF025F61F7500944304 /* MinimedKitUI.framework in Frameworks */,
@@ -1417,7 +1411,7 @@
 				3811DE0F25C9D37700A708ED /* Swinject */,
 				383948D225CD4D6D00E91849 /* Disk */,
 				38B17B6525DD90E0005CAE3D /* SwiftDate */,
-				389FE32625F3ABE6002E92E0 /* CareKitUI */,
+				38A00B2D25FCD582006BC0B0 /* Charts */,
 			);
 			productName = FreeAPS;
 			productReference = 388E595825AD948C0019842D /* FreeAPS.app */;
@@ -1472,7 +1466,7 @@
 				3811DE0E25C9D37700A708ED /* XCRemoteSwiftPackageReference "Swinject" */,
 				383948D125CD4D6D00E91849 /* XCRemoteSwiftPackageReference "Disk" */,
 				38B17B6425DD90E0005CAE3D /* XCRemoteSwiftPackageReference "SwiftDate" */,
-				389FE32525F3ABE6002E92E0 /* XCRemoteSwiftPackageReference "CareKit" */,
+				38A00B2C25FCD581006BC0B0 /* XCRemoteSwiftPackageReference "Charts" */,
 			);
 			productRefGroup = 388E595925AD948C0019842D /* Products */;
 			projectDirPath = "";
@@ -2007,12 +2001,12 @@
 				minimumVersion = 0.6.4;
 			};
 		};
-		389FE32525F3ABE6002E92E0 /* XCRemoteSwiftPackageReference "CareKit" */ = {
+		38A00B2C25FCD581006BC0B0 /* XCRemoteSwiftPackageReference "Charts" */ = {
 			isa = XCRemoteSwiftPackageReference;
-			repositoryURL = "https://github.com/carekit-apple/CareKit";
+			repositoryURL = "https://github.com/danielgindi/Charts";
 			requirement = {
 				kind = upToNextMajorVersion;
-				minimumVersion = 2.0.1;
+				minimumVersion = 4.0.1;
 			};
 		};
 		38B17B6425DD90E0005CAE3D /* XCRemoteSwiftPackageReference "SwiftDate" */ = {
@@ -2036,10 +2030,10 @@
 			package = 383948D125CD4D6D00E91849 /* XCRemoteSwiftPackageReference "Disk" */;
 			productName = Disk;
 		};
-		389FE32625F3ABE6002E92E0 /* CareKitUI */ = {
+		38A00B2D25FCD582006BC0B0 /* Charts */ = {
 			isa = XCSwiftPackageProductDependency;
-			package = 389FE32525F3ABE6002E92E0 /* XCRemoteSwiftPackageReference "CareKit" */;
-			productName = CareKitUI;
+			package = 38A00B2C25FCD581006BC0B0 /* XCRemoteSwiftPackageReference "Charts" */;
+			productName = Charts;
 		};
 		38B17B6525DD90E0005CAE3D /* SwiftDate */ = {
 			isa = XCSwiftPackageProductDependency;

+ 0 - 28
FreeAPS.xcodeproj/xcshareddata/xcschemes/FreeAPS.xcscheme

@@ -272,34 +272,6 @@
                ReferencedContainer = "container:Dependecies/rileylink_ios/RileyLink.xcodeproj">
             </BuildableReference>
          </BuildActionEntry>
-         <BuildActionEntry
-            buildForTesting = "YES"
-            buildForRunning = "YES"
-            buildForProfiling = "YES"
-            buildForArchiving = "YES"
-            buildForAnalyzing = "YES">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "06405DA51B8AA74700A689FF"
-               BuildableName = "SwiftCharts.framework"
-               BlueprintName = "SwiftCharts"
-               ReferencedContainer = "container:Dependecies/SwiftCharts/SwiftCharts.xcodeproj">
-            </BuildableReference>
-         </BuildActionEntry>
-         <BuildActionEntry
-            buildForTesting = "YES"
-            buildForRunning = "YES"
-            buildForProfiling = "YES"
-            buildForArchiving = "YES"
-            buildForAnalyzing = "YES">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "22E7020E1BF5B8EC00C19675"
-               BuildableName = "SwiftCharts.framework"
-               BlueprintName = "SwiftCharts tvOS"
-               ReferencedContainer = "container:Dependecies/SwiftCharts/SwiftCharts.xcodeproj">
-            </BuildableReference>
-         </BuildActionEntry>
       </BuildActionEntries>
    </BuildAction>
    <TestAction

+ 0 - 3
FreeAPS.xcworkspace/contents.xcworkspacedata

@@ -5,9 +5,6 @@
       location = "group:FreeAPS.xcodeproj">
    </FileRef>
    <FileRef
-      location = "group:Dependecies/SwiftCharts/SwiftCharts.xcodeproj">
-   </FileRef>
-   <FileRef
       location = "group:Dependecies/MKRingProgressView/MKRingProgressView.xcodeproj">
    </FileRef>
    <FileRef

+ 22 - 4
FreeAPS.xcworkspace/xcshareddata/swiftpm/Package.resolved

@@ -2,12 +2,12 @@
   "object": {
     "pins": [
       {
-        "package": "CareKit",
-        "repositoryURL": "https://github.com/carekit-apple/CareKit",
+        "package": "Charts",
+        "repositoryURL": "https://github.com/danielgindi/Charts",
         "state": {
           "branch": null,
-          "revision": "51cef0b8e88b3c47c183fe36e8afc1f695bae44f",
-          "version": "2.0.1"
+          "revision": "8d134a78bb2cb9e7a0f05ecbd5880bb05cd02863",
+          "version": "4.0.1"
         }
       },
       {
@@ -20,6 +20,24 @@
         }
       },
       {
+        "package": "swift-algorithms",
+        "repositoryURL": "https://github.com/apple/swift-algorithms",
+        "state": {
+          "branch": null,
+          "revision": "1e761dd787b0f148f0b7aec42a7ff401767c26fa",
+          "version": "0.0.3"
+        }
+      },
+      {
+        "package": "swift-numerics",
+        "repositoryURL": "https://github.com/apple/swift-numerics",
+        "state": {
+          "branch": null,
+          "revision": "6583ac70c326c3ee080c1d42d9ca3361dca816cd",
+          "version": "0.1.0"
+        }
+      },
+      {
         "package": "SwiftDate",
         "repositoryURL": "https://github.com/malcommac/SwiftDate",
         "state": {

+ 124 - 50
FreeAPS/Sources/Modules/Home/View/GlucoseChartView.swift

@@ -1,99 +1,173 @@
-import CareKitUI
+import Charts
+import SwiftDate
 import SwiftUI
 
+extension DateFormatter: AxisValueFormatter {
+    public func stringForValue(_ value: Double, axis _: AxisBase?) -> String {
+        timeStyle = .short
+        return string(from: Date(timeIntervalSince1970: value))
+    }
+}
+
 struct GlucoseChartView: UIViewRepresentable {
     @Binding var glucose: [BloodGlucose]
     @Binding var suggestion: Suggestion?
 
-    func makeUIView(context _: Context) -> OCKCartesianGraphView {
-        let view = OCKCartesianGraphView(type: .scatter)
+    func makeUIView(context _: Context) -> LineChartView {
+        let view = LineChartView()
         makeDataPointsFor(view: view)
+        view.xAxis.valueFormatter = DateFormatter()
         return view
     }
 
-    func updateUIView(_ view: OCKCartesianGraphView, context _: Context) {
+    func updateUIView(_ view: LineChartView, context _: Context) {
         makeDataPointsFor(view: view)
     }
 
-    private func makeDataPointsFor(view: OCKCartesianGraphView) {
+    private func makeDataPointsFor(view: LineChartView) {
         let dataPoints = glucose.map {
-            CGPoint(x: CGFloat($0.dateString.timeIntervalSince1970), y: CGFloat($0.sgv ?? 0))
+            ChartDataEntry(x: $0.dateString.timeIntervalSince1970, y: Double($0.sgv ?? 0))
         }
-        var data = OCKDataSeries(
-            dataPoints: dataPoints,
-            title: "BG",
-            color: .green
-        )
-        data.size = 1
+
+        let data = MyLineChartDataSet(entries: dataPoints, label: "BG")
+        data.drawCirclesEnabled = true
+        data.circleRadius = 2
+        data.setCircleColor(.green)
+        data.setColor(.green)
+        data.lineWidth = 0
+        data.drawValuesEnabled = false
 
         var series = [data]
 
-        let lastDate = glucose.last?.dateString ?? Date()
+        let lastDate = suggestion?.deliverAt ?? Date()
 
         if let iob = suggestion?.predictions?.iob {
             let dataPoints = iob.enumerated().map {
-                CGPoint(
-                    x: CGFloat(lastDate.addingTimeInterval(Double($0 * 300)).timeIntervalSince1970),
-                    y: CGFloat($1)
+                ChartDataEntry(
+                    x: lastDate.addingTimeInterval(Double($0 * 300)).timeIntervalSince1970,
+                    y: Double($1)
                 )
             }
-            var data = OCKDataSeries(
-                dataPoints: dataPoints,
-                title: "IOB",
-                color: .blue
-            )
-            data.size = 1
+            let data = MyLineChartDataSet(entries: dataPoints, label: "IOB")
+            data.drawCirclesEnabled = true
+            data.circleRadius = 2
+            data.setCircleColor(.blue)
+            data.setColor(.blue)
+            data.lineWidth = 0
+            data.drawValuesEnabled = false
             series.append(data)
         }
 
         if let zt = suggestion?.predictions?.zt {
             let dataPoints = zt.enumerated().map {
-                CGPoint(
-                    x: CGFloat(lastDate.addingTimeInterval(Double($0 * 300)).timeIntervalSince1970),
-                    y: CGFloat($1)
+                ChartDataEntry(
+                    x: lastDate.addingTimeInterval(Double($0 * 300)).timeIntervalSince1970,
+                    y: Double($1)
                 )
             }
-            var data = OCKDataSeries(
-                dataPoints: dataPoints,
-                title: "ZT",
-                color: .cyan
-            )
-            data.size = 1
+            let data = MyLineChartDataSet(entries: dataPoints, label: "ZT")
+            data.drawCirclesEnabled = true
+            data.circleRadius = 2
+            data.setCircleColor(.cyan)
+            data.setColor(.cyan)
+            data.lineWidth = 0
+            data.drawValuesEnabled = false
             series.append(data)
         }
 
         if let cob = suggestion?.predictions?.cob {
             let dataPoints = cob.enumerated().map {
-                CGPoint(
-                    x: CGFloat(lastDate.addingTimeInterval(Double($0 * 300)).timeIntervalSince1970),
-                    y: CGFloat($1)
+                ChartDataEntry(
+                    x: lastDate.addingTimeInterval(Double($0 * 300)).timeIntervalSince1970,
+                    y: Double($1)
                 )
             }
-            var data = OCKDataSeries(
-                dataPoints: dataPoints,
-                title: "COB",
-                color: .orange
-            )
-            data.size = 1
+            let data = MyLineChartDataSet(entries: dataPoints, label: "COB")
+            data.drawCirclesEnabled = true
+            data.circleRadius = 2
+            data.setCircleColor(.orange)
+            data.setColor(.orange)
+            data.lineWidth = 0
+            data.drawValuesEnabled = false
             series.append(data)
         }
 
         if let uam = suggestion?.predictions?.uam {
             let dataPoints = uam.enumerated().map {
-                CGPoint(
-                    x: CGFloat(lastDate.addingTimeInterval(Double($0 * 300)).timeIntervalSince1970),
-                    y: CGFloat($1)
+                ChartDataEntry(
+                    x: lastDate.addingTimeInterval(Double($0 * 300)).timeIntervalSince1970,
+                    y: Double($1)
                 )
             }
-            var data = OCKDataSeries(
-                dataPoints: dataPoints,
-                title: "UAM",
-                color: .yellow
-            )
-            data.size = 1
+            let data = MyLineChartDataSet(entries: dataPoints, label: "UAM")
+            data.drawCirclesEnabled = true
+            data.circleRadius = 2
+            data.setCircleColor(.yellow)
+            data.setColor(.yellow)
+            data.lineWidth = 0
+            data.drawValuesEnabled = false
             series.append(data)
         }
 
-        view.dataSeries = series
+        view.data = LineChartData(dataSets: series)
+    }
+}
+
+class MyLineChartDataSet: LineChartDataSet {
+    override func entryIndex(x xValue: Double, closestToY yValue: Double, rounding: ChartDataSetRounding) -> Int {
+        var closest = partitioningIndex { $0.x >= xValue }
+        if closest >= endIndex {
+            closest = endIndex - 1
+        }
+
+        let closestXValue = self[closest].x
+
+        switch rounding {
+        case .up:
+            // If rounding up, and found x-value is lower than specified x, and we can go upper...
+            if closestXValue < xValue, closest < index(before: endIndex)
+            {
+                formIndex(after: &closest)
+            }
+
+        case .down:
+            // If rounding down, and found x-value is upper than specified x, and we can go lower...
+            if closestXValue > xValue, closest > startIndex
+            {
+                formIndex(before: &closest)
+            }
+
+        case .closest:
+            break
+        }
+
+        // Search by closest to y-value
+        if !yValue.isNaN
+        {
+            while closest > startIndex, self[index(before: closest)].x == closestXValue
+            {
+                formIndex(before: &closest)
+            }
+
+            var closestYValue = self[closest].y
+            var closestYIndex = closest
+
+            while closest < index(before: endIndex)
+            {
+                formIndex(after: &closest)
+                let value = self[closest]
+
+                if value.x != closestXValue { break }
+                if abs(value.y - yValue) <= abs(closestYValue - yValue)
+                {
+                    closestYValue = yValue
+                    closestYIndex = closest
+                }
+            }
+
+            closest = closestYIndex
+        }
+
+        return closest
     }
 }

+ 1 - 1
FreeAPS/Sources/Modules/Home/View/HomeRootView.swift

@@ -11,7 +11,7 @@ extension Home {
                         Text("Header")
                     }
                     ScrollView(.vertical, showsIndicators: false) {
-                        GlucoseChartView(glucose: $viewModel.glucose, suggestion: $viewModel.suggestion).frame(height: 150)
+                        GlucoseChartView(glucose: $viewModel.glucose, suggestion: $viewModel.suggestion).frame(height: 300)
                         if let reason = viewModel.suggestion?.reason {
                             Text(reason).font(.caption).padding()
                         }