NightScoutViewController.swift 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // LoopFollow
  2. // NightScoutViewController.swift
  3. import Combine
  4. import UIKit
  5. import WebKit
  6. class NightscoutViewController: UIViewController {
  7. @IBOutlet var webView: WKWebView!
  8. private var cancellables = Set<AnyCancellable>()
  9. override func viewDidLoad() {
  10. super.viewDidLoad()
  11. overrideUserInterfaceStyle = Storage.shared.appearanceMode.value.userInterfaceStyle
  12. // Listen for appearance setting changes
  13. Storage.shared.appearanceMode.$value
  14. .receive(on: DispatchQueue.main)
  15. .sink { [weak self] mode in
  16. self?.overrideUserInterfaceStyle = mode.userInterfaceStyle
  17. }
  18. .store(in: &cancellables)
  19. // Listen for system appearance changes (when in System mode)
  20. NotificationCenter.default.publisher(for: .appearanceDidChange)
  21. .receive(on: DispatchQueue.main)
  22. .sink { [weak self] _ in
  23. self?.overrideUserInterfaceStyle = Storage.shared.appearanceMode.value.userInterfaceStyle
  24. }
  25. .store(in: &cancellables)
  26. var url = Storage.shared.url.value
  27. let token = Storage.shared.token.value
  28. if token != "" {
  29. url = url + "?token=" + token
  30. }
  31. guard let myUrl = URL(string: url) else { return }
  32. let webpagePreferences = WKWebpagePreferences()
  33. webpagePreferences.allowsContentJavaScript = true
  34. webView.configuration.defaultWebpagePreferences = webpagePreferences
  35. webView.navigationDelegate = self
  36. webView.uiDelegate = self
  37. webView.load(URLRequest(url: myUrl))
  38. let refreshControl = UIRefreshControl()
  39. refreshControl.addTarget(self, action: #selector(reloadWebView(_:)), for: .valueChanged)
  40. webView.scrollView.addSubview(refreshControl)
  41. }
  42. @objc func reloadWebView(_ sender: UIRefreshControl) {
  43. clearWebCache()
  44. webView.reload()
  45. sender.endRefreshing()
  46. }
  47. override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
  48. super.traitCollectionDidChange(previousTraitCollection)
  49. if Storage.shared.appearanceMode.value == .system,
  50. previousTraitCollection?.userInterfaceStyle != traitCollection.userInterfaceStyle
  51. {
  52. overrideUserInterfaceStyle = Storage.shared.appearanceMode.value.userInterfaceStyle
  53. }
  54. }
  55. func clearWebCache() {
  56. let dataStore = WKWebsiteDataStore.default()
  57. let cacheTypes = Set([WKWebsiteDataTypeDiskCache, WKWebsiteDataTypeMemoryCache])
  58. let date = Date(timeIntervalSince1970: 0)
  59. dataStore.removeData(ofTypes: cacheTypes, modifiedSince: date) {
  60. print("Web cache cleared.")
  61. }
  62. }
  63. // this handles target=_blank links by opening them in the same view
  64. func webView(webView: WKWebView!, createWebViewWithConfiguration _: WKWebViewConfiguration!, forNavigationAction navigationAction: WKNavigationAction!, windowFeatures _: WKWindowFeatures!) -> WKWebView! {
  65. if let frame = navigationAction.targetFrame,
  66. frame.isMainFrame
  67. {
  68. return nil
  69. }
  70. // for _blank target or non-mainFrame target
  71. webView.load(navigationAction.request)
  72. return nil
  73. }
  74. }
  75. // MARK: - WKUIDelegate implementation
  76. extension NightscoutViewController: WKNavigationDelegate, WKUIDelegate {
  77. func webView(_: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame _: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
  78. let alertCtrl = UIAlertController(title: nil, message: message, preferredStyle: .alert)
  79. alertCtrl.addAction(UIAlertAction(title: "OK", style: .default) { _ in
  80. completionHandler(true)
  81. })
  82. alertCtrl.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in
  83. completionHandler(false)
  84. })
  85. present(alertCtrl, animated: true)
  86. }
  87. func webView(_: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
  88. guard let _ = navigationAction.request.url else {
  89. decisionHandler(.cancel)
  90. return
  91. }
  92. decisionHandler(.allow)
  93. }
  94. func webView(_: WKWebView, shouldStartLoadWith request: URLRequest) -> Bool {
  95. guard let url = request.url else {
  96. return false
  97. }
  98. NSLog("Should start: \(url.absoluteString)")
  99. return true
  100. }
  101. func webView(_ webView: WKWebView, createWebViewWith _: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures _: WKWindowFeatures) -> WKWebView? {
  102. if navigationAction.targetFrame == nil {
  103. webView.load(navigationAction.request)
  104. }
  105. return nil
  106. }
  107. func webView(_ webView: WKWebView, didFinish _: WKNavigation!) {
  108. let javascript = """
  109. var meta = document.querySelector('meta[name="viewport"]');
  110. if (meta) {
  111. meta.setAttribute('content', 'width=device-width, initial-scale=0.9, maximum-scale=5.0, user-scalable=yes');
  112. }
  113. """
  114. webView.evaluateJavaScript(javascript)
  115. }
  116. }