// // ReadViewController.swift // Reader // // Created by Shadowfacts on 1/9/22. // import UIKit import WebKit import HTMLEntities class ReadViewController: UIViewController { private static let publishedFormatter: DateFormatter = { let f = DateFormatter() f.dateStyle = .medium f.timeStyle = .medium return f }() let fervorController: FervorController let item: Item override var prefersStatusBarHidden: Bool { navigationController?.isNavigationBarHidden ?? false } override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation { .slide } init(item: Item, fervorController: FervorController) { self.fervorController = fervorController self.item = item super.init(nibName: nil, bundle: nil) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func viewDidLoad() { super.viewDidLoad() navigationItem.largeTitleDisplayMode = .never view.backgroundColor = .appBackground let webView = WKWebView() webView.translatesAutoresizingMaskIntoConstraints = false webView.navigationDelegate = self if let content = itemContentHTML() { // todo: using the bundle url is the only way to get the stylesheet to load, but feels wrong // will break, e.g., images with relative urls webView.loadHTMLString(content, baseURL: Bundle.main.bundleURL) } view.addSubview(webView) NSLayoutConstraint.activate([ webView.leadingAnchor.constraint(equalTo: view.leadingAnchor), webView.trailingAnchor.constraint(equalTo: view.trailingAnchor), webView.topAnchor.constraint(equalTo: view.topAnchor), webView.bottomAnchor.constraint(equalTo: view.bottomAnchor), ]) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) navigationController?.hidesBarsOnSwipe = true } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) navigationController?.hidesBarsOnSwipe = false } private func itemContentHTML() -> String? { guard let content = item.content else { return nil } var info = "" if let title = item.title, !title.isEmpty { info += "

" if let url = item.url { info += "" } info += title.htmlEscape() if item.url != nil { info += "" } info += "

" } if let feedTitle = item.feed!.title, !feedTitle.isEmpty { info += "

\(feedTitle.htmlEscape())

" } if let author = item.author, !author.isEmpty { info += "

\(author)

" } if let published = item.published { let formatted = ReadViewController.publishedFormatter.string(from: published) info += "

\(formatted)

" } return """
\(info)
\(content)
""" } } extension ReadViewController: WKNavigationDelegate { func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction) async -> WKNavigationActionPolicy { let url = navigationAction.request.url! if url == Bundle.main.bundleURL { return .allow } return .cancel } }