Преглед изворни кода

initial partly draft for js-swift bridge

cyberta пре 3 година
родитељ
комит
84f6da9344
1 измењених фајлова са 73 додато и 4 уклоњено
  1. 73 4
      deltachat-ios/Controller/WebxdcViewController.swift

+ 73 - 4
deltachat-ios/Controller/WebxdcViewController.swift

@@ -4,6 +4,10 @@ import DcCore
 
 class WebxdcViewController: WebViewViewController {
 
+    enum WebxdcHandler: String {
+        case getStatusUpdates = "getStatusUpdatesHandler"
+        case sendStatusUpdate = "sendStatusUpdateHandler"
+    }
     let INTERNALSCHEMA = "webxdc"
     let INTERNALDOMAIN = "local.app"
 
@@ -25,11 +29,57 @@ class WebxdcViewController: WebViewViewController {
     ]
     """
 
+    lazy var webxdcbridge: String = {
+        let script = """
+        window.webxdc = (() => {
+          var update_listener = () => {};
+
+          // instead of calling .getStatusUpdatesHandler (-> async),
+          // we're passing the updates directly to this js function
+          window.__webxdcUpdateiOS = (updateString) => {
+            var updates = JSON.parse(updateString);
+            if (updates.length === 1) {
+              update_listener(updates[0]);
+            }
+          };
+
+          return {
+            selfAddr: \(dcContext.addr ?? "unknown"),
+
+            selfName: \(dcContext.displayname ?? "unknown"),
+
+            setUpdateListener: (cb) => (update_listener = cb),
+
+            async getAllUpdates: () => {
+              // FIXME: we need to add an callback here, comp. https://programming.vip/docs/the-perfect-solution-for-wkwebview-to-interact-with-js.html
+              return  JSON.parse(webkit.messageHandlers.getStatusUpdatesHandler.postMessage(0));
+            },
+
+            sendUpdate: (payload, descr) => {
+                // only one parameter is allowed, we we create a new parameter object here
+                var parameter = {
+                    payload: payload,
+                    desc: desc
+                };
+                webkit.messageHandlers.sendStatusUpdateHandler.postMessage(JSON.stringify(parameter));
+            },
+          };
+        })();
+        """
+        return script
+    }()
+
     override var configuration: WKWebViewConfiguration {
-        let preferences = WKPreferences()
         let config = WKWebViewConfiguration()
+        let preferences = WKPreferences()
+        let contentController = WKUserContentController()
 
-        config.userContentController.add(self, name: "webxdcHandler")
+        contentController.add(self, name: WebxdcHandler.sendStatusUpdate.rawValue)
+        contentController.add(self, name: WebxdcHandler.getStatusUpdates.rawValue)
+        let bridgeScript = WKUserScript(source: webxdcbridge, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
+        contentController.addUserScript(bridgeScript)
+
+        config.userContentController = contentController
         config.setURLSchemeHandler(self, forURLScheme: INTERNALSCHEMA)
 
         if #available(iOS 13.0, *) {
@@ -70,7 +120,8 @@ class WebxdcViewController: WebViewViewController {
             url.scheme != INTERNALSCHEMA {
             logger.debug("cancel loading: \(url)")
             decisionHandler(.cancel)
-            return }
+            return
+        }
         logger.debug("loading: \(String(describing: navigationAction.request.url))")
         decisionHandler(.allow)
     }
@@ -119,6 +170,22 @@ class WebxdcViewController: WebViewViewController {
 
 extension WebxdcViewController: WKScriptMessageHandler {
     func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
+        let handler = WebxdcHandler(rawValue: message.name)
+        switch handler {
+        case .getStatusUpdates:
+            logger.debug("getStatusUpdates called")
+            guard let param = message.body as? Int else {
+                logger.error("could not convert param \(message.body) to int")
+                return
+            }
+            // let statusUpdates = dcContext.getWebxdcStatusUpdates(msgId: messageId, statusUpdateId: param)
+            // TODO: return
+        case .sendStatusUpdate:
+            logger.debug("sendStatusUpdate called")
+            // dcContext.sendWebxdcStatusUpdate(msgId: messageId, payload: <#T##String#>, description: <#T##String#>)
+        default:
+            logger.debug("another method was called")
+        }
     }
 }
 
@@ -136,11 +203,13 @@ extension WebxdcViewController: WKURLSchemeHandler {
                 logger.debug(String(bytes: data, encoding: String.Encoding.utf8) ?? "invalid string")
             }
 
-            let response = URLResponse.init(url: url, mimeType: mimeType, expectedContentLength: data.count, textEncodingName: nil)
+            let response = URLResponse(url: url, mimeType: mimeType, expectedContentLength: data.count, textEncodingName: nil)
 
             urlSchemeTask.didReceive(response)
             urlSchemeTask.didReceive(data)
             urlSchemeTask.didFinish()
+        } else {
+            logger.debug("not loading \(String(describing: urlSchemeTask.request.url))")
         }
     }