feat: use custom jsbridge, remove WebViewJavascriptBridge for xcode 15 issue

This commit is contained in:
yicheng 2023-09-26 11:11:37 +08:00
parent 6a2b7274de
commit 1528477fb1
6 changed files with 104 additions and 41 deletions

View File

@ -14,6 +14,7 @@
4905A2C82A2058D400AEDA2E /* KeyboardShortcuts in Frameworks */ = {isa = PBXBuildFile; productRef = 4905A2C72A2058D400AEDA2E /* KeyboardShortcuts */; };
4905A2CA2A20841B00AEDA2E /* NSView+Layout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4905A2C92A20841B00AEDA2E /* NSView+Layout.swift */; };
4908087B29F8F405007A4944 /* libresolv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 4908087A29F8F3FF007A4944 /* libresolv.tbd */; };
490C8A102AC26E67007140F2 /* JSBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 490C8A0F2AC26E67007140F2 /* JSBridge.swift */; };
4913C82321157D0200F6B87C /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4913C82221157D0200F6B87C /* Notification.swift */; };
491E6203258A424D00313AEF /* CommonUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 491E61FD258A424500313AEF /* CommonUtils.m */; };
49228457270AADE20027A4B6 /* RemoteConfigUpdateIntervalSettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49228456270AADE20027A4B6 /* RemoteConfigUpdateIntervalSettingView.swift */; };
@ -170,6 +171,7 @@
4905A2C42A2058B000AEDA2E /* GlobalShortCutViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalShortCutViewController.swift; sourceTree = "<group>"; };
4905A2C92A20841B00AEDA2E /* NSView+Layout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSView+Layout.swift"; sourceTree = "<group>"; };
4908087A29F8F3FF007A4944 /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; };
490C8A0F2AC26E67007140F2 /* JSBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSBridge.swift; sourceTree = "<group>"; };
4913C82221157D0200F6B87C /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = "<group>"; };
491E61FC258A424500313AEF /* CommonUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonUtils.h; sourceTree = "<group>"; };
491E61FD258A424500313AEF /* CommonUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CommonUtils.m; sourceTree = "<group>"; };
@ -359,6 +361,7 @@
isa = PBXGroup;
children = (
4960A6DA2136529200B940C9 /* JSBridgeHandler.swift */,
490C8A0F2AC26E67007140F2 /* JSBridge.swift */,
493AEAE2221AE3420016FE98 /* AppVersionUtil.swift */,
49D176A62355FE680093DD7B /* NetworkChangeNotifier.swift */,
49B445152457CDF000B27E3E /* ClashStatusTool.swift */,
@ -927,6 +930,7 @@
F935B2FC23085515009E4D33 /* SystemProxyManager.swift in Sources */,
0AD7506D2A5B9B26001FFBBD /* ConnectionLeftTextCellView.swift in Sources */,
495A44D320D267D000888A0A /* LaunchAtLogin.swift in Sources */,
490C8A102AC26E67007140F2 /* JSBridge.swift in Sources */,
4991D2322A565E6A00978143 /* Combine+Ext.swift in Sources */,
49281C802A1F01FA00F60935 /* DebugSettingViewController.swift in Sources */,
49D767762A6195E600830333 /* StructedLogReq.swift in Sources */,

View File

@ -0,0 +1,81 @@
//
// JSBridge.swift
// ClashX
//
// Created by yicheng on 2023/9/26.
// Copyright © 2023 west2online. All rights reserved.
//
import Foundation
import WebKit
class JSBridge: NSObject {
typealias ResponseCallback = (Any?) -> Void
typealias BridgeHandler = (Any?, @escaping ResponseCallback) -> Void
private weak var webView: WKWebView?
private var handlers = [String: BridgeHandler]()
init(_ webView: WKWebView) {
self.webView = webView
super.init()
setup()
}
deinit {
webView?.configuration.userContentController.removeAllUserScripts()
webView?.configuration.userContentController.removeScriptMessageHandler(forName: "jsBridge")
}
private func setup() {
addScriptMessageHandler()
}
private func addScriptMessageHandler() {
let scriptMessageHandler = ClashScriptMessageHandler(delegate: self)
webView?.configuration.userContentController.add(scriptMessageHandler, name: "jsBridge")
}
private func sendBackMessage(data: Any?, eventID: String) {
let data = ["id": eventID, "data": data, "type": "jsBridge"] as [String: Any?]
do {
let jsonData = try JSONSerialization.data(withJSONObject: data, options: [])
let jsonString = String(data: jsonData, encoding: .utf8)!
let str = "window.postMessage(\(jsonString), window.origin);"
webView?.evaluateJavaScript(str)
} catch let err {
Logger.log(err.localizedDescription, level: .warning)
}
}
func registerHandler(_ name: String, handler: @escaping BridgeHandler) {
handlers[name] = handler
}
}
extension JSBridge: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if
let body = message.body as? [String: Any],
let handlerName = body["name"] as? String,
let handler = handlers[handlerName],
let eventID = body["id"] as? String {
let data = body["data"]
handler(data) { [weak self] res in
self?.sendBackMessage(data: res, eventID: eventID)
}
}
}
}
private class ClashScriptMessageHandler: NSObject, WKScriptMessageHandler {
weak var delegate: WKScriptMessageHandler?
public init(delegate: WKScriptMessageHandler) {
self.delegate = delegate
super.init()
}
public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
delegate?.userContentController(userContentController, didReceive: message)
}
}

View File

@ -8,16 +8,14 @@
import Alamofire
import SwiftyJSON
import WebViewJavascriptBridge
import WebKit
class JsBridgeUtil {
static func initJSbridge(webview: Any, delegate: Any) -> WebViewJavascriptBridge {
let bridge = WebViewJavascriptBridge(webview)!
bridge.setWebViewDelegate(delegate)
static func initJSbridge(webview: WKWebView, delegate: Any) -> JSBridge {
let bridge = JSBridge(webview)
bridge.registerHandler("isSystemProxySet") { _, responseCallback in
responseCallback?(ConfigManager.shared.proxyPortAutoSet)
responseCallback(ConfigManager.shared.proxyPortAutoSet)
}
bridge.registerHandler("setSystemProxy") { anydata, responseCallback in
@ -29,22 +27,22 @@ class JsBridgeUtil {
} else {
SystemProxyManager.shared.disableProxy()
}
responseCallback?(true)
responseCallback(true)
} else {
responseCallback?(false)
responseCallback(false)
}
}
bridge.registerHandler("getStartAtLogin") { _, responseCallback in
responseCallback?(LaunchAtLogin.shared.isEnabled)
responseCallback(LaunchAtLogin.shared.isEnabled)
}
bridge.registerHandler("setStartAtLogin") { anydata, responseCallback in
if let enable = anydata as? Bool {
LaunchAtLogin.shared.isEnabled = enable
responseCallback?(true)
responseCallback(true)
} else {
responseCallback?(false)
responseCallback(false)
}
}
@ -57,10 +55,10 @@ class JsBridgeUtil {
} else {
resp = delay
}
responseCallback?(resp)
responseCallback(resp)
}
} else {
responseCallback?(nil)
responseCallback(nil)
}
}
@ -77,13 +75,12 @@ class JsBridgeUtil {
"port": port,
"secret": ConfigManager.shared.overrideSecret ?? ConfigManager.shared.apiSecret
]
callback?(data)
callback(data)
}
// ping-pong
bridge.registerHandler("ping") { [weak bridge] _, responseCallback in
bridge?.callHandler("pong")
responseCallback?(true)
bridge.registerHandler("ping") { _, responseCallback in
responseCallback("pong")
}
return bridge
}

View File

@ -10,7 +10,6 @@ import Cocoa
import RxCocoa
import RxSwift
import WebKit
import WebViewJavascriptBridge
enum WebCacheCleaner {
static func clean() {
@ -27,7 +26,7 @@ enum WebCacheCleaner {
class ClashWebViewContoller: NSViewController {
let webview: CustomWKWebView = .init()
var bridge: WebViewJavascriptBridge?
var bridge: JSBridge?
let disposeBag = DisposeBag()
let minSize = NSSize(width: 920, height: 580)
@ -53,15 +52,9 @@ class ClashWebViewContoller: NSViewController {
webview.configuration.userContentController.addUserScript(script)
bridge = JsBridgeUtil.initJSbridge(webview: webview, delegate: self)
registerExtenalJSBridgeFunction()
webview.configuration.preferences.setValue(true, forKey: "developerExtrasEnabled")
NotificationCenter.default.rx.notification(.configFileChange).bind {
[weak self] _ in
self?.bridge?.callHandler("onConfigChange")
}.disposed(by: disposeBag)
NotificationCenter.default.rx.notification(.reloadDashboard).bind {
[weak self] _ in
self?.webview.reload()
@ -113,17 +106,10 @@ class ClashWebViewContoller: NSViewController {
}
Logger.log("load dashboard url fail", level: .error)
}
}
extension ClashWebViewContoller {
func registerExtenalJSBridgeFunction() {
bridge?.registerHandler("setDragAreaHeight") {
[weak self] anydata, responseCallback in
if let height = anydata as? CGFloat {
self?.webview.dragableAreaHeight = height
}
responseCallback?(nil)
}
func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
NSAlert.alert(with: message)
completionHandler()
}
}

View File

@ -24,7 +24,6 @@ target 'ClashX' do
pod 'RxSwift'
pod 'RxCocoa'
pod 'CocoaLumberjack/Swift'
pod 'WebViewJavascriptBridge'
pod 'Starscream','3.1.1'
pod 'AppCenter/Analytics'
pod 'AppCenter/Crashes'

View File

@ -22,7 +22,6 @@ PODS:
- SwiftFormat/CLI (0.52.3)
- SwiftLint (0.52.4)
- SwiftyJSON (5.0.1)
- WebViewJavascriptBridge (6.0.3)
DEPENDENCIES:
- Alamofire (~> 5.0)
@ -39,7 +38,6 @@ DEPENDENCIES:
- SwiftFormat/CLI (~> 0.49)
- SwiftLint
- SwiftyJSON
- WebViewJavascriptBridge
SPEC REPOS:
trunk:
@ -57,7 +55,6 @@ SPEC REPOS:
- SwiftFormat
- SwiftLint
- SwiftyJSON
- WebViewJavascriptBridge
SPEC CHECKSUMS:
Alamofire: 0e92e751b3e9e66d7982db43919d01f313b8eb91
@ -74,8 +71,7 @@ SPEC CHECKSUMS:
SwiftFormat: 5de81c42f043741a16e17ae2da012bbddc7c0b58
SwiftLint: 1cc5cd61ba9bacb2194e340aeb47a2a37fda00b3
SwiftyJSON: 2f33a42c6fbc52764d96f13368585094bfd8aa5e
WebViewJavascriptBridge: 7f5bc4d3581e672e8f32bd0f812d54bc69bb8e29
PODFILE CHECKSUM: d3e952c889c7931151a654c076812b3b3294aa59
PODFILE CHECKSUM: f3a6ebd40f44d7184ef9437d24b1979389395820
COCOAPODS: 1.12.1