2018-06-13 10:44:30 +08:00
|
|
|
//
|
|
|
|
// AppDelegate.swift
|
|
|
|
// ClashX
|
|
|
|
//
|
|
|
|
// Created by 称一称 on 2018/6/10.
|
|
|
|
// Copyright © 2018年 west2online. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
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!
|
2018-06-23 20:17:05 +08:00
|
|
|
static let StatusItemIconWidth: CGFloat = NSStatusItem.variableLength * 2
|
2018-06-13 10:44:30 +08:00
|
|
|
|
|
|
|
@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!
|
|
|
|
var disposeBag = DisposeBag()
|
2018-06-13 10:44:30 +08:00
|
|
|
let ssQueue = DispatchQueue(label: "com.w2fzu.ssqueue", attributes: .concurrent)
|
|
|
|
|
2018-06-23 20:17:05 +08:00
|
|
|
|
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-03 16:49:40 +08:00
|
|
|
|
2018-06-13 10:44:30 +08:00
|
|
|
_ = ProxyConfigManager.install()
|
2018-07-30 13:35:18 +08:00
|
|
|
PFMoveToApplicationsFolderIfNecessary()
|
2018-08-03 16:49:40 +08:00
|
|
|
self.startProxy()
|
2018-07-30 13:35:18 +08:00
|
|
|
|
2018-06-23 20:17:05 +08:00
|
|
|
statusItem = NSStatusBar.system.statusItem(withLength: 57)
|
|
|
|
let view = StatusItemView.create(statusItem: statusItem,statusMenu: statusMenu)
|
|
|
|
statusItem.view = view
|
2018-08-04 16:30:10 +08:00
|
|
|
setupData()
|
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() {
|
|
|
|
NotificationCenter.default.rx.notification(kShouldUpDateConfig).bind {
|
|
|
|
[unowned self] (note) in
|
|
|
|
self.syncConfig(){
|
|
|
|
self.resetTrafficMonitor()
|
|
|
|
}
|
|
|
|
}.disposed(by: disposeBag)
|
|
|
|
|
|
|
|
ConfigManager.shared.proxyPortAutoSetObservable
|
|
|
|
.distinctUntilChanged()
|
|
|
|
.bind{ [unowned self]
|
|
|
|
enable in
|
|
|
|
self.proxySettingMenuItem.state = (enable ?? false) ? .on : .off
|
|
|
|
let image = (enable ?? false) ?
|
|
|
|
NSImage(named: NSImage.Name(rawValue: "menu_icon"))! :
|
|
|
|
NSImage(named: NSImage.Name(rawValue: "menu_icon_disabled"))!
|
|
|
|
((self.statusItem.view) as! StatusItemView).imageView.image = image
|
|
|
|
}.disposed(by: disposeBag)
|
|
|
|
|
|
|
|
ConfigManager.shared.currentConfigVariable
|
|
|
|
.asObservable()
|
|
|
|
.filter{$0 != nil}
|
|
|
|
.bind {[unowned self] (config) in
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}.disposed(by: disposeBag)
|
2018-06-14 16:16:00 +08:00
|
|
|
|
2018-08-04 16:30:10 +08:00
|
|
|
LaunchAtLogin.shared.isEnableVirable
|
|
|
|
.asObservable()
|
|
|
|
.subscribe(onNext: { (enable) in
|
|
|
|
self.autoStartMenuItem.state = enable ? .on : .off
|
|
|
|
}).disposed(by: disposeBag)
|
2018-06-13 10:44:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func startProxy() {
|
|
|
|
ssQueue.async {
|
|
|
|
run()
|
|
|
|
}
|
2018-08-04 16:30:10 +08:00
|
|
|
syncConfig(){
|
|
|
|
self.resetTrafficMonitor()
|
|
|
|
}
|
2018-08-04 14:33:47 +08:00
|
|
|
}
|
|
|
|
|
2018-08-04 16:30:10 +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-04 14:33:47 +08:00
|
|
|
|
2018-08-04 16:30:10 +08:00
|
|
|
if ConfigManager.shared.proxyPortAutoSet {
|
|
|
|
_ = ProxyConfigManager.setUpSystemProxy(port: config.port,socksPort: config.socketPort)
|
|
|
|
completeHandler?()
|
2018-07-30 15:55:10 +08:00
|
|
|
}
|
2018-06-23 21:43:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-04 16:30:10 +08:00
|
|
|
func resetTrafficMonitor() {
|
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-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-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) {
|
|
|
|
let ctrl = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"), bundle: nil)
|
|
|
|
.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "sampleConfigGenerator")) as! NSWindowController
|
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) {
|
|
|
|
let path = (NSHomeDirectory() as NSString).appendingPathComponent("/.config/clash/config.ini")
|
|
|
|
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-04 16:30:10 +08:00
|
|
|
ApiRequest.requestConfigUpdate() { [unowned self] success in
|
|
|
|
self.syncConfig(){
|
|
|
|
self.resetTrafficMonitor()
|
|
|
|
}
|
2018-06-13 10:44:30 +08:00
|
|
|
}
|
|
|
|
}
|
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
|
|
|
|
ApiRequest.requestUpdateConfig(newConfig: config) { (success) in
|
|
|
|
if (success) {
|
|
|
|
ConfigManager.shared.currentConfig = config
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-06-13 10:44:30 +08:00
|
|
|
}
|
|
|
|
|
2018-06-14 12:56:07 +08:00
|
|
|
|