feat: use custom jsbridge, remove WebViewJavascriptBridge for xcode 15 issue
This commit is contained in:
parent
6a2b7274de
commit
1528477fb1
@ -14,6 +14,7 @@
|
|||||||
4905A2C82A2058D400AEDA2E /* KeyboardShortcuts in Frameworks */ = {isa = PBXBuildFile; productRef = 4905A2C72A2058D400AEDA2E /* KeyboardShortcuts */; };
|
4905A2C82A2058D400AEDA2E /* KeyboardShortcuts in Frameworks */ = {isa = PBXBuildFile; productRef = 4905A2C72A2058D400AEDA2E /* KeyboardShortcuts */; };
|
||||||
4905A2CA2A20841B00AEDA2E /* NSView+Layout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4905A2C92A20841B00AEDA2E /* NSView+Layout.swift */; };
|
4905A2CA2A20841B00AEDA2E /* NSView+Layout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4905A2C92A20841B00AEDA2E /* NSView+Layout.swift */; };
|
||||||
4908087B29F8F405007A4944 /* libresolv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 4908087A29F8F3FF007A4944 /* libresolv.tbd */; };
|
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 */; };
|
4913C82321157D0200F6B87C /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4913C82221157D0200F6B87C /* Notification.swift */; };
|
||||||
491E6203258A424D00313AEF /* CommonUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 491E61FD258A424500313AEF /* CommonUtils.m */; };
|
491E6203258A424D00313AEF /* CommonUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 491E61FD258A424500313AEF /* CommonUtils.m */; };
|
||||||
49228457270AADE20027A4B6 /* RemoteConfigUpdateIntervalSettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49228456270AADE20027A4B6 /* RemoteConfigUpdateIntervalSettingView.swift */; };
|
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>"; };
|
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>"; };
|
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; };
|
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>"; };
|
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>"; };
|
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>"; };
|
491E61FD258A424500313AEF /* CommonUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CommonUtils.m; sourceTree = "<group>"; };
|
||||||
@ -359,6 +361,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
4960A6DA2136529200B940C9 /* JSBridgeHandler.swift */,
|
4960A6DA2136529200B940C9 /* JSBridgeHandler.swift */,
|
||||||
|
490C8A0F2AC26E67007140F2 /* JSBridge.swift */,
|
||||||
493AEAE2221AE3420016FE98 /* AppVersionUtil.swift */,
|
493AEAE2221AE3420016FE98 /* AppVersionUtil.swift */,
|
||||||
49D176A62355FE680093DD7B /* NetworkChangeNotifier.swift */,
|
49D176A62355FE680093DD7B /* NetworkChangeNotifier.swift */,
|
||||||
49B445152457CDF000B27E3E /* ClashStatusTool.swift */,
|
49B445152457CDF000B27E3E /* ClashStatusTool.swift */,
|
||||||
@ -927,6 +930,7 @@
|
|||||||
F935B2FC23085515009E4D33 /* SystemProxyManager.swift in Sources */,
|
F935B2FC23085515009E4D33 /* SystemProxyManager.swift in Sources */,
|
||||||
0AD7506D2A5B9B26001FFBBD /* ConnectionLeftTextCellView.swift in Sources */,
|
0AD7506D2A5B9B26001FFBBD /* ConnectionLeftTextCellView.swift in Sources */,
|
||||||
495A44D320D267D000888A0A /* LaunchAtLogin.swift in Sources */,
|
495A44D320D267D000888A0A /* LaunchAtLogin.swift in Sources */,
|
||||||
|
490C8A102AC26E67007140F2 /* JSBridge.swift in Sources */,
|
||||||
4991D2322A565E6A00978143 /* Combine+Ext.swift in Sources */,
|
4991D2322A565E6A00978143 /* Combine+Ext.swift in Sources */,
|
||||||
49281C802A1F01FA00F60935 /* DebugSettingViewController.swift in Sources */,
|
49281C802A1F01FA00F60935 /* DebugSettingViewController.swift in Sources */,
|
||||||
49D767762A6195E600830333 /* StructedLogReq.swift in Sources */,
|
49D767762A6195E600830333 /* StructedLogReq.swift in Sources */,
|
||||||
|
81
ClashX/General/Utils/JSBridge.swift
Normal file
81
ClashX/General/Utils/JSBridge.swift
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
@ -8,16 +8,14 @@
|
|||||||
|
|
||||||
import Alamofire
|
import Alamofire
|
||||||
import SwiftyJSON
|
import SwiftyJSON
|
||||||
import WebViewJavascriptBridge
|
import WebKit
|
||||||
|
|
||||||
class JsBridgeUtil {
|
class JsBridgeUtil {
|
||||||
static func initJSbridge(webview: Any, delegate: Any) -> WebViewJavascriptBridge {
|
static func initJSbridge(webview: WKWebView, delegate: Any) -> JSBridge {
|
||||||
let bridge = WebViewJavascriptBridge(webview)!
|
let bridge = JSBridge(webview)
|
||||||
|
|
||||||
bridge.setWebViewDelegate(delegate)
|
|
||||||
|
|
||||||
bridge.registerHandler("isSystemProxySet") { _, responseCallback in
|
bridge.registerHandler("isSystemProxySet") { _, responseCallback in
|
||||||
responseCallback?(ConfigManager.shared.proxyPortAutoSet)
|
responseCallback(ConfigManager.shared.proxyPortAutoSet)
|
||||||
}
|
}
|
||||||
|
|
||||||
bridge.registerHandler("setSystemProxy") { anydata, responseCallback in
|
bridge.registerHandler("setSystemProxy") { anydata, responseCallback in
|
||||||
@ -29,22 +27,22 @@ class JsBridgeUtil {
|
|||||||
} else {
|
} else {
|
||||||
SystemProxyManager.shared.disableProxy()
|
SystemProxyManager.shared.disableProxy()
|
||||||
}
|
}
|
||||||
responseCallback?(true)
|
responseCallback(true)
|
||||||
} else {
|
} else {
|
||||||
responseCallback?(false)
|
responseCallback(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bridge.registerHandler("getStartAtLogin") { _, responseCallback in
|
bridge.registerHandler("getStartAtLogin") { _, responseCallback in
|
||||||
responseCallback?(LaunchAtLogin.shared.isEnabled)
|
responseCallback(LaunchAtLogin.shared.isEnabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
bridge.registerHandler("setStartAtLogin") { anydata, responseCallback in
|
bridge.registerHandler("setStartAtLogin") { anydata, responseCallback in
|
||||||
if let enable = anydata as? Bool {
|
if let enable = anydata as? Bool {
|
||||||
LaunchAtLogin.shared.isEnabled = enable
|
LaunchAtLogin.shared.isEnabled = enable
|
||||||
responseCallback?(true)
|
responseCallback(true)
|
||||||
} else {
|
} else {
|
||||||
responseCallback?(false)
|
responseCallback(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,10 +55,10 @@ class JsBridgeUtil {
|
|||||||
} else {
|
} else {
|
||||||
resp = delay
|
resp = delay
|
||||||
}
|
}
|
||||||
responseCallback?(resp)
|
responseCallback(resp)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
responseCallback?(nil)
|
responseCallback(nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,13 +75,12 @@ class JsBridgeUtil {
|
|||||||
"port": port,
|
"port": port,
|
||||||
"secret": ConfigManager.shared.overrideSecret ?? ConfigManager.shared.apiSecret
|
"secret": ConfigManager.shared.overrideSecret ?? ConfigManager.shared.apiSecret
|
||||||
]
|
]
|
||||||
callback?(data)
|
callback(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ping-pong
|
// ping-pong
|
||||||
bridge.registerHandler("ping") { [weak bridge] _, responseCallback in
|
bridge.registerHandler("ping") { _, responseCallback in
|
||||||
bridge?.callHandler("pong")
|
responseCallback("pong")
|
||||||
responseCallback?(true)
|
|
||||||
}
|
}
|
||||||
return bridge
|
return bridge
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ import Cocoa
|
|||||||
import RxCocoa
|
import RxCocoa
|
||||||
import RxSwift
|
import RxSwift
|
||||||
import WebKit
|
import WebKit
|
||||||
import WebViewJavascriptBridge
|
|
||||||
|
|
||||||
enum WebCacheCleaner {
|
enum WebCacheCleaner {
|
||||||
static func clean() {
|
static func clean() {
|
||||||
@ -27,7 +26,7 @@ enum WebCacheCleaner {
|
|||||||
|
|
||||||
class ClashWebViewContoller: NSViewController {
|
class ClashWebViewContoller: NSViewController {
|
||||||
let webview: CustomWKWebView = .init()
|
let webview: CustomWKWebView = .init()
|
||||||
var bridge: WebViewJavascriptBridge?
|
var bridge: JSBridge?
|
||||||
let disposeBag = DisposeBag()
|
let disposeBag = DisposeBag()
|
||||||
let minSize = NSSize(width: 920, height: 580)
|
let minSize = NSSize(width: 920, height: 580)
|
||||||
|
|
||||||
@ -53,15 +52,9 @@ class ClashWebViewContoller: NSViewController {
|
|||||||
webview.configuration.userContentController.addUserScript(script)
|
webview.configuration.userContentController.addUserScript(script)
|
||||||
|
|
||||||
bridge = JsBridgeUtil.initJSbridge(webview: webview, delegate: self)
|
bridge = JsBridgeUtil.initJSbridge(webview: webview, delegate: self)
|
||||||
registerExtenalJSBridgeFunction()
|
|
||||||
|
|
||||||
webview.configuration.preferences.setValue(true, forKey: "developerExtrasEnabled")
|
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 {
|
NotificationCenter.default.rx.notification(.reloadDashboard).bind {
|
||||||
[weak self] _ in
|
[weak self] _ in
|
||||||
self?.webview.reload()
|
self?.webview.reload()
|
||||||
@ -113,17 +106,10 @@ class ClashWebViewContoller: NSViewController {
|
|||||||
}
|
}
|
||||||
Logger.log("load dashboard url fail", level: .error)
|
Logger.log("load dashboard url fail", level: .error)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
extension ClashWebViewContoller {
|
func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
|
||||||
func registerExtenalJSBridgeFunction() {
|
NSAlert.alert(with: message)
|
||||||
bridge?.registerHandler("setDragAreaHeight") {
|
completionHandler()
|
||||||
[weak self] anydata, responseCallback in
|
|
||||||
if let height = anydata as? CGFloat {
|
|
||||||
self?.webview.dragableAreaHeight = height
|
|
||||||
}
|
|
||||||
responseCallback?(nil)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
Podfile
1
Podfile
@ -24,7 +24,6 @@ target 'ClashX' do
|
|||||||
pod 'RxSwift'
|
pod 'RxSwift'
|
||||||
pod 'RxCocoa'
|
pod 'RxCocoa'
|
||||||
pod 'CocoaLumberjack/Swift'
|
pod 'CocoaLumberjack/Swift'
|
||||||
pod 'WebViewJavascriptBridge'
|
|
||||||
pod 'Starscream','3.1.1'
|
pod 'Starscream','3.1.1'
|
||||||
pod 'AppCenter/Analytics'
|
pod 'AppCenter/Analytics'
|
||||||
pod 'AppCenter/Crashes'
|
pod 'AppCenter/Crashes'
|
||||||
|
@ -22,7 +22,6 @@ PODS:
|
|||||||
- SwiftFormat/CLI (0.52.3)
|
- SwiftFormat/CLI (0.52.3)
|
||||||
- SwiftLint (0.52.4)
|
- SwiftLint (0.52.4)
|
||||||
- SwiftyJSON (5.0.1)
|
- SwiftyJSON (5.0.1)
|
||||||
- WebViewJavascriptBridge (6.0.3)
|
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- Alamofire (~> 5.0)
|
- Alamofire (~> 5.0)
|
||||||
@ -39,7 +38,6 @@ DEPENDENCIES:
|
|||||||
- SwiftFormat/CLI (~> 0.49)
|
- SwiftFormat/CLI (~> 0.49)
|
||||||
- SwiftLint
|
- SwiftLint
|
||||||
- SwiftyJSON
|
- SwiftyJSON
|
||||||
- WebViewJavascriptBridge
|
|
||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
trunk:
|
trunk:
|
||||||
@ -57,7 +55,6 @@ SPEC REPOS:
|
|||||||
- SwiftFormat
|
- SwiftFormat
|
||||||
- SwiftLint
|
- SwiftLint
|
||||||
- SwiftyJSON
|
- SwiftyJSON
|
||||||
- WebViewJavascriptBridge
|
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
Alamofire: 0e92e751b3e9e66d7982db43919d01f313b8eb91
|
Alamofire: 0e92e751b3e9e66d7982db43919d01f313b8eb91
|
||||||
@ -74,8 +71,7 @@ SPEC CHECKSUMS:
|
|||||||
SwiftFormat: 5de81c42f043741a16e17ae2da012bbddc7c0b58
|
SwiftFormat: 5de81c42f043741a16e17ae2da012bbddc7c0b58
|
||||||
SwiftLint: 1cc5cd61ba9bacb2194e340aeb47a2a37fda00b3
|
SwiftLint: 1cc5cd61ba9bacb2194e340aeb47a2a37fda00b3
|
||||||
SwiftyJSON: 2f33a42c6fbc52764d96f13368585094bfd8aa5e
|
SwiftyJSON: 2f33a42c6fbc52764d96f13368585094bfd8aa5e
|
||||||
WebViewJavascriptBridge: 7f5bc4d3581e672e8f32bd0f812d54bc69bb8e29
|
|
||||||
|
|
||||||
PODFILE CHECKSUM: d3e952c889c7931151a654c076812b3b3294aa59
|
PODFILE CHECKSUM: f3a6ebd40f44d7184ef9437d24b1979389395820
|
||||||
|
|
||||||
COCOAPODS: 1.12.1
|
COCOAPODS: 1.12.1
|
||||||
|
Loading…
Reference in New Issue
Block a user