|
|
@@ -5,10 +5,15 @@ import WebKit
|
|
|
struct RedditWebView: NSViewRepresentable {
|
|
|
let url: URL
|
|
|
let reloadTrigger: Int
|
|
|
+ var goBackTrigger: Int = 0
|
|
|
+ var onCanGoBackChange: (Bool) -> Void = { _ in }
|
|
|
var onAuthError: (String) -> Void = { _ in }
|
|
|
|
|
|
func makeCoordinator() -> Coordinator {
|
|
|
- Coordinator(onAuthError: onAuthError)
|
|
|
+ Coordinator(
|
|
|
+ onCanGoBackChange: onCanGoBackChange,
|
|
|
+ onAuthError: onAuthError
|
|
|
+ )
|
|
|
}
|
|
|
|
|
|
func makeNSView(context: Context) -> RedditWebViewContainer {
|
|
|
@@ -17,11 +22,21 @@ struct RedditWebView: NSViewRepresentable {
|
|
|
container.webView.uiDelegate = context.coordinator
|
|
|
context.coordinator.container = container
|
|
|
context.coordinator.lastReloadTrigger = reloadTrigger
|
|
|
+ context.coordinator.startObservingNavigation(in: container.webView)
|
|
|
container.load(url: url)
|
|
|
return container
|
|
|
}
|
|
|
|
|
|
func updateNSView(_ container: RedditWebViewContainer, context: Context) {
|
|
|
+ context.coordinator.onCanGoBackChange = onCanGoBackChange
|
|
|
+
|
|
|
+ if context.coordinator.lastGoBackTrigger != goBackTrigger {
|
|
|
+ context.coordinator.lastGoBackTrigger = goBackTrigger
|
|
|
+ if container.webView.canGoBack {
|
|
|
+ container.webView.goBack()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
let urlChanged = context.coordinator.lastLoadedURL != url
|
|
|
let triggerChanged = context.coordinator.lastReloadTrigger != reloadTrigger
|
|
|
guard urlChanged || triggerChanged else { return }
|
|
|
@@ -34,15 +49,33 @@ struct RedditWebView: NSViewRepresentable {
|
|
|
final class Coordinator: NSObject, WKNavigationDelegate, WKUIDelegate {
|
|
|
weak var container: RedditWebViewContainer?
|
|
|
var lastReloadTrigger = -1
|
|
|
+ var lastGoBackTrigger = 0
|
|
|
var lastLoadedURL: URL?
|
|
|
private var prefillWorkItem: DispatchWorkItem?
|
|
|
+ private var canGoBackObservation: NSKeyValueObservation?
|
|
|
+ var onCanGoBackChange: (Bool) -> Void
|
|
|
private let onAuthError: (String) -> Void
|
|
|
|
|
|
- init(onAuthError: @escaping (String) -> Void) {
|
|
|
+ init(
|
|
|
+ onCanGoBackChange: @escaping (Bool) -> Void,
|
|
|
+ onAuthError: @escaping (String) -> Void
|
|
|
+ ) {
|
|
|
+ self.onCanGoBackChange = onCanGoBackChange
|
|
|
self.onAuthError = onAuthError
|
|
|
}
|
|
|
|
|
|
+ func startObservingNavigation(in webView: WKWebView) {
|
|
|
+ guard canGoBackObservation == nil else { return }
|
|
|
+
|
|
|
+ canGoBackObservation = webView.observe(\.canGoBack, options: [.initial, .new]) { [weak self] webView, _ in
|
|
|
+ DispatchQueue.main.async {
|
|
|
+ self?.onCanGoBackChange(webView.canGoBack)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
|
|
+ startObservingNavigation(in: webView)
|
|
|
webView.evaluateJavaScript(RedditPostBoundaryStyle.injectionScript, completionHandler: nil)
|
|
|
webView.evaluateJavaScript(RedditHomeChromeStyle.injectionScript, completionHandler: nil)
|
|
|
webView.evaluateJavaScript(RedditAuthChromeStyle.injectionScript, completionHandler: nil)
|