diff --git a/V2rayU/AppDelegate.swift b/V2rayU/AppDelegate.swift index e34a016..6e46ea5 100644 --- a/V2rayU/AppDelegate.swift +++ b/V2rayU/AppDelegate.swift @@ -18,8 +18,6 @@ class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ aNotification: Notification) { - NSAppleEventManager.shared().setEventHandler(self, andSelector: #selector(self.handleAppleEvent(event:replyEvent:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL)) - // Insert code here to initialize your application let startedAtLogin = NSWorkspace.shared.runningApplications.contains { $0.bundleIdentifier == launcherAppIdentifier @@ -40,6 +38,12 @@ class AppDelegate: NSObject, NSApplicationDelegate { // check version V2rayUpdater.checkForUpdatesInBackground() } + + // wake and sleep + NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(onWakeNote(note:)), name: NSWorkspace.willSleepNotification, object: nil) + NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(onSleepNote(note:)), name: NSWorkspace.didWakeNotification, object: nil) + // url scheme + NSAppleEventManager.shared().setEventHandler(self, andSelector: #selector(self.handleAppleEvent(event:replyEvent:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL)) } func checkDefault() { @@ -69,8 +73,17 @@ class AppDelegate: NSObject, NSApplicationDelegate { } let appleEventURL = URL(string: appleEventURLString) + // todo + } - print("Received Apple Event URL: \(appleEventURL)") + @objc func onWakeNote(note: NSNotification) { + if UserDefaults.getBool(forKey: .v2rayTurnOn) { + V2rayLaunch.Start() + } + } + + @objc func onSleepNote(note: NSNotification) { + V2rayLaunch.Stop() } func applicationWillTerminate(_ aNotification: Notification) { diff --git a/V2rayU/Base.lproj/ConfigWindow.xib b/V2rayU/Base.lproj/ConfigWindow.xib index 683d483..aed9425 100644 --- a/V2rayU/Base.lproj/ConfigWindow.xib +++ b/V2rayU/Base.lproj/ConfigWindow.xib @@ -80,7 +80,6 @@ - @@ -175,7 +174,7 @@ Gw - + @@ -267,20 +266,11 @@ Gw - - - - - - - - - - + @@ -1582,6 +1572,15 @@ Gw + + + + + + + + + diff --git a/V2rayU/Base.lproj/QrcodeWindow.xib b/V2rayU/Base.lproj/QrcodeWindow.xib index feac95e..07499e2 100644 --- a/V2rayU/Base.lproj/QrcodeWindow.xib +++ b/V2rayU/Base.lproj/QrcodeWindow.xib @@ -16,8 +16,7 @@ - - + diff --git a/V2rayU/ConfigWindow.swift b/V2rayU/ConfigWindow.swift index 595e745..b7b3b0d 100644 --- a/V2rayU/ConfigWindow.swift +++ b/V2rayU/ConfigWindow.swift @@ -417,6 +417,8 @@ class ConfigWindowController: NSWindowController, NSWindowDelegate, NSTabViewDel func loadJsonData(rowIndex: Int) { defer { self.bindDataToView() + // replace current + self.switchToImportView() } // reset @@ -447,9 +449,18 @@ class ConfigWindowController: NSWindowController, NSWindowDelegate, NSTabViewDel // save let errMsg = V2rayServer.save(idx: self.serversTableView.selectedRow, isValid: self.v2rayConfig.isValid, jsonData: text) - self.errTip.stringValue = errMsg - - self.refreshServerList(ok: errMsg.count == 0) + if errMsg.count == 0 { + if self.errTip.stringValue == "" { + self.errTip.stringValue = "save success" + DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { + // your code here + self.errTip.stringValue = "" + } + } + self.refreshServerList(ok: errMsg.count == 0) + } else { + self.errTip.stringValue = errMsg + } } func refreshServerList(ok: Bool = true) { @@ -482,6 +493,8 @@ class ConfigWindowController: NSWindowController, NSWindowDelegate, NSTabViewDel @IBAction func setV2rayLogLevel(_ sender: NSPopUpButton) { if let item = logLevel.selectedItem { UserDefaults.set(forKey: .v2rayLogLevel, value: item.title) + // replace current + self.switchToImportView() // restart service menuController.startV2rayCore() } diff --git a/V2rayU/MainMenu.swift b/V2rayU/MainMenu.swift index 7f10212..1b96556 100644 --- a/V2rayU/MainMenu.swift +++ b/V2rayU/MainMenu.swift @@ -17,7 +17,6 @@ let preferencesWindowController = PreferencesWindowController( PreferenceGeneralViewController(), ] ) -var configWindow = ConfigWindowController() var qrcodeWindow = QrcodeWindowController() // menu controller @@ -25,6 +24,7 @@ class MenuController: NSObject, NSMenuDelegate { var closedByConfigWindow: Bool = false let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) var statusItemClicked: (() -> Void)? + var configWindow: ConfigWindowController! @IBOutlet weak var v2rayRulesMode: NSMenuItem! @IBOutlet weak var globalMode: NSMenuItem! @@ -112,12 +112,12 @@ class MenuController: NSObject, NSMenuDelegate { NSLog("start v2ray-core begin") guard let v2ray = V2rayServer.loadSelectedItem() else { - self.notice(title: "start v2ray fail", subtitle: "", informativeText: "v2ray config not found") + noticeTip(title: "start v2ray fail", subtitle: "", informativeText: "v2ray config not found") return } if !v2ray.isValid { - self.notice(title: "start v2ray fail", subtitle: "", informativeText: "invalid v2ray config") + noticeTip(title: "start v2ray fail", subtitle: "", informativeText: "invalid v2ray config") return } @@ -153,14 +153,6 @@ class MenuController: NSObject, NSMenuDelegate { NSApplication.shared.terminate(self) } - @IBAction func generateQRCode(_ sender: NSMenuItem) { - NSLog("GenerateQRCode") - } - - @IBAction func scanQRCode(_ sender: NSMenuItem) { - NSLog("ScanQRCode") - } - @IBAction func openPreference(_ sender: NSMenuItem) { preferencesWindowController.showWindow() } @@ -188,14 +180,21 @@ class MenuController: NSObject, NSMenuDelegate { // open config window @IBAction func openConfig(_ sender: NSMenuItem) { - // close before - configWindow.close() - // renew - configWindow = ConfigWindowController() + if configWindow != nil { + // close before + if closedByConfigWindow { + configWindow.close() + // renew + configWindow = ConfigWindowController() + } + } else { + // renew + configWindow = ConfigWindowController() + } + // show window - configWindow.showWindow(self) - // center - configWindow.window?.center() + configWindow.showWindow(nil) + configWindow.window?.makeKeyAndOrderFront(self) // show dock icon NSApp.setActivationPolicy(.regular) // bring to front @@ -308,14 +307,14 @@ class MenuController: NSObject, NSMenuDelegate { @IBAction func generateQrcode(_ sender: NSMenuItem) { guard let v2ray = V2rayServer.loadSelectedItem() else { NSLog("v2ray config not found") - self.notice(title: "generate Qrcode fail", subtitle: "", informativeText: "no available servers") + noticeTip(title: "generate Qrcode fail", subtitle: "", informativeText: "no available servers") return } let share = ShareUri() share.qrcode(item: v2ray) if share.error.count > 0 { - self.notice(title: "generate Qrcode fail", subtitle: "", informativeText: share.error) + noticeTip(title: "generate Qrcode fail", subtitle: "", informativeText: share.error) return } @@ -338,7 +337,7 @@ class MenuController: NSObject, NSMenuDelegate { if uri.count > 0 { self.importUri(url: uri) } else { - self.notice(title: "import server fail", subtitle: "", informativeText: "no found qrcode") + noticeTip(title: "import server fail", subtitle: "", informativeText: "no found qrcode") } } @@ -346,7 +345,7 @@ class MenuController: NSObject, NSMenuDelegate { if let uri = NSPasteboard.general.string(forType: .string), uri.count > 0 { self.importUri(url: uri) } else { - self.notice(title: "import server fail", subtitle: "", informativeText: "no found ss:// or vmess:// from Pasteboard") + noticeTip(title: "import server fail", subtitle: "", informativeText: "no found ss:// or vmess:// from Pasteboard") } } @@ -354,12 +353,12 @@ class MenuController: NSObject, NSMenuDelegate { let uri = url.trimmingCharacters(in: .whitespaces) if uri.count == 0 { - self.notice(title: "import server fail", subtitle: "", informativeText: "import error: uri not found") + noticeTip(title: "import server fail", subtitle: "", informativeText: "import error: uri not found") return } if URL(string: uri) == nil { - self.notice(title: "import server fail", subtitle: "", informativeText: "no found ss:// or vmess://") + noticeTip(title: "import server fail", subtitle: "", informativeText: "no found ss:// or vmess://") return } @@ -377,18 +376,7 @@ class MenuController: NSObject, NSMenuDelegate { return } - self.notice(title: "import server fail", subtitle: "", informativeText: "no found ss:// or vmess://") - } - - func notice(title: String = "", subtitle: String = "", informativeText: String = "") { - // 定义NSUserNotification - let userNotification = NSUserNotification() - userNotification.title = title - userNotification.subtitle = subtitle - userNotification.informativeText = informativeText - // 使用NSUserNotificationCenter发送NSUserNotification - let userNotificationCenter = NSUserNotificationCenter.default - userNotificationCenter.scheduleNotification(userNotification) + noticeTip(title: "import server fail", subtitle: "", informativeText: "no found ss:// or vmess://") } func saveServer(importUri: ImportUri) { @@ -398,10 +386,20 @@ class MenuController: NSObject, NSMenuDelegate { // refresh server self.showServers() - self.notice(title: "import server success", subtitle: "", informativeText: importUri.remark) + noticeTip(title: "import server success", subtitle: "", informativeText: importUri.remark) } else { - self.notice(title: "import server fail", subtitle: "", informativeText: importUri.error) + noticeTip(title: "import server fail", subtitle: "", informativeText: importUri.error) } } + func noticeTip(title: String = "", subtitle: String = "", informativeText: String = "") { + // 定义NSUserNotification + let userNotification = NSUserNotification() + userNotification.title = title + userNotification.subtitle = subtitle + userNotification.informativeText = informativeText + // 使用NSUserNotificationCenter发送NSUserNotification + let userNotificationCenter = NSUserNotificationCenter.default + userNotificationCenter.scheduleNotification(userNotification) + } } diff --git a/V2rayU/v2ray/V2rayConfig.swift b/V2rayU/v2ray/V2rayConfig.swift index bd2bcaa..26a8d46 100644 --- a/V2rayU/v2ray/V2rayConfig.swift +++ b/V2rayU/v2ray/V2rayConfig.swift @@ -138,7 +138,7 @@ class V2rayConfig: NSObject { func combineManualData() { // base - self.v2ray.log.loglevel = V2rayLog.logLevel(rawValue: self.logLevel)! + self.v2ray.log.loglevel = V2rayLog.logLevel(rawValue: UserDefaults.get(forKey: .v2rayLogLevel) ?? "info")! self.v2ray.dns.servers = self.dns.components(separatedBy: ",") // ------------------------------------- inbound start --------------------------------------------- var inHttp = V2rayInbound() @@ -1126,8 +1126,8 @@ class V2rayConfig: NSObject { kcpSettings.readBufferSize = steamJson["kcpSettings"]["readBufferSize"].intValue kcpSettings.writeBufferSize = steamJson["kcpSettings"]["writeBufferSize"].intValue // "none" - if KcpSettingsHeaderType.firstIndex(of: steamJson["kcpSettings"]["type"].stringValue) != nil { - kcpSettings.header.type = steamJson["kcpSettings"]["type"].stringValue + if KcpSettingsHeaderType.firstIndex(of: steamJson["kcpSettings"]["header"]["type"].stringValue) != nil { + kcpSettings.header.type = steamJson["kcpSettings"]["header"]["type"].stringValue } stream.kcpSettings = kcpSettings }