SettingsViewController.swift 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. //
  2. // SettingsViewController.swift
  3. // LoopFollow
  4. //
  5. // Created by Jon Fawcett on 6/3/20.
  6. // Copyright © 2020 Jon Fawcett. All rights reserved.
  7. //
  8. import UIKit
  9. import Eureka
  10. import EventKit
  11. import EventKitUI
  12. class SettingsViewController: FormViewController {
  13. struct cal {
  14. var title: String
  15. var identifier: String
  16. }
  17. override func viewDidLoad() {
  18. super.viewDidLoad()
  19. if UserDefaultsRepository.forceDarkMode.value {
  20. overrideUserInterfaceStyle = .dark
  21. }
  22. form +++ Section("Nightscout Settings")
  23. <<< TextRow(){ row in
  24. row.title = "URL"
  25. row.placeholder = "https://mycgm.herokuapp.com"
  26. row.value = UserDefaultsRepository.url.value
  27. }.onChange { row in
  28. guard let value = row.value else { return }
  29. UserDefaultsRepository.url.value = value.lowercased()
  30. }
  31. buildGeneralSettings()
  32. buildAlarmSettings()
  33. buildGraphSettings()
  34. buildWatchSettings()
  35. }
  36. func buildGeneralSettings() {
  37. form
  38. +++ Section("General Settings")
  39. <<< SwitchRow("colorBGText") { row in
  40. row.title = "Color Main BG Text"
  41. row.value = UserDefaultsRepository.colorBGText.value
  42. }.onChange { [weak self] row in
  43. guard let value = row.value else { return }
  44. UserDefaultsRepository.colorBGText.value = value
  45. // Force main screen update
  46. guard let mainScreen = self?.tabBarController!.viewControllers?[0] as? MainViewController else { return }
  47. mainScreen.setBGTextColor()
  48. }
  49. <<< SwitchRow("forceDarkMode") { row in
  50. row.title = "Force Dark Mode (Restart App)"
  51. row.value = UserDefaultsRepository.forceDarkMode.value
  52. }.onChange { [weak self] row in
  53. guard let value = row.value else { return }
  54. UserDefaultsRepository.forceDarkMode.value = value
  55. }
  56. <<< SwitchRow("screenlockSwitchState") { row in
  57. row.title = "Keep Screen Active"
  58. row.value = UserDefaultsRepository.screenlockSwitchState.value
  59. }.onChange { [weak self] row in
  60. guard let value = row.value else { return }
  61. if value {
  62. UserDefaultsRepository.screenlockSwitchState.value = value
  63. }
  64. }
  65. <<< SwitchRow("backgroundRefresh"){ row in
  66. row.title = "Background Refresh"
  67. row.tag = "backgroundRefresh"
  68. row.value = UserDefaultsRepository.backgroundRefresh.value
  69. }.onChange { [weak self] row in
  70. guard let value = row.value else { return }
  71. UserDefaultsRepository.backgroundRefresh.value = value
  72. }
  73. <<< SliderRow() { row in
  74. row.title = "Refresh Minutes"
  75. row.tag = "backgroundRefreshFrequency"
  76. row.steps = 19
  77. row.value = Float(UserDefaultsRepository.backgroundRefreshFrequency.value)
  78. row.hidden = "$backgroundRefresh == false"
  79. }.cellSetup { cell, row in
  80. cell.slider.minimumValue = 0.5
  81. cell.slider.maximumValue = 10
  82. }
  83. <<< SwitchRow("appBadge"){ row in
  84. row.title = "Display App Badge"
  85. row.tag = "appBadge"
  86. row.value = UserDefaultsRepository.appBadge.value
  87. }.onChange { [weak self] row in
  88. guard let value = row.value else { return }
  89. UserDefaultsRepository.appBadge.value = value
  90. // Force main screen update
  91. guard let mainScreen = self?.tabBarController!.viewControllers?[0] as? MainViewController else { return }
  92. mainScreen.nightscoutLoader(forceLoad: true)
  93. }
  94. }
  95. func buildAlarmSettings() {
  96. form
  97. +++ Section("Alarm Settings")
  98. <<< SwitchRow("overrideSystemOutputVolume"){ row in
  99. row.title = "Override System Volume"
  100. row.value = UserDefaultsRepository.overrideSystemOutputVolume.value
  101. }.onChange { [weak self] row in
  102. guard let value = row.value else { return }
  103. UserDefaultsRepository.overrideSystemOutputVolume.value = value
  104. }
  105. <<< StepperRow("forcedOutputVolume") { row in
  106. row.title = "Volume Level"
  107. row.cell.stepper.stepValue = 0.05
  108. row.cell.stepper.minimumValue = 0
  109. row.cell.stepper.maximumValue = 1
  110. row.value = Double(UserDefaultsRepository.forcedOutputVolume.value)
  111. row.hidden = "$overrideSystemOutputVolume == false"
  112. row.displayValueFor = { value in
  113. guard let value = value else { return nil }
  114. return "\(Int(value*100))%"
  115. }
  116. }.onChange { [weak self] row in
  117. guard let value = row.value else { return }
  118. UserDefaultsRepository.forcedOutputVolume.value = Float(value)
  119. }
  120. /* <<< StepperRow("fadeInTimeInterval") { row in
  121. row.title = "Fade-in Seconds"
  122. row.cell.stepper.stepValue = 5
  123. row.cell.stepper.minimumValue = 0
  124. row.cell.stepper.maximumValue = 60
  125. row.value = Double(UserDefaultsRepository.fadeInTimeInterval.value)
  126. row.displayValueFor = { value in
  127. guard let value = value else { return nil }
  128. return "\(Int(value))"
  129. }
  130. }.onChange { [weak self] row in
  131. guard let value = row.value else { return }
  132. UserDefaultsRepository.fadeInTimeInterval.value = TimeInterval(value)
  133. }*/
  134. }
  135. func buildGraphSettings() {
  136. form
  137. +++ Section("Graph Settings")
  138. <<< SwitchRow("switchRowDots"){ row in
  139. row.title = "Display Dots"
  140. row.value = UserDefaultsRepository.showDots.value
  141. }.onChange { [weak self] row in
  142. guard let value = row.value else { return }
  143. UserDefaultsRepository.showDots.value = value
  144. // Force main screen update
  145. guard let mainScreen = self?.tabBarController!.viewControllers?[0] as? MainViewController else { return }
  146. mainScreen.nightscoutLoader(forceLoad: true)
  147. }
  148. <<< SwitchRow("switchRowLines"){ row in
  149. row.title = "Display Lines"
  150. row.value = UserDefaultsRepository.showLines.value
  151. }.onChange { [weak self] row in
  152. guard let value = row.value else { return }
  153. UserDefaultsRepository.showLines.value = value
  154. // Force main screen update
  155. guard let mainScreen = self?.tabBarController!.viewControllers?[0] as? MainViewController else { return }
  156. mainScreen.nightscoutLoader(forceLoad: true)
  157. }
  158. <<< StepperRow("lowLine") { row in
  159. row.title = "Low BG Display Value"
  160. row.cell.stepper.stepValue = 1
  161. row.cell.stepper.minimumValue = 40
  162. row.cell.stepper.maximumValue = 120
  163. row.value = Double(UserDefaultsRepository.lowLine.value)
  164. row.displayValueFor = { value in
  165. guard let value = value else { return nil }
  166. return "\(Int(value))"
  167. }
  168. }.onChange { [weak self] row in
  169. guard let value = row.value else { return }
  170. UserDefaultsRepository.lowLine.value = Int(value)
  171. // Force main screen update
  172. guard let mainScreen = self?.tabBarController!.viewControllers?[0] as? MainViewController else { return }
  173. mainScreen.nightscoutLoader(forceLoad: true)
  174. }
  175. <<< StepperRow("highLine") { row in
  176. row.title = "High BG Display Value"
  177. row.cell.stepper.stepValue = 1
  178. row.cell.stepper.minimumValue = 150
  179. row.cell.stepper.maximumValue = 400
  180. row.value = Double(UserDefaultsRepository.highLine.value)
  181. row.displayValueFor = { value in
  182. guard let value = value else { return nil }
  183. return "\(Int(value))"
  184. }
  185. }.onChange { [weak self] row in
  186. guard let value = row.value else { return }
  187. UserDefaultsRepository.highLine.value = Int(value)
  188. // Force main screen update
  189. guard let mainScreen = self?.tabBarController!.viewControllers?[0] as? MainViewController else { return }
  190. mainScreen.nightscoutLoader(forceLoad: true)
  191. }
  192. }
  193. func buildWatchSettings(){
  194. //array of calendars
  195. let store = EKEventStore()
  196. let ekCalendars = store.calendars(for: EKEntityType.event)
  197. var calendars: [cal] = []
  198. for i in 0..<ekCalendars.count{
  199. let item = cal(title: ekCalendars[i].title, identifier: ekCalendars[i].calendarIdentifier)
  200. calendars.append(item)
  201. }
  202. form
  203. +++ Section(header: "Watch Settings", footer: "Add the Apple calendar complication to your watch face for BG, Trend, Delta, COB, and IOB updated every 5 minutes. It is recommended to create a new calendar called 'Loop' and modify the calendar settings in the iPhone Watch App to only display the Loop calendar on your watch")
  204. <<< SwitchRow("writeCalendarEvent"){ row in
  205. row.title = "BG to Calendar"
  206. row.value = UserDefaultsRepository.writeCalendarEvent.value
  207. }.onChange { [weak self] row in
  208. guard let value = row.value else { return }
  209. UserDefaultsRepository.writeCalendarEvent.value = value
  210. }
  211. <<< PickerInputRow<String>("calendarIdentifier") { row in
  212. row.title = "Calendar"
  213. row.options = calendars.map { $0.identifier }
  214. row.hidden = "$writeCalendarEvent == false"
  215. row.value = UserDefaultsRepository.calendarIdentifier.value
  216. row.displayValueFor = { value in
  217. guard let value = value else { return nil }
  218. let matching = calendars
  219. .flatMap { $0 }
  220. .filter { $0.identifier.range(of: value) != nil || $0.title.range(of: value) != nil }
  221. if matching.count > 0 {
  222. return "\(String(matching[0].title))"
  223. } else {
  224. return " - "
  225. }
  226. }
  227. }.onChange { [weak self] row in
  228. guard let value = row.value else { return }
  229. UserDefaultsRepository.calendarIdentifier.value = value
  230. }
  231. }
  232. }