2018-06-13 10:44:30 +08:00
|
|
|
//
|
|
|
|
// AppDelegate.swift
|
|
|
|
// ClashX
|
|
|
|
//
|
2018-08-08 13:47:38 +08:00
|
|
|
// Created by CYC on 2018/6/10.
|
|
|
|
// Copyright © 2018年 yichengchen. All rights reserved.
|
2018-06-13 10:44:30 +08:00
|
|
|
//
|
|
|
|
|
|
|
|
import Cocoa
|
2018-06-23 14:37:00 +08:00
|
|
|
import LetsMove
|
2018-06-23 21:43:33 +08:00
|
|
|
import Alamofire
|
2018-08-04 14:33:47 +08:00
|
|
|
import RxCocoa
|
|
|
|
import RxSwift
|
2018-06-14 12:56:07 +08:00
|
|
|
|
2018-06-13 10:44:30 +08:00
|
|
|
@NSApplicationMain
|
|
|
|
class AppDelegate: NSObject, NSApplicationDelegate {
|
|
|
|
var statusItem: NSStatusItem!
|
|
|
|
|
|
|
|
@IBOutlet weak var statusMenu: NSMenu!
|
|
|
|
@IBOutlet weak var proxySettingMenuItem: NSMenuItem!
|
2018-06-14 16:16:00 +08:00
|
|
|
@IBOutlet weak var autoStartMenuItem: NSMenuItem!
|
2018-06-13 10:44:30 +08:00
|
|
|
|
2018-08-04 16:30:10 +08:00
|
|
|
@IBOutlet weak var proxyModeGlobalMenuItem: NSMenuItem!
|
|
|
|
@IBOutlet weak var proxyModeDirectMenuItem: NSMenuItem!
|
|
|
|
@IBOutlet weak var proxyModeRuleMenuItem: NSMenuItem!
|
2018-08-26 21:21:09 +08:00
|
|
|
@IBOutlet weak var allowFromLanMenuItem: NSMenuItem!
|
2018-08-04 21:49:32 +08:00
|
|
|
|
2018-08-07 23:21:09 +08:00
|
|
|
@IBOutlet weak var proxyModeMenuItem: NSMenuItem!
|
2018-08-05 01:17:27 +08:00
|
|
|
@IBOutlet weak var showNetSpeedIndicatorMenuItem: NSMenuItem!
|
2018-08-04 21:49:32 +08:00
|
|
|
@IBOutlet weak var separatorLineTop: NSMenuItem!
|
2018-08-04 22:09:11 +08:00
|
|
|
@IBOutlet weak var sepatatorLineEndProxySelect: NSMenuItem!
|
2018-08-04 21:49:32 +08:00
|
|
|
|
2018-08-12 11:29:51 +08:00
|
|
|
@IBOutlet weak var logLevelMenuItem: NSMenuItem!
|
|
|
|
|
2018-08-04 16:30:10 +08:00
|
|
|
var disposeBag = DisposeBag()
|
2018-06-13 10:44:30 +08:00
|
|
|
let ssQueue = DispatchQueue(label: "com.w2fzu.ssqueue", attributes: .concurrent)
|
2018-08-05 01:17:27 +08:00
|
|
|
var statusItemView:StatusItemView!
|
2018-06-23 20:17:05 +08:00
|
|
|
|
2018-08-19 12:57:15 +08:00
|
|
|
var isRunning = false
|
|
|
|
|
2018-06-13 10:44:30 +08:00
|
|
|
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
2018-06-14 12:56:07 +08:00
|
|
|
signal(SIGPIPE, SIG_IGN)
|
2018-08-12 18:03:55 +08:00
|
|
|
failLaunchProtect()
|
2018-06-13 10:44:30 +08:00
|
|
|
_ = ProxyConfigManager.install()
|
2018-07-30 13:35:18 +08:00
|
|
|
PFMoveToApplicationsFolderIfNecessary()
|
2018-08-05 01:17:27 +08:00
|
|
|
statusItemView = StatusItemView.create(statusItem: nil,statusMenu: statusMenu)
|
2018-08-05 19:45:37 +08:00
|
|
|
statusItemView.onPopUpMenuAction = {
|
|
|
|
[weak self] in
|
|
|
|
guard let `self` = self else {return}
|
2018-08-11 13:23:06 +08:00
|
|
|
self.syncConfig()
|
2018-08-05 19:45:37 +08:00
|
|
|
}
|
2018-08-04 16:30:10 +08:00
|
|
|
setupData()
|
2018-08-19 14:07:56 +08:00
|
|
|
startProxy()
|
2018-08-26 13:25:29 +08:00
|
|
|
updateLoggingLevel()
|
2018-06-13 10:44:30 +08:00
|
|
|
}
|
2018-06-23 20:17:05 +08:00
|
|
|
|
2018-06-13 10:44:30 +08:00
|
|
|
|
|
|
|
func applicationWillTerminate(_ aNotification: Notification) {
|
2018-08-04 16:30:10 +08:00
|
|
|
if ConfigManager.shared.proxyPortAutoSet {
|
2018-06-13 10:44:30 +08:00
|
|
|
_ = ProxyConfigManager.setUpSystemProxy(port: nil,socksPort: nil)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-04 16:30:10 +08:00
|
|
|
func setupData() {
|
2018-08-12 00:10:42 +08:00
|
|
|
|
|
|
|
// check and refresh api url
|
|
|
|
_ = ConfigManager.apiUrl
|
|
|
|
// start watch config file change
|
|
|
|
ConfigFileFactory.shared.watchConfigFile()
|
|
|
|
|
2018-08-04 16:30:10 +08:00
|
|
|
NotificationCenter.default.rx.notification(kShouldUpDateConfig).bind {
|
|
|
|
[unowned self] (note) in
|
2018-08-11 17:29:31 +08:00
|
|
|
self.actionUpdateConfig(self)
|
|
|
|
}.disposed(by: disposeBag)
|
2018-08-04 16:30:10 +08:00
|
|
|
|
2018-08-05 01:17:27 +08:00
|
|
|
|
|
|
|
ConfigManager.shared
|
|
|
|
.showNetSpeedIndicatorObservable
|
|
|
|
.bind {[unowned self] (show) in
|
2018-08-06 16:54:41 +08:00
|
|
|
self.showNetSpeedIndicatorMenuItem.state = (show ?? true) ? .on : .off
|
2018-08-07 23:01:03 +08:00
|
|
|
self.statusItem = NSStatusBar.system.statusItem(withLength: (show ?? true) ? 65 : 25)
|
2018-08-05 01:17:27 +08:00
|
|
|
self.statusItem.view = self.statusItemView
|
2018-08-06 16:54:41 +08:00
|
|
|
self.statusItemView.showSpeedContainer(show: (show ?? true))
|
2018-08-05 01:17:27 +08:00
|
|
|
self.statusItemView.statusItem = self.statusItem
|
|
|
|
}.disposed(by: disposeBag)
|
|
|
|
|
|
|
|
ConfigManager.shared
|
|
|
|
.proxyPortAutoSetObservable
|
2018-08-04 16:30:10 +08:00
|
|
|
.distinctUntilChanged()
|
|
|
|
.bind{ [unowned self]
|
2018-08-06 16:54:41 +08:00
|
|
|
en in
|
|
|
|
let enable = en ?? false
|
|
|
|
self.proxySettingMenuItem.state = enable ? .on : .off
|
2018-08-04 16:30:10 +08:00
|
|
|
}.disposed(by: disposeBag)
|
|
|
|
|
2018-08-19 11:30:03 +08:00
|
|
|
let configObservable = ConfigManager.shared
|
2018-08-05 01:17:27 +08:00
|
|
|
.currentConfigVariable
|
2018-08-04 16:30:10 +08:00
|
|
|
.asObservable()
|
2018-08-19 11:30:03 +08:00
|
|
|
Observable.zip(configObservable,configObservable.skip(1))
|
|
|
|
.filter{(_, new) in return new != nil}
|
|
|
|
.bind {[unowned self] (old,config) in
|
2018-08-04 16:30:10 +08:00
|
|
|
self.proxyModeDirectMenuItem.state = .off
|
|
|
|
self.proxyModeGlobalMenuItem.state = .off
|
|
|
|
self.proxyModeRuleMenuItem.state = .off
|
|
|
|
|
|
|
|
switch config!.mode {
|
|
|
|
case .direct:self.proxyModeDirectMenuItem.state = .on
|
|
|
|
case .global:self.proxyModeGlobalMenuItem.state = .on
|
|
|
|
case .rule:self.proxyModeRuleMenuItem.state = .on
|
|
|
|
}
|
2018-08-26 21:21:09 +08:00
|
|
|
self.allowFromLanMenuItem.state = config!.allowLan ? .on : .off
|
2018-08-07 23:21:09 +08:00
|
|
|
self.proxyModeMenuItem.title = "Proxy Mode (\(config!.mode.rawValue))"
|
|
|
|
|
2018-08-04 23:41:28 +08:00
|
|
|
self.updateProxyList()
|
2018-08-06 23:06:50 +08:00
|
|
|
|
2018-08-20 12:25:16 +08:00
|
|
|
if (old?.port != config?.port && ConfigManager.shared.proxyPortAutoSet) {
|
|
|
|
_ = ProxyConfigManager.setUpSystemProxy(port: config!.port,socksPort: config!.socketPort)
|
2018-08-06 23:06:50 +08:00
|
|
|
}
|
2018-08-19 11:30:03 +08:00
|
|
|
|
2018-08-11 13:23:06 +08:00
|
|
|
self.selectProxyGroupWithMemory()
|
2018-08-04 16:30:10 +08:00
|
|
|
}.disposed(by: disposeBag)
|
2018-06-14 16:16:00 +08:00
|
|
|
|
2018-08-05 01:17:27 +08:00
|
|
|
LaunchAtLogin.shared
|
|
|
|
.isEnableVirable
|
2018-08-04 16:30:10 +08:00
|
|
|
.asObservable()
|
|
|
|
.subscribe(onNext: { (enable) in
|
|
|
|
self.autoStartMenuItem.state = enable ? .on : .off
|
|
|
|
}).disposed(by: disposeBag)
|
2018-08-05 01:17:27 +08:00
|
|
|
|
|
|
|
|
2018-06-13 10:44:30 +08:00
|
|
|
}
|
|
|
|
|
2018-08-12 18:03:55 +08:00
|
|
|
func failLaunchProtect(){
|
2018-08-06 15:52:38 +08:00
|
|
|
let x = UserDefaults.standard
|
|
|
|
var launch_fail_times:Int = 0
|
|
|
|
if let xx = x.object(forKey: "launch_fail_times") as? Int {launch_fail_times = xx }
|
|
|
|
launch_fail_times += 1
|
|
|
|
x.set(launch_fail_times, forKey: "launch_fail_times")
|
2018-08-19 11:31:43 +08:00
|
|
|
if launch_fail_times > 2{
|
2018-08-06 15:52:38 +08:00
|
|
|
//发生连续崩溃
|
|
|
|
let path = (NSHomeDirectory() as NSString).appendingPathComponent("/.config/clash/")
|
|
|
|
let documentDirectory = URL(fileURLWithPath: path)
|
|
|
|
let originPath = documentDirectory.appendingPathComponent("config.ini")
|
|
|
|
let destinationPath = documentDirectory.appendingPathComponent("config.ini.bak")
|
2018-08-12 18:03:55 +08:00
|
|
|
try? FileManager.default.removeItem(at:destinationPath)
|
2018-08-06 15:52:38 +08:00
|
|
|
try? FileManager.default.moveItem(at: originPath, to: destinationPath)
|
|
|
|
try? FileManager.default.removeItem(at: documentDirectory.appendingPathComponent("Country.mmdb"))
|
|
|
|
NSUserNotificationCenter.default.post(title: "Fail on launch protect", info: "You origin Config has been rename to config.ini.bak")
|
|
|
|
|
|
|
|
}
|
|
|
|
DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + Double(Int64(1 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: {
|
|
|
|
x.set(0, forKey: "launch_fail_times")
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-08-06 23:06:50 +08:00
|
|
|
func selectProxyGroupWithMemory(){
|
|
|
|
for item in ConfigManager.selectedProxyMap {
|
|
|
|
ApiRequest.updateProxyGroup(group: item.key, selectProxy: item.value) { (success) in
|
|
|
|
if (!success) {
|
|
|
|
ConfigManager.selectedProxyMap[item.key] = nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-11 14:02:34 +08:00
|
|
|
func selectOutBoundModeWithMenory() {
|
|
|
|
ApiRequest.updateOutBoundMode(mode: ConfigManager.selectOutBoundMode){
|
|
|
|
_ in
|
|
|
|
self.syncConfig()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-26 21:21:09 +08:00
|
|
|
func selectAllowLanWithMenory() {
|
|
|
|
ApiRequest.updateAllowLan(allow: ConfigManager.allowConnectFromLan){
|
|
|
|
self.syncConfig()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-04 22:09:11 +08:00
|
|
|
func updateProxyList() {
|
2018-08-04 21:49:32 +08:00
|
|
|
ProxyMenuItemFactory.menuItems { [unowned self] (menus) in
|
2018-08-11 14:02:34 +08:00
|
|
|
let startIndex = self.statusMenu.items.index(of: self.separatorLineTop)!+1
|
|
|
|
let endIndex = self.statusMenu.items.index(of: self.sepatatorLineEndProxySelect)!
|
2018-08-04 21:49:32 +08:00
|
|
|
var items = self.statusMenu.items
|
2018-08-11 14:02:34 +08:00
|
|
|
|
2018-08-11 23:07:51 +08:00
|
|
|
self.sepatatorLineEndProxySelect.isHidden = menus.count == 0
|
2018-08-11 14:02:34 +08:00
|
|
|
items.removeSubrange(Range(uncheckedBounds: (lower: startIndex, upper: endIndex)))
|
2018-08-05 19:45:37 +08:00
|
|
|
|
2018-08-04 21:49:32 +08:00
|
|
|
for each in menus {
|
2018-08-04 22:09:11 +08:00
|
|
|
items.insert(each, at: startIndex)
|
2018-08-04 21:49:32 +08:00
|
|
|
}
|
|
|
|
self.statusMenu.removeAllItems()
|
|
|
|
for each in items.reversed() {
|
|
|
|
self.statusMenu.insertItem(each, at: 0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-12 11:29:51 +08:00
|
|
|
func updateLoggingLevel() {
|
|
|
|
for item in self.logLevelMenuItem.submenu?.items ?? [] {
|
|
|
|
item.state = item.title.lowercased() == ConfigManager.selectLoggingApiLevel.rawValue ? .on : .off
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-07 23:21:09 +08:00
|
|
|
|
2018-06-13 10:44:30 +08:00
|
|
|
func startProxy() {
|
2018-08-19 12:57:15 +08:00
|
|
|
if self.isRunning {return}
|
|
|
|
|
|
|
|
self.isRunning = true
|
|
|
|
print("Trying start proxy")
|
|
|
|
if let cstring = run() {
|
|
|
|
// self.isRunning = false
|
|
|
|
let error = String(cString: cstring)
|
|
|
|
if (error != "success") {
|
|
|
|
NSUserNotificationCenter.default.postConfigErrorNotice(msg:error)
|
|
|
|
} else {
|
2018-08-27 20:14:45 +08:00
|
|
|
self.resetStreamApi()
|
|
|
|
self.selectOutBoundModeWithMenory()
|
|
|
|
self.selectAllowLanWithMenory()
|
2018-08-19 12:57:15 +08:00
|
|
|
}
|
2018-06-13 10:44:30 +08:00
|
|
|
}
|
2018-08-19 12:57:15 +08:00
|
|
|
|
2018-08-04 14:33:47 +08:00
|
|
|
}
|
|
|
|
|
2018-08-26 21:21:09 +08:00
|
|
|
func syncConfig(completeHandler:(()->())? = nil){
|
2018-07-30 15:55:10 +08:00
|
|
|
ApiRequest.requestConfig{ (config) in
|
2018-08-04 14:33:47 +08:00
|
|
|
guard config.port > 0 else {return}
|
2018-08-04 16:30:10 +08:00
|
|
|
ConfigManager.shared.currentConfig = config
|
2018-08-26 21:21:09 +08:00
|
|
|
completeHandler?()
|
2018-06-23 21:43:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-07 15:09:25 +08:00
|
|
|
func resetStreamApi() {
|
2018-08-04 14:33:47 +08:00
|
|
|
ApiRequest.shared.requestTrafficInfo(){ [weak self] up,down in
|
2018-07-30 15:55:10 +08:00
|
|
|
guard let `self` = self else {return}
|
|
|
|
((self.statusItem.view) as! StatusItemView).updateSpeedLabel(up: up, down: down)
|
2018-06-23 21:43:33 +08:00
|
|
|
}
|
2018-08-07 15:09:25 +08:00
|
|
|
|
|
|
|
ApiRequest.shared.requestLog { (type, msg) in
|
2018-08-12 10:30:21 +08:00
|
|
|
Logger.log(msg: msg,level: ClashLogLevel(rawValue: type) ?? .unknow)
|
2018-08-07 15:09:25 +08:00
|
|
|
}
|
2018-06-13 10:44:30 +08:00
|
|
|
}
|
2018-08-04 16:30:10 +08:00
|
|
|
|
2018-08-04 14:33:47 +08:00
|
|
|
|
|
|
|
//Actions:
|
2018-06-23 21:43:33 +08:00
|
|
|
|
2018-06-13 10:44:30 +08:00
|
|
|
@IBAction func actionQuit(_ sender: Any) {
|
|
|
|
NSApplication.shared.terminate(self)
|
|
|
|
}
|
2018-08-04 14:33:47 +08:00
|
|
|
|
2018-06-13 10:44:30 +08:00
|
|
|
@IBAction func actionSetSystemProxy(_ sender: Any) {
|
2018-08-04 16:30:10 +08:00
|
|
|
ConfigManager.shared.proxyPortAutoSet = !ConfigManager.shared.proxyPortAutoSet
|
|
|
|
if ConfigManager.shared.proxyPortAutoSet {
|
|
|
|
let port = ConfigManager.shared.currentConfig?.port ?? 0
|
|
|
|
let socketPort = ConfigManager.shared.currentConfig?.socketPort ?? 0
|
|
|
|
_ = ProxyConfigManager.setUpSystemProxy(port: port,socksPort:socketPort)
|
2018-06-13 10:44:30 +08:00
|
|
|
} else {
|
|
|
|
_ = ProxyConfigManager.setUpSystemProxy(port: nil,socksPort: nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@IBAction func actionCopyExportCommand(_ sender: Any) {
|
|
|
|
let pasteboard = NSPasteboard.general
|
|
|
|
pasteboard.clearContents()
|
2018-08-04 16:30:10 +08:00
|
|
|
let port = ConfigManager.shared.currentConfig?.port ?? 0
|
|
|
|
pasteboard.setString("export https_proxy=http://127.0.0.1:\(port);export http_proxy=http://127.0.0.1:\(port)", forType: .string)
|
2018-06-13 10:44:30 +08:00
|
|
|
}
|
2018-08-26 21:21:09 +08:00
|
|
|
@IBAction func actionAllowFromLan(_ sender: NSMenuItem) {
|
|
|
|
ApiRequest.updateAllowLan(allow: !ConfigManager.allowConnectFromLan) {
|
|
|
|
[unowned self] in
|
|
|
|
self.syncConfig()
|
|
|
|
ConfigManager.allowConnectFromLan = !ConfigManager.allowConnectFromLan
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2018-06-13 10:44:30 +08:00
|
|
|
|
2018-06-14 16:16:00 +08:00
|
|
|
@IBAction func actionStartAtLogin(_ sender: NSMenuItem) {
|
2018-08-04 16:30:10 +08:00
|
|
|
LaunchAtLogin.shared.isEnabled = !LaunchAtLogin.shared.isEnabled
|
2018-06-14 16:16:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
var genConfigWindow:NSWindowController?=nil
|
|
|
|
@IBAction func actionGenConfig(_ sender: Any) {
|
2018-08-05 18:00:34 +08:00
|
|
|
let ctrl = PreferencesWindowController(windowNibName: NSNib.Name(rawValue: "PreferencesWindowController"))
|
|
|
|
|
2018-06-23 14:27:04 +08:00
|
|
|
|
2018-06-14 16:16:00 +08:00
|
|
|
genConfigWindow?.close()
|
|
|
|
genConfigWindow=ctrl
|
2018-06-23 14:27:04 +08:00
|
|
|
ctrl.window?.title = ctrl.contentViewController?.title ?? ""
|
2018-06-14 16:16:00 +08:00
|
|
|
ctrl.showWindow(nil)
|
|
|
|
NSApp.activate(ignoringOtherApps: true)
|
|
|
|
ctrl.window?.makeKeyAndOrderFront(self)
|
|
|
|
|
|
|
|
}
|
2018-06-13 10:44:30 +08:00
|
|
|
|
|
|
|
@IBAction func openConfigFolder(_ sender: Any) {
|
2018-08-19 11:14:41 +08:00
|
|
|
let path = (NSHomeDirectory() as NSString).appendingPathComponent("/.config/clash")
|
2018-06-13 10:44:30 +08:00
|
|
|
NSWorkspace.shared.openFile(path)
|
|
|
|
}
|
2018-08-04 16:30:10 +08:00
|
|
|
|
2018-06-13 10:44:30 +08:00
|
|
|
@IBAction func actionUpdateConfig(_ sender: Any) {
|
2018-08-19 12:57:15 +08:00
|
|
|
ApiRequest.requestConfigUpdate() { [unowned self] error in
|
|
|
|
if (error == nil) {
|
2018-08-11 13:23:06 +08:00
|
|
|
self.syncConfig()
|
|
|
|
self.resetStreamApi()
|
2018-08-19 12:57:15 +08:00
|
|
|
self.selectProxyGroupWithMemory()
|
|
|
|
self.selectOutBoundModeWithMenory()
|
2018-08-06 14:17:04 +08:00
|
|
|
NSUserNotificationCenter
|
|
|
|
.default
|
|
|
|
.post(title: "Reload Config Succeed", info: "succees")
|
|
|
|
} else {
|
|
|
|
NSUserNotificationCenter
|
|
|
|
.default
|
2018-08-19 12:57:15 +08:00
|
|
|
.post(title: "Reload Config Fail", info: error ?? "")
|
2018-08-04 16:30:10 +08:00
|
|
|
}
|
2018-08-06 14:17:04 +08:00
|
|
|
|
2018-06-13 10:44:30 +08:00
|
|
|
}
|
|
|
|
}
|
2018-08-04 16:30:10 +08:00
|
|
|
|
2018-08-12 11:29:51 +08:00
|
|
|
@IBAction func actionSetLogLevel(_ sender: NSMenuItem) {
|
|
|
|
let level = ClashLogLevel(rawValue: sender.title.lowercased()) ?? .unknow
|
|
|
|
ConfigManager.selectLoggingApiLevel = level
|
|
|
|
updateLoggingLevel()
|
|
|
|
resetStreamApi()
|
|
|
|
}
|
|
|
|
|
2018-08-05 23:16:58 +08:00
|
|
|
@IBAction func actionImportBunchJsonFile(_ sender: NSMenuItem) {
|
|
|
|
ConfigFileFactory.importConfigFile()
|
|
|
|
}
|
2018-08-04 16:30:10 +08:00
|
|
|
@IBAction func actionSwitchProxyMode(_ sender: NSMenuItem) {
|
|
|
|
let mode:ClashProxyMode
|
|
|
|
switch sender {
|
|
|
|
case proxyModeGlobalMenuItem:
|
|
|
|
mode = .global
|
|
|
|
case proxyModeDirectMenuItem:
|
|
|
|
mode = .direct
|
|
|
|
case proxyModeRuleMenuItem:
|
|
|
|
mode = .rule
|
|
|
|
default:
|
|
|
|
return
|
|
|
|
}
|
|
|
|
let config = ConfigManager.shared.currentConfig?.copy()
|
|
|
|
config?.mode = mode
|
2018-08-11 14:02:34 +08:00
|
|
|
ApiRequest.updateOutBoundMode(mode: mode) { (success) in
|
|
|
|
ConfigManager.shared.currentConfig = config
|
|
|
|
ConfigManager.selectOutBoundMode = mode
|
2018-08-04 16:30:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-26 13:25:29 +08:00
|
|
|
@IBAction func actionImportConfigFromSSURL(_ sender: NSMenuItem) {
|
|
|
|
let pasteBoard = NSPasteboard.general.string(forType: NSPasteboard.PasteboardType.string)
|
|
|
|
if let proxyModel = ProxyServerModel(urlStr: pasteBoard ?? "") {
|
|
|
|
ConfigFileFactory.addProxyToConfig(proxy: proxyModel)
|
|
|
|
} else {
|
|
|
|
NSUserNotificationCenter.default.postImportConfigFromUrlFailNotice(urlStr: pasteBoard ?? "empty")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@IBAction func actionScanQRCode(_ sender: NSMenuItem) {
|
|
|
|
if let urls = QRCodeUtil.ScanQRCodeOnScreen() {
|
|
|
|
for url in urls {
|
|
|
|
if let proxyModel = ProxyServerModel(urlStr: url) {
|
|
|
|
ConfigFileFactory.addProxyToConfig(proxy: proxyModel)
|
|
|
|
} else {
|
|
|
|
NSUserNotificationCenter
|
|
|
|
.default
|
|
|
|
.postImportConfigFromUrlFailNotice(urlStr: url)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else {
|
|
|
|
NSUserNotificationCenter.default.postQRCodeNotFoundNotice()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-05 01:17:27 +08:00
|
|
|
@IBAction func actionShowNetSpeedIndicator(_ sender: NSMenuItem) {
|
|
|
|
ConfigManager.shared.showNetSpeedIndicator = !ConfigManager.shared.showNetSpeedIndicator
|
|
|
|
}
|
2018-08-07 23:44:30 +08:00
|
|
|
|
|
|
|
@IBAction func actionShowLog(_ sender: Any) {
|
|
|
|
NSWorkspace.shared.openFile(Logger.shared.logFilePath())
|
|
|
|
|
|
|
|
}
|
2018-06-13 10:44:30 +08:00
|
|
|
}
|
|
|
|
|
2018-06-14 12:56:07 +08:00
|
|
|
|