// // ReaderViewController.swift // App // // Created by James Magahern on 2/15/21. // import UIKit import WebKit protocol ReaderViewControllerDelegate: AnyObject { func readerViewController(_ reader: ReaderViewController, didRequestNavigationToURL navigationURL: URL) } class ReaderViewController: UIViewController { public let baseURL: URL? public let readableHTMLString: String public var darkModeEnabled: Bool = false { didSet { bridge.darkModeEnabled = darkModeEnabled; updateDarkModeButton() } } public weak var delegate: ReaderViewControllerDelegate? private let bridge = ProcessBundleBridge(webViewConfiguration: nil) private let darkModeDisabledImage = UIImage(systemName: "moon.circle") private let darkModeEnabledImage = UIImage(systemName: "moon.circle.fill") private lazy var darkModeButton: UIBarButtonItem = { UIBarButtonItem(image: darkModeEnabledImage, style: .plain, target: self, action: #selector(self.didTapDarkModeButton)) }() init(readableHTMLString: String, baseURL: URL?) { self.readableHTMLString = readableHTMLString self.baseURL = baseURL super.init(nibName: nil, bundle: nil) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func loadView() { self.view = bridge.webView bridge.webView.navigationDelegate = self } override func viewDidLoad() { super.viewDidLoad() navigationItem.leftBarButtonItem = darkModeButton navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(self.didTapDoneButton)) } private func updateDarkModeButton() { if darkModeEnabled { darkModeButton.image = darkModeEnabledImage } else { darkModeButton.image = darkModeDisabledImage } } @objc private func didTapDoneButton(_ sender: Any?) { dismiss(animated: true, completion: nil) } @objc private func didTapDarkModeButton(_ sender: Any?) { darkModeEnabled = !darkModeEnabled } override func viewWillAppear(_ animated: Bool) { let readerHTMLURL = Bundle.main.url(forResource: "reader", withExtension: "html")! var readerHTML = try! String(contentsOf: readerHTMLURL) let bodyRange = readerHTML.range(of: "{{ body }}")! readerHTML.replaceSubrange(bodyRange, with: readableHTMLString) bridge.webView.loadHTMLString(readerHTML, baseURL: baseURL) updateDarkModeButton() } } extension ReaderViewController: WKNavigationDelegate { func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { guard let url = navigationAction.request.url else { return } if url == baseURL { decisionHandler(.allow) return } else { // Don't load links in here, dismiss the reader view and load them in the tab behind us. delegate?.readerViewController(self, didRequestNavigationToURL: url) dismiss(animated: true, completion: nil) decisionHandler(.cancel) } } }