Files
omnivore/apple/OmnivoreKit/Sources/Views/Article/WebAppView.swift
2022-06-21 22:05:39 -07:00

188 lines
6.0 KiB
Swift

import Models
import SwiftUI
import Utils
import WebKit
public let readerViewNavBarHeight = 50.0
enum WebViewConfigurationManager {
private static let processPool = WKProcessPool()
static func create() -> WKWebViewConfiguration {
let config = WKWebViewConfiguration()
config.processPool = processPool
#if os(iOS)
config.allowsInlineMediaPlayback = true
#endif
config.mediaTypesRequiringUserActionForPlayback = .audio
return config
}
}
public enum WebViewManager {
public static let sharedView = create()
public static func shared() -> WebView {
sharedView
}
public static func create() -> WebView {
WebView(frame: CGRect.zero, configuration: WebViewConfigurationManager.create())
}
}
#if os(iOS)
struct WebAppView: UIViewRepresentable {
let request: URLRequest
let baseURL: URL
let rawAuthCookie: String?
let openLinkAction: (URL) -> Void
let webViewActionHandler: (WKScriptMessage) -> Void
let navBarVisibilityRatioUpdater: (Double) -> Void
@Binding var annotation: String
@Binding var annotationSaveTransactionID: UUID?
@Binding var sendIncreaseFontSignal: Bool
@Binding var sendDecreaseFontSignal: Bool
func makeCoordinator() -> WebAppViewCoordinator {
WebAppViewCoordinator()
}
func fontSize() -> Int {
let storedSize = UserDefaults.standard.integer(forKey: "preferredWebFontSize")
return storedSize <= 1 ? UITraitCollection.current.preferredWebFontSize : storedSize
}
func makeUIView(context: Context) -> WKWebView {
let webView = WebViewManager.create()
let contentController = WKUserContentController()
webView.navigationDelegate = context.coordinator
webView.isOpaque = false
webView.backgroundColor = .clear
webView.configuration.userContentController = contentController
webView.scrollView.delegate = context.coordinator
webView.scrollView.contentInset.top = readerViewNavBarHeight
webView.scrollView.verticalScrollIndicatorInsets.top = readerViewNavBarHeight
for action in WebViewAction.allCases {
webView.configuration.userContentController.add(context.coordinator, name: action.rawValue)
}
webView.configuration.userContentController.add(webView, name: "viewerAction")
webView.configureForOmnivoreAppEmbed(
config: WebViewConfig(
url: baseURL,
themeId: UITraitCollection.current.userInterfaceStyle == .dark ? "Gray" : "LightGray",
margin: 0,
fontSize: fontSize(),
fontFamily: "inter",
rawAuthCookie: rawAuthCookie
)
)
context.coordinator.linkHandler = openLinkAction
context.coordinator.webViewActionHandler = webViewActionHandler
context.coordinator.updateNavBarVisibilityRatio = navBarVisibilityRatioUpdater
return webView
}
func updateUIView(_ webView: WKWebView, context: Context) {
if context.coordinator.needsReload {
webView.load(request)
context.coordinator.needsReload = false
}
if annotationSaveTransactionID != context.coordinator.lastSavedAnnotationID {
context.coordinator.lastSavedAnnotationID = annotationSaveTransactionID
(webView as? WebView)?.dispatchEvent(.saveAnnotation(annotation: annotation))
}
if sendIncreaseFontSignal {
sendIncreaseFontSignal = false
(webView as? WebView)?.updateFontSize()
}
if sendDecreaseFontSignal {
sendDecreaseFontSignal = false
(webView as? WebView)?.updateFontSize()
}
}
}
#endif
#if os(macOS)
struct WebAppView: NSViewRepresentable {
let request: URLRequest
let baseURL: URL
let rawAuthCookie: String?
let openLinkAction: (URL) -> Void
let webViewActionHandler: (WKScriptMessage) -> Void
let navBarVisibilityRatioUpdater: (Double) -> Void
@Binding var annotation: String
@Binding var annotationSaveTransactionID: UUID?
@Binding var sendIncreaseFontSignal: Bool
@Binding var sendDecreaseFontSignal: Bool
func makeCoordinator() -> WebAppViewCoordinator {
WebAppViewCoordinator()
}
func fontSize() -> Int {
let storedSize = UserDefaults.standard.integer(forKey: "preferredWebFontSize")
return storedSize <= 1 ? Int(NSFont.userFont(ofSize: 16)?.pointSize ?? 16) : storedSize
}
func makeNSView(context: Context) -> WKWebView {
let contentController = WKUserContentController()
let webView = WebView(frame: CGRect.zero)
webView.navigationDelegate = context.coordinator
webView.configuration.userContentController = contentController
webView.setValue(false, forKey: "drawsBackground")
for action in WebViewAction.allCases {
webView.configuration.userContentController.add(context.coordinator, name: action.rawValue)
}
webView.configureForOmnivoreAppEmbed(
config: WebViewConfig(
url: baseURL,
themeId: NSApp.effectiveAppearance.name == NSAppearance.Name.darkAqua ? "Gray" : "LightGray",
margin: 0,
fontSize: fontSize(),
fontFamily: "inter",
rawAuthCookie: rawAuthCookie
)
)
context.coordinator.linkHandler = openLinkAction
context.coordinator.webViewActionHandler = webViewActionHandler
return webView
}
func updateNSView(_ webView: WKWebView, context: Context) {
if context.coordinator.needsReload {
webView.load(request)
context.coordinator.needsReload = false
}
if annotationSaveTransactionID != context.coordinator.lastSavedAnnotationID {
context.coordinator.lastSavedAnnotationID = annotationSaveTransactionID
(webView as? WebView)?.dispatchEvent(.saveAnnotation(annotation: annotation))
}
if sendIncreaseFontSignal {
sendIncreaseFontSignal = false
(webView as? WebView)?.updateFontSize()
}
if sendDecreaseFontSignal {
sendDecreaseFontSignal = false
(webView as? WebView)?.updateFontSize()
}
}
}
#endif