ClashX.Meta/ClashX/AppDelegate.swift

245 lines
8.4 KiB
Swift
Raw Normal View History

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
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-13 10:44:30 +08:00
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var statusItem: NSStatusItem!
@IBOutlet weak var statusMenu: NSMenu!
@IBOutlet weak var proxySettingMenuItem: NSMenuItem!
@IBOutlet weak var autoStartMenuItem: NSMenuItem!
2018-06-13 10:44:30 +08:00
@IBOutlet weak var proxyModeGlobalMenuItem: NSMenuItem!
@IBOutlet weak var proxyModeDirectMenuItem: NSMenuItem!
@IBOutlet weak var proxyModeRuleMenuItem: NSMenuItem!
2018-08-04 21:49:32 +08:00
@IBOutlet weak var showNetSpeedIndicatorMenuItem: NSMenuItem!
2018-08-04 21:49:32 +08:00
@IBOutlet weak var separatorLineTop: NSMenuItem!
@IBOutlet weak var sepatatorLineEndProxySelect: NSMenuItem!
2018-08-04 21:49:32 +08:00
var disposeBag = DisposeBag()
2018-06-13 10:44:30 +08:00
let ssQueue = DispatchQueue(label: "com.w2fzu.ssqueue", attributes: .concurrent)
var statusItemView:StatusItemView!
2018-06-23 20:17:05 +08:00
2018-06-13 10:44:30 +08:00
func applicationDidFinishLaunching(_ aNotification: Notification) {
signal(SIGPIPE, SIG_IGN)
2018-06-13 10:44:30 +08:00
_ = ProxyConfigManager.install()
PFMoveToApplicationsFolderIfNecessary()
self.startProxy()
statusItemView = StatusItemView.create(statusItem: nil,statusMenu: statusMenu)
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) {
if ConfigManager.shared.proxyPortAutoSet {
2018-06-13 10:44:30 +08:00
_ = ProxyConfigManager.setUpSystemProxy(port: nil,socksPort: nil)
}
}
func setupData() {
NotificationCenter.default.rx.notification(kShouldUpDateConfig).bind {
[unowned self] (note) in
self.syncConfig(){
self.resetTrafficMonitor()
}
}.disposed(by: disposeBag)
ConfigManager.shared
.showNetSpeedIndicatorObservable
.bind {[unowned self] (show) in
self.showNetSpeedIndicatorMenuItem.state = (show!) ? .on : .off
self.statusItem = NSStatusBar.system.statusItem(withLength: show! ? 57 : 22)
self.statusItem.view = self.statusItemView
self.statusItemView.showSpeedContainer(show: show!)
self.statusItemView.statusItem = self.statusItem
}.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
}
self.updateProxyList()
}.disposed(by: disposeBag)
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 updateProxyList() {
2018-08-04 21:49:32 +08:00
ProxyMenuItemFactory.menuItems { [unowned self] (menus) in
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
for idx in startIndex ..< endIndex {
items.remove(at: idx)
}
2018-08-04 21:49:32 +08:00
for each in menus {
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-06-13 10:44:30 +08:00
func startProxy() {
ssQueue.async {
run()
}
syncConfig(){
self.resetTrafficMonitor()
}
2018-08-04 14:33:47 +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}
ConfigManager.shared.currentConfig = config
2018-08-04 14:33:47 +08:00
if ConfigManager.shared.proxyPortAutoSet {
_ = ProxyConfigManager.setUpSystemProxy(port: config.port,socksPort: config.socketPort)
self.updateProxyList()
completeHandler?()
2018-07-30 15:55:10 +08:00
}
2018-06-23 21:43:33 +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 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) {
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()
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
}
@IBAction func actionStartAtLogin(_ sender: NSMenuItem) {
LaunchAtLogin.shared.isEnabled = !LaunchAtLogin.shared.isEnabled
}
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
genConfigWindow?.close()
genConfigWindow=ctrl
2018-06-23 14:27:04 +08:00
ctrl.window?.title = ctrl.contentViewController?.title ?? ""
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-06-13 10:44:30 +08:00
@IBAction func actionUpdateConfig(_ sender: Any) {
ApiRequest.requestConfigUpdate() { [unowned self] success in
self.syncConfig(){
self.resetTrafficMonitor()
}
2018-06-13 10:44:30 +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
}
}
}
@IBAction func actionShowNetSpeedIndicator(_ sender: NSMenuItem) {
ConfigManager.shared.showNetSpeedIndicator = !ConfigManager.shared.showNetSpeedIndicator
}
2018-06-13 10:44:30 +08:00
}