From 4333021406d43c9407575787e9edc8f47ca2cf5f Mon Sep 17 00:00:00 2001 From: Andrew Balmer Date: Fri, 24 Jan 2025 18:29:17 -0500 Subject: [PATCH 1/5] updated protocol --- .../KlaviyoUI/KlaviyoWebView/KlaviyoWebViewModeling.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Sources/KlaviyoUI/KlaviyoWebView/KlaviyoWebViewModeling.swift b/Sources/KlaviyoUI/KlaviyoWebView/KlaviyoWebViewModeling.swift index 3b136dc8..ef024991 100644 --- a/Sources/KlaviyoUI/KlaviyoWebView/KlaviyoWebViewModeling.swift +++ b/Sources/KlaviyoUI/KlaviyoWebView/KlaviyoWebViewModeling.swift @@ -14,8 +14,10 @@ public protocol KlaviyoWebViewModeling: AnyObject { var url: URL { get } var delegate: KlaviyoWebViewDelegate? { get set } - /// Scripts to be injected into the ``WKWebView`` when the website loads. - var loadScripts: [String: WKUserScript]? { get } + /// Scripts & message handlers to be injected into the ``WKWebView`` when the website loads. + var loadScripts: Set? { get } + var messageHandlers: Set? { get } + var navEventStream: AsyncStream { get } var navEventContinuation: AsyncStream.Continuation { get } From 4d1388c596e8f6cee897626271f86e44565f6c04 Mon Sep 17 00:00:00 2001 From: Andrew Balmer Date: Fri, 24 Jan 2025 18:32:18 -0500 Subject: [PATCH 2/5] updated KlaviyoWebViewModel --- .../KlaviyoWebView/KlaviyoWebViewModel.swift | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/Sources/KlaviyoUI/KlaviyoWebView/KlaviyoWebViewModel.swift b/Sources/KlaviyoUI/KlaviyoWebView/KlaviyoWebViewModel.swift index dd0df728..3b07d00a 100644 --- a/Sources/KlaviyoUI/KlaviyoWebView/KlaviyoWebViewModel.swift +++ b/Sources/KlaviyoUI/KlaviyoWebView/KlaviyoWebViewModel.swift @@ -23,23 +23,29 @@ public protocol KlaviyoWebViewDelegate: AnyObject { @_spi(KlaviyoPrivate) public class KlaviyoWebViewModel: KlaviyoWebViewModeling { - public let url: URL - public let loadScripts: [String: WKUserScript]? + private enum MessageHandler: String, CaseIterable { + case closeHandler + } + public weak var delegate: KlaviyoWebViewDelegate? + public let url: URL + public let loadScripts: Set? = KlaviyoWebViewModel.initializeLoadScripts() + public var messageHandlers: Set? = Set(MessageHandler.allCases.map(\.rawValue)) + public let (navEventStream, navEventContinuation) = AsyncStream.makeStream(of: WKNavigationEvent.self) public init(url: URL) { self.url = url - loadScripts = KlaviyoWebViewModel.initializeLoadScripts() +// loadScripts = KlaviyoWebViewModel.initializeLoadScripts() } - private static func initializeLoadScripts() -> [String: WKUserScript] { - var scripts: [String: WKUserScript] = [:] + private static func initializeLoadScripts() -> Set { + var scripts = Set() if let closeHandlerScript = try? ResourceLoader.getResourceContents(path: "closeHandler", type: "js") { let script = WKUserScript(source: closeHandlerScript, injectionTime: .atDocumentEnd, forMainFrameOnly: true) - scripts["closeHandler"] = script + scripts.insert(script) } return scripts @@ -48,10 +54,13 @@ public class KlaviyoWebViewModel: KlaviyoWebViewModeling { // MARK: handle WKWebView events public func handleScriptMessage(_ message: WKScriptMessage) { - if message.name == "closeHandler" { - // TODO: handle close button tap - print("user tapped close button") + guard let handler = MessageHandler(rawValue: message.name) else { + // script message has no handler + return + } + switch handler { + case .closeHandler: Task { await delegate?.dismiss() } From 1ede1112fac05342b82641193503f6b540a6c1b0 Mon Sep 17 00:00:00 2001 From: Andrew Balmer Date: Fri, 24 Jan 2025 18:39:15 -0500 Subject: [PATCH 3/5] updated JSTestWebViewModel --- .../JSTestWebViewModel.swift | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/Sources/KlaviyoUI/KlaviyoWebView/Development Assets/JSTestWebViewModel.swift b/Sources/KlaviyoUI/KlaviyoWebView/Development Assets/JSTestWebViewModel.swift index 13691b4e..7d710ca2 100644 --- a/Sources/KlaviyoUI/KlaviyoWebView/Development Assets/JSTestWebViewModel.swift +++ b/Sources/KlaviyoUI/KlaviyoWebView/Development Assets/JSTestWebViewModel.swift @@ -11,23 +11,34 @@ import Foundation import WebKit class JSTestWebViewModel: KlaviyoWebViewModeling { - let url: URL - let loadScripts: [String: WKUserScript]? + public enum MessageHandler: String, CaseIterable { + case toggleMessageHandler + case closeHandler + } + weak var delegate: KlaviyoWebViewDelegate? + let url: URL + var loadScripts: Set? = JSTestWebViewModel.initializeLoadScripts() + var messageHandlers: Set? = Set(MessageHandler.allCases.map(\.rawValue)) + public let (navEventStream, navEventContinuation) = AsyncStream.makeStream(of: WKNavigationEvent.self) init(url: URL) { self.url = url - loadScripts = JSTestWebViewModel.initializeLoadScripts() } - private static func initializeLoadScripts() -> [String: WKUserScript] { - var scripts: [String: WKUserScript] = [:] + private static func initializeLoadScripts() -> Set { + var scripts = Set() if let toggleHandlerScript = try? ResourceLoader.getResourceContents(path: "toggleHandler", type: "js") { let script = WKUserScript(source: toggleHandlerScript, injectionTime: .atDocumentEnd, forMainFrameOnly: true) - scripts["toggleMessageHandler"] = script + scripts.insert(script) + } + + if let closeHandlerScript = try? ResourceLoader.getResourceContents(path: "closeHandler", type: "js") { + let script = WKUserScript(source: closeHandlerScript, injectionTime: .atDocumentEnd, forMainFrameOnly: true) + scripts.insert(script) } return scripts @@ -36,7 +47,13 @@ class JSTestWebViewModel: KlaviyoWebViewModeling { // MARK: handle WKWebView events func handleScriptMessage(_ message: WKScriptMessage) { - if message.name == "toggleMessageHandler" { + guard let handler = MessageHandler(rawValue: message.name) else { + // script message has no handler + return + } + + switch handler { + case .toggleMessageHandler: guard let dict = message.body as? [String: AnyObject] else { return } @@ -61,6 +78,10 @@ class JSTestWebViewModel: KlaviyoWebViewModeling { print("Javascript evaluation failed; message: \(error.localizedDescription)") } } + case .closeHandler: + Task { + await delegate?.dismiss() + } } } } From 2bbadb335750e2a54aeafcdcc95b6e649f425dc0 Mon Sep 17 00:00:00 2001 From: Andrew Balmer Date: Fri, 24 Jan 2025 18:46:12 -0500 Subject: [PATCH 4/5] updated ViewController --- .../KlaviyoWebView/KlaviyoWebViewController.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Sources/KlaviyoUI/KlaviyoWebView/KlaviyoWebViewController.swift b/Sources/KlaviyoUI/KlaviyoWebView/KlaviyoWebViewController.swift index 7dd5a6d2..68457d1e 100644 --- a/Sources/KlaviyoUI/KlaviyoWebView/KlaviyoWebViewController.swift +++ b/Sources/KlaviyoUI/KlaviyoWebView/KlaviyoWebViewController.swift @@ -63,9 +63,8 @@ class KlaviyoWebViewController: UIViewController, WKUIDelegate, KlaviyoWebViewDe override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) - let scriptNames = viewModel.loadScripts?.keys.compactMap { $0 } ?? [] - for scriptName in scriptNames { - webView.configuration.userContentController.removeScriptMessageHandler(forName: scriptName) + viewModel.messageHandlers?.forEach { + webView.configuration.userContentController.removeScriptMessageHandler(forName: $0) } } @@ -90,11 +89,12 @@ class KlaviyoWebViewController: UIViewController, WKUIDelegate, KlaviyoWebViewDe /// Configures the scripts to be injected into the website when the website loads. private func configureLoadScripts() { - guard let scriptsDict = viewModel.loadScripts else { return } + viewModel.loadScripts?.forEach { + webView.configuration.userContentController.addUserScript($0) + } - for (name, script) in scriptsDict { - webView.configuration.userContentController.addUserScript(script) - webView.configuration.userContentController.add(self, name: name) + viewModel.messageHandlers?.forEach { + webView.configuration.userContentController.add(self, name: $0) } } From c73c3721ba29e47479d1438c832a2a3d55a72365 Mon Sep 17 00:00:00 2001 From: Andrew Balmer Date: Fri, 24 Jan 2025 19:02:27 -0500 Subject: [PATCH 5/5] updated JSTestWebViewModel --- .../Development Assets/JSTestWebViewModel.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/KlaviyoUI/KlaviyoWebView/Development Assets/JSTestWebViewModel.swift b/Sources/KlaviyoUI/KlaviyoWebView/Development Assets/JSTestWebViewModel.swift index 7d710ca2..55f18993 100644 --- a/Sources/KlaviyoUI/KlaviyoWebView/Development Assets/JSTestWebViewModel.swift +++ b/Sources/KlaviyoUI/KlaviyoWebView/Development Assets/JSTestWebViewModel.swift @@ -11,9 +11,9 @@ import Foundation import WebKit class JSTestWebViewModel: KlaviyoWebViewModeling { - public enum MessageHandler: String, CaseIterable { + private enum MessageHandler: String, CaseIterable { case toggleMessageHandler - case closeHandler + case closeMessageHandler } weak var delegate: KlaviyoWebViewDelegate? @@ -78,7 +78,7 @@ class JSTestWebViewModel: KlaviyoWebViewModeling { print("Javascript evaluation failed; message: \(error.localizedDescription)") } } - case .closeHandler: + case .closeMessageHandler: Task { await delegate?.dismiss() }