I need help in capturing a website notification through a WKWebView and then presenting it as a local notification. An example of this would be capturing WhatsApp web notifications and presenting them as native iPad local notifications
WebView Struc
import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {
//Constant for the Food URL
let foodURL: URL?
let contentController = ContentController()
//MARK: - Create the Webview
func makeUIView(context: Context) -> WKWebView {
// Prepare the user script which should be injected into the page context.
let userScriptURL = Bundle.main.url(forResource: "UserScript", withExtension: "js")!
let userScriptCode = try! String(contentsOf: userScriptURL)
let userScript = WKUserScript(source: userScriptCode, injectionTime: .atDocumentStart, forMainFrameOnly: false)
// Create the custom configuration to use for the web view.
let webPreference = WKWebpagePreferences()
webPreference.allowsContentJavaScript = true
let webConfiguration = WKWebViewConfiguration()
webConfiguration.defaultWebpagePreferences = webPreference
webConfiguration.userContentController.addUserScript(self.getZoomDisableScript())
webConfiguration.userContentController.addUserScript(userScript)
webConfiguration.userContentController.add(self, name: "notify")
// Create the web view.
return WKWebView(frame: .zero, configuration: webConfiguration)
}
//MARK: - Update the Webview by loading it
func updateUIView( uiView: WKWebView, context: Context) {
//Guard and assign the superCertURL
guard let superPalFoodURL = self.foodURL else {
return
}
//URL Request
let request = URLRequest(url: superPalFoodURL)
uiView.load(request)
}
//MARK: - Disables Zoom
private func getZoomDisableScript() -> WKUserScript {
let source: String = "var meta = document.createElement('meta');" +
"meta.name = 'viewport';" +
"meta.content = 'width=device-width, initial-scale=1.0, maximum- scale=1.0, user-scalable=no';" +
"var head = document.getElementsByTagName('head')[0];" + "head.appendChild(meta);"
return WKUserScript(source: source, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
}
func userContentController( userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
let content = UNMutableNotificationContent()
content.title = "WKWebView Notification Example"
content.body = message.body as! String
let uuidString = UUID().uuidString
let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: nil)
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.add(request) { (error) in
if error != nil {
NSLog(error.debugDescription)
}
}
}
}
UserScript.JS
class NotificationOverride {
// Grant permission by default to keep this example simple.
// Safari 13 does not support class fields yet, so a static getter must be used.
static get permission() {
return "granted";
}
// Safari 13 still uses callbacks instead of promises.
static requestPermission (callback) {
callback("granted");
}
// Forward the notification text to the native app through the script message handler.
constructor (messageText) {
window.webkit.messageHandlers.notify.postMessage(messageText);
}
}
// Override the global browser notification object.
window.Notification = NotificationOverride;
WebView Struc
import SwiftUI
import WebKit
struct WebView: UIViewRepresentable {
//Constant for the Food URL
let foodURL: URL?
let contentController = ContentController()
//MARK: - Create the Webview
func makeUIView(context: Context) -> WKWebView {
// Prepare the user script which should be injected into the page context.
let userScriptURL = Bundle.main.url(forResource: "UserScript", withExtension: "js")!
let userScriptCode = try! String(contentsOf: userScriptURL)
let userScript = WKUserScript(source: userScriptCode, injectionTime: .atDocumentStart, forMainFrameOnly: false)
// Create the custom configuration to use for the web view.
let webPreference = WKWebpagePreferences()
webPreference.allowsContentJavaScript = true
let webConfiguration = WKWebViewConfiguration()
webConfiguration.defaultWebpagePreferences = webPreference
webConfiguration.userContentController.addUserScript(self.getZoomDisableScript())
webConfiguration.userContentController.addUserScript(userScript)
webConfiguration.userContentController.add(self, name: "notify")
// Create the web view.
return WKWebView(frame: .zero, configuration: webConfiguration)
}
//MARK: - Update the Webview by loading it
func updateUIView( uiView: WKWebView, context: Context) {
//Guard and assign the superCertURL
guard let superPalFoodURL = self.foodURL else {
return
}
//URL Request
let request = URLRequest(url: superPalFoodURL)
uiView.load(request)
}
//MARK: - Disables Zoom
private func getZoomDisableScript() -> WKUserScript {
let source: String = "var meta = document.createElement('meta');" +
"meta.name = 'viewport';" +
"meta.content = 'width=device-width, initial-scale=1.0, maximum- scale=1.0, user-scalable=no';" +
"var head = document.getElementsByTagName('head')[0];" + "head.appendChild(meta);"
return WKUserScript(source: source, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
}
func userContentController( userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
let content = UNMutableNotificationContent()
content.title = "WKWebView Notification Example"
content.body = message.body as! String
let uuidString = UUID().uuidString
let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: nil)
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.add(request) { (error) in
if error != nil {
NSLog(error.debugDescription)
}
}
}
}
UserScript.JS
class NotificationOverride {
// Grant permission by default to keep this example simple.
// Safari 13 does not support class fields yet, so a static getter must be used.
static get permission() {
return "granted";
}
// Safari 13 still uses callbacks instead of promises.
static requestPermission (callback) {
callback("granted");
}
// Forward the notification text to the native app through the script message handler.
constructor (messageText) {
window.webkit.messageHandlers.notify.postMessage(messageText);
}
}
// Override the global browser notification object.
window.Notification = NotificationOverride;