【Feature】add remote config file fetcher
This commit is contained in:
parent
45c73cd80c
commit
b3a509a499
|
@ -24,6 +24,7 @@
|
|||
495A44BF20D2660A00888A0A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 495A44BE20D2660A00888A0A /* AppDelegate.swift */; };
|
||||
495A44CD20D266BA00888A0A /* ClashXLaunchHelper.app in CopyFiles */ = {isa = PBXBuildFile; fileRef = 495A44BC20D2660A00888A0A /* ClashXLaunchHelper.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
495A44D320D267D000888A0A /* LaunchAtLogin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 495A44D220D267D000888A0A /* LaunchAtLogin.swift */; };
|
||||
495BFB8821919B9800C8779D /* RemoteConfigManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 495BFB8721919B9800C8779D /* RemoteConfigManager.swift */; };
|
||||
4960A6DB2136529200B940C9 /* JSBridgeHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4960A6DA2136529200B940C9 /* JSBridgeHandler.swift */; };
|
||||
4966E9E32118153A00A391FB /* NSUserNotificationCenter+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4966E9E22118153A00A391FB /* NSUserNotificationCenter+Extension.swift */; };
|
||||
4966E9E6211824F300A391FB /* NSImage+extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4966E9E5211824F300A391FB /* NSImage+extension.swift */; };
|
||||
|
@ -125,6 +126,7 @@
|
|||
495A44C720D2660B00888A0A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
495A44C820D2660B00888A0A /* ClashXLaunchHelper.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ClashXLaunchHelper.entitlements; sourceTree = "<group>"; };
|
||||
495A44D220D267D000888A0A /* LaunchAtLogin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchAtLogin.swift; sourceTree = "<group>"; };
|
||||
495BFB8721919B9800C8779D /* RemoteConfigManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteConfigManager.swift; sourceTree = "<group>"; };
|
||||
4960A6DA2136529200B940C9 /* JSBridgeHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSBridgeHandler.swift; sourceTree = "<group>"; };
|
||||
4966E9E22118153A00A391FB /* NSUserNotificationCenter+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSUserNotificationCenter+Extension.swift"; sourceTree = "<group>"; };
|
||||
4966E9E5211824F300A391FB /* NSImage+extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSImage+extension.swift"; sourceTree = "<group>"; };
|
||||
|
@ -211,6 +213,7 @@
|
|||
4949D15C2132614B00EF85E6 /* QRCodeUtil.swift */,
|
||||
4960A6DA2136529200B940C9 /* JSBridgeHandler.swift */,
|
||||
4931969A21631E5D00A8E6E7 /* SpeedDataRecorder.swift */,
|
||||
495BFB8721919B9800C8779D /* RemoteConfigManager.swift */,
|
||||
);
|
||||
path = General;
|
||||
sourceTree = "<group>";
|
||||
|
@ -618,6 +621,7 @@
|
|||
492C4871210EF62E004554A0 /* ClashConfig.swift in Sources */,
|
||||
492C4869210EE6B9004554A0 /* ApiRequest.swift in Sources */,
|
||||
49CF3B6520CEE06C001EBF94 /* ConfigManager.swift in Sources */,
|
||||
495BFB8821919B9800C8779D /* RemoteConfigManager.swift in Sources */,
|
||||
49722FF1211F338B00650A41 /* Witness.swift in Sources */,
|
||||
49722FF0211F338B00650A41 /* EventStream.swift in Sources */,
|
||||
4952C3BF2115C7CA004A4FA8 /* ProxyMenuItemFactory.swift in Sources */,
|
||||
|
|
|
@ -420,7 +420,14 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||
NSWorkspace.shared.openFile(Logger.shared.logFilePath())
|
||||
|
||||
}
|
||||
@IBAction func actionSetRemoteConfigUrl(_ sender: Any) {
|
||||
RemoteConfigManager.showUrlInputAlert()
|
||||
}
|
||||
|
||||
|
||||
@IBAction func actionUpdateRemoteConfig(_ sender: Any) {
|
||||
RemoteConfigManager.updateConfigIfNeed()
|
||||
}
|
||||
}
|
||||
|
||||
extension AppDelegate:NSMenuDelegate {
|
||||
|
|
|
@ -132,6 +132,25 @@
|
|||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Remote Config" id="h1C-R6-Y9w">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Remote Config" id="az2-wz-yyy">
|
||||
<items>
|
||||
<menuItem title="Set Url" id="k1Z-jQ-kAy">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="actionSetRemoteConfigUrl:" target="Voe-Tx-rLC" id="ZSD-Pg-4xP"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Update" id="I2P-Wd-Ns7">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="actionUpdateRemoteConfig:" target="Voe-Tx-rLC" id="umk-nZ-asT"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Open config Folder" keyEquivalent="o" id="DwE-WX-ETZ">
|
||||
<connections>
|
||||
<action selector="openConfigFolder:" target="Voe-Tx-rLC" id="6Ke-Bi-AAZ"/>
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
//
|
||||
// RemoteConfigManager.swift
|
||||
// ClashX
|
||||
//
|
||||
// Created by CYC on 2018/11/6.
|
||||
// Copyright © 2018 west2online. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
import Alamofire
|
||||
import Yams
|
||||
|
||||
class RemoteConfigManager: NSObject {
|
||||
static var configUrl:String? {
|
||||
get {
|
||||
return UserDefaults.standard.string(forKey: "kRemoteConfigUrl")
|
||||
}
|
||||
|
||||
set {
|
||||
UserDefaults.standard.set(newValue, forKey: "kRemoteConfigUrl")
|
||||
}
|
||||
}
|
||||
|
||||
static func showUrlInputAlert() {
|
||||
let msg = NSAlert()
|
||||
msg.addButton(withTitle: "OK")
|
||||
msg.addButton(withTitle: "Cancel") // 2nd button
|
||||
msg.messageText = "Remote config"
|
||||
msg.informativeText = "url:"
|
||||
|
||||
let txt = NSTextField(frame: NSRect(x: 0, y: 0, width: 300, height: 24))
|
||||
txt.cell?.usesSingleLineMode = true
|
||||
txt.stringValue = configUrl ?? ""
|
||||
msg.accessoryView = txt
|
||||
let response = msg.runModal()
|
||||
|
||||
if response == .alertFirstButtonReturn {
|
||||
if URL(string: txt.stringValue) != nil {
|
||||
configUrl = txt.stringValue
|
||||
updateConfigIfNeed()
|
||||
}else {
|
||||
alert(with: "Url Error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static func getRemoteConfigString(handler:@escaping (String?)->()) {
|
||||
guard let url = configUrl else {alert(with: "Not config url set!");return}
|
||||
request(url, method: .get).responseString { (res) in
|
||||
if let s = res.result.value {
|
||||
handler(s)
|
||||
} else {
|
||||
handler(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static func updateConfigIfNeed() {
|
||||
getRemoteConfigString { (string) in
|
||||
guard let newConfigString = string else {alert(with: "Download fail"); return}
|
||||
if FileManager.default.fileExists(atPath: kConfigFilePath) {
|
||||
do {
|
||||
let currentConfigStr = try String(contentsOfFile: kConfigFilePath)
|
||||
if currentConfigStr == newConfigString {
|
||||
self.alert(with: "Config not updated")
|
||||
} else {
|
||||
guard var originConfig = (try Yams.load(yaml: currentConfigStr)) as? [String:Any] else { throw "Can not parse current config"}
|
||||
guard let newConfig = try Yams.load(yaml: newConfigString) as? [String:Any] else { throw "Can not parse new config"}
|
||||
|
||||
originConfig["Proxy"] = newConfig["Proxy"]
|
||||
originConfig["Proxy Group"] = newConfig["Proxy Group"]
|
||||
originConfig["Rule"] = newConfig["Rule"]
|
||||
|
||||
for (k,v) in originConfig {
|
||||
if v is NSNull {
|
||||
originConfig[k] = nil
|
||||
}
|
||||
}
|
||||
|
||||
let newConfigStringToWrite = try Yams.dump(object: originConfig)
|
||||
try FileManager.default.removeItem(atPath: kConfigFilePath)
|
||||
try newConfigStringToWrite.write(toFile: kConfigFilePath, atomically: true, encoding: .utf8)
|
||||
NotificationCenter.default.post(Notification(name: kShouldUpDateConfig))
|
||||
self.alert(with: "Success!")
|
||||
}
|
||||
} catch let err {
|
||||
self.alert(with: err.localizedDescription)
|
||||
}
|
||||
|
||||
} else {
|
||||
do {
|
||||
try string?.write(toFile: kConfigFilePath, atomically: true, encoding: .utf8)
|
||||
NotificationCenter.default.post(Notification(name: kShouldUpDateConfig))
|
||||
self.alert(with: "Success!")
|
||||
} catch let err {
|
||||
self.alert(with: err.localizedDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static func alert(with text:String) {
|
||||
let alert = NSAlert()
|
||||
alert.messageText = text
|
||||
alert.alertStyle = .warning
|
||||
alert.addButton(withTitle: "OK")
|
||||
alert.runModal()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension String: Error {}
|
|
@ -20,6 +20,15 @@
|
|||
/* Class = "NSMenuItem"; title = "Rule"; ObjectID = "89n-bD-JHk"; */
|
||||
"89n-bD-JHk.title" = "规则判断";
|
||||
|
||||
/* Class = "NSMenuItem"; title = "Remote config"; ObjectID = "h1C-R6-Y9w"; */
|
||||
"h1C-R6-Y9w.title" = "托管配置";
|
||||
|
||||
/* Class = "NSMenuItem"; title = "Set url"; ObjectID = "k1Z-jQ-kAy"; */
|
||||
"k1Z-jQ-kAy.title" = "设置地址";
|
||||
|
||||
/* Class = "NSMenuItem"; title = "Update"; ObjectID = "I2P-Wd-Ns7"; */
|
||||
"I2P-Wd-Ns7.title" = "更新";
|
||||
|
||||
/* Class = "NSMenuItem"; title = "Set as system proxy"; ObjectID = "8se-yr-wmp"; */
|
||||
"8se-yr-wmp.title" = "设置为系统代理";
|
||||
|
||||
|
|
Loading…
Reference in New Issue