MoreMenuViewController.swift 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. // LoopFollow
  2. // MoreMenuViewController.swift
  3. import Combine
  4. import SwiftUI
  5. import UIKit
  6. class MoreMenuViewController: UIViewController {
  7. private var tableView: UITableView!
  8. private var cancellables = Set<AnyCancellable>()
  9. struct MenuItem {
  10. let title: String
  11. let icon: String
  12. let action: () -> Void
  13. }
  14. private var menuItems: [MenuItem] = []
  15. override func viewDidLoad() {
  16. super.viewDidLoad()
  17. title = "More"
  18. view.backgroundColor = .systemBackground
  19. // Apply appearance mode
  20. overrideUserInterfaceStyle = Storage.shared.appearanceMode.value.userInterfaceStyle
  21. // Listen for appearance setting changes
  22. Storage.shared.appearanceMode.$value
  23. .receive(on: DispatchQueue.main)
  24. .sink { [weak self] mode in
  25. self?.overrideUserInterfaceStyle = mode.userInterfaceStyle
  26. }
  27. .store(in: &cancellables)
  28. // Listen for system appearance changes (when in System mode)
  29. NotificationCenter.default.publisher(for: .appearanceDidChange)
  30. .receive(on: DispatchQueue.main)
  31. .sink { [weak self] _ in
  32. self?.overrideUserInterfaceStyle = Storage.shared.appearanceMode.value.userInterfaceStyle
  33. }
  34. .store(in: &cancellables)
  35. setupTableView()
  36. updateMenuItems()
  37. }
  38. override func viewWillAppear(_ animated: Bool) {
  39. super.viewWillAppear(animated)
  40. updateMenuItems()
  41. tableView.reloadData()
  42. Observable.shared.settingsPath.set(NavigationPath())
  43. }
  44. override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
  45. super.traitCollectionDidChange(previousTraitCollection)
  46. if Storage.shared.appearanceMode.value == .system,
  47. previousTraitCollection?.userInterfaceStyle != traitCollection.userInterfaceStyle
  48. {
  49. overrideUserInterfaceStyle = Storage.shared.appearanceMode.value.userInterfaceStyle
  50. }
  51. }
  52. private func setupTableView() {
  53. tableView = UITableView(frame: view.bounds, style: .insetGrouped)
  54. tableView.translatesAutoresizingMaskIntoConstraints = false
  55. tableView.delegate = self
  56. tableView.dataSource = self
  57. tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
  58. view.addSubview(tableView)
  59. NSLayoutConstraint.activate([
  60. tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
  61. tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
  62. tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
  63. tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
  64. ])
  65. }
  66. private func updateMenuItems() {
  67. menuItems = []
  68. // Always add Settings
  69. menuItems.append(MenuItem(
  70. title: "Settings",
  71. icon: "gear",
  72. action: { [weak self] in
  73. self?.openSettings()
  74. }
  75. ))
  76. // Add items based on their positions
  77. if Storage.shared.alarmsPosition.value == .more {
  78. menuItems.append(MenuItem(
  79. title: "Alarms",
  80. icon: "alarm",
  81. action: { [weak self] in
  82. self?.openAlarms()
  83. }
  84. ))
  85. }
  86. if Storage.shared.remotePosition.value == .more {
  87. menuItems.append(MenuItem(
  88. title: "Remote",
  89. icon: "antenna.radiowaves.left.and.right",
  90. action: { [weak self] in
  91. self?.openRemote()
  92. }
  93. ))
  94. }
  95. if Storage.shared.nightscoutPosition.value == .more {
  96. menuItems.append(MenuItem(
  97. title: "Nightscout",
  98. icon: "safari",
  99. action: { [weak self] in
  100. self?.openNightscout()
  101. }
  102. ))
  103. }
  104. }
  105. private func openSettings() {
  106. let settingsVC = UIHostingController(rootView: SettingsMenuView())
  107. let navController = UINavigationController(rootViewController: settingsVC)
  108. // Apply appearance mode
  109. let style = Storage.shared.appearanceMode.value.userInterfaceStyle
  110. settingsVC.overrideUserInterfaceStyle = style
  111. navController.overrideUserInterfaceStyle = style
  112. // Add a close button
  113. settingsVC.navigationItem.rightBarButtonItem = UIBarButtonItem(
  114. barButtonSystemItem: .done,
  115. target: self,
  116. action: #selector(dismissModal)
  117. )
  118. navController.modalPresentationStyle = .fullScreen
  119. present(navController, animated: true)
  120. }
  121. private func openAlarms() {
  122. let storyboard = UIStoryboard(name: "Main", bundle: nil)
  123. let alarmsVC = storyboard.instantiateViewController(withIdentifier: "AlarmViewController")
  124. let navController = UINavigationController(rootViewController: alarmsVC)
  125. // Apply appearance mode
  126. let style = Storage.shared.appearanceMode.value.userInterfaceStyle
  127. alarmsVC.overrideUserInterfaceStyle = style
  128. navController.overrideUserInterfaceStyle = style
  129. // Add a close button
  130. alarmsVC.navigationItem.rightBarButtonItem = UIBarButtonItem(
  131. barButtonSystemItem: .done,
  132. target: self,
  133. action: #selector(dismissModal)
  134. )
  135. navController.modalPresentationStyle = .fullScreen
  136. present(navController, animated: true)
  137. }
  138. private func openRemote() {
  139. let storyboard = UIStoryboard(name: "Main", bundle: nil)
  140. let remoteVC = storyboard.instantiateViewController(withIdentifier: "RemoteViewController")
  141. let navController = UINavigationController(rootViewController: remoteVC)
  142. // Apply appearance mode
  143. let style = Storage.shared.appearanceMode.value.userInterfaceStyle
  144. remoteVC.overrideUserInterfaceStyle = style
  145. navController.overrideUserInterfaceStyle = style
  146. // Add a close button
  147. remoteVC.navigationItem.rightBarButtonItem = UIBarButtonItem(
  148. barButtonSystemItem: .done,
  149. target: self,
  150. action: #selector(dismissModal)
  151. )
  152. navController.modalPresentationStyle = .fullScreen
  153. present(navController, animated: true)
  154. }
  155. private func openNightscout() {
  156. let storyboard = UIStoryboard(name: "Main", bundle: nil)
  157. let nightscoutVC = storyboard.instantiateViewController(withIdentifier: "NightscoutViewController")
  158. let navController = UINavigationController(rootViewController: nightscoutVC)
  159. // Apply appearance mode
  160. let style = Storage.shared.appearanceMode.value.userInterfaceStyle
  161. nightscoutVC.overrideUserInterfaceStyle = style
  162. navController.overrideUserInterfaceStyle = style
  163. // Add a close button
  164. nightscoutVC.navigationItem.rightBarButtonItem = UIBarButtonItem(
  165. barButtonSystemItem: .done,
  166. target: self,
  167. action: #selector(dismissModal)
  168. )
  169. navController.modalPresentationStyle = .fullScreen
  170. present(navController, animated: true)
  171. }
  172. @objc private func dismissModal() {
  173. dismiss(animated: true)
  174. }
  175. }
  176. extension MoreMenuViewController: UITableViewDataSource, UITableViewDelegate {
  177. func tableView(_: UITableView, numberOfRowsInSection _: Int) -> Int {
  178. return menuItems.count
  179. }
  180. func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  181. let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
  182. let item = menuItems[indexPath.row]
  183. var config = cell.defaultContentConfiguration()
  184. config.text = item.title
  185. config.image = UIImage(systemName: item.icon)
  186. cell.contentConfiguration = config
  187. cell.accessoryType = .disclosureIndicator
  188. return cell
  189. }
  190. func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  191. tableView.deselectRow(at: indexPath, animated: true)
  192. menuItems[indexPath.row].action()
  193. }
  194. }