diff --git a/SrunBar/AboutWindow.swift b/SrunBar/AboutWindow.swift index 816e5c4..bbfb1a9 100644 --- a/SrunBar/AboutWindow.swift +++ b/SrunBar/AboutWindow.swift @@ -12,19 +12,21 @@ class AboutWindow: NSWindowController, NSWindowDelegate { @IBOutlet weak var versionLabel: NSTextField! - let version = "v0.2.8" + let version = UserDefaults.standard.string(forKey: "version") ?? "" + let link = "https://github.com/vouv/SrunBar" override var windowNibName : String! { "AboutWindow" } override func windowDidLoad() { super.windowDidLoad() - self.versionLabel?.stringValue = "SrunBar " + version + debugPrint("load about") + versionLabel?.stringValue = "SrunBar " + version self.window?.center() self.window?.makeKeyAndOrderFront(nil) NSApp.activate(ignoringOtherApps: true) } - + @IBAction func linkClicked(_ sender: NSButtonCell) { let url = URL(string: link) NSWorkspace.shared.open(url!) diff --git a/SrunBar/AppDelegate.swift b/SrunBar/AppDelegate.swift index e653d1a..84c9e74 100644 --- a/SrunBar/AppDelegate.swift +++ b/SrunBar/AppDelegate.swift @@ -11,13 +11,14 @@ import Cocoa @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { + let version = "v0.3.0" + func applicationDidFinishLaunching(_ aNotification: Notification) { // Insert code here to initialize your application // check update // 每天执行一次更新 -// let al = NSAlert.init(); -// al.messageText = "update!" -// al.runModal() + let def = UserDefaults.standard + def.set(version, forKey: "version") } func applicationWillTerminate(_ aNotification: Notification) { diff --git a/SrunBar/Base.lproj/MainMenu.xib b/SrunBar/Base.lproj/MainMenu.xib index 6476e6a..4d55dc0 100644 --- a/SrunBar/Base.lproj/MainMenu.xib +++ b/SrunBar/Base.lproj/MainMenu.xib @@ -17,17 +17,22 @@ - - + - + + + + + + + - + @@ -252,4 +257,7 @@ + + + diff --git a/SrunBar/StatusMenuController.swift b/SrunBar/StatusMenuController.swift index 6a6c22c..0a5bbf6 100644 --- a/SrunBar/StatusMenuController.swift +++ b/SrunBar/StatusMenuController.swift @@ -8,6 +8,13 @@ import Cocoa +enum SrunStatus : Int { + case connected = 1 + case unKnown = 2 + case ready = 3 +} + + class StatusMenuController: NSObject, NSMenuDelegate { @IBOutlet weak var statusMenu: NSMenu! @IBOutlet weak var infoView: InfoView! @@ -18,9 +25,10 @@ class StatusMenuController: NSObject, NSMenuDelegate { var aboutWindow: AboutWindow! var updateWindow: UpdateWindow! - @IBOutlet weak var loginItem: NSMenuItem! - - @IBOutlet weak var aboutItem: NSMenuItem! + @IBOutlet weak var statusMenuItem: NSMenuItem! +// @IBOutlet weak var loginItem: NSMenuItem! +// +// @IBOutlet weak var aboutItem: NSMenuItem! var statusIcon: NSImage? { let icon = NSImage(named: "statusIcon") @@ -32,6 +40,18 @@ class StatusMenuController: NSObject, NSMenuDelegate { let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) let srun = SrunAPI() + var srunStatus = SrunStatus.connected + let srunStatusText = [ + SrunStatus.connected: "已联网", + SrunStatus.ready: "未登录", + SrunStatus.unKnown: "未知网络", + ] + let srunStatusImage = [ + SrunStatus.connected: NSImage(named: "NSStatusAvailable")!, + SrunStatus.ready: NSImage(named: "NSStatusPartiallyAvailable")!, + SrunStatus.unKnown: NSImage(named: "NSStatusNone")!, + ] + override func awakeFromNib() { statusItem.menu = statusMenu // 监听显示事件 @@ -61,7 +81,7 @@ class StatusMenuController: NSObject, NSMenuDelegate { self.doInfo() } } - + func doLogin() { let defaults = UserDefaults.standard guard let username = defaults.string(forKey: "username") else { @@ -97,8 +117,12 @@ class StatusMenuController: NSObject, NSMenuDelegate { srun.logout(username: username) { (err) in if let err = err { self.notify(title: "注销失败", subtitle: err.localizedDescription) + self.setSrunStatus(.unKnown) + }else { self.notify(title: "注销成功", subtitle: "账号\(username)") + self.setSrunStatus(.ready) + return } } } @@ -113,12 +137,28 @@ class StatusMenuController: NSObject, NSMenuDelegate { } srun.info(username: username, password: password) { (res, error) in if error != nil { - return + }else if let info = res { - DispatchQueue.main.async { - self.infoView.update(info) + // 如未登录,返回数据为空 + if info.user_name == username { + DispatchQueue.main.async { + self.setSrunStatus(.connected) + self.infoView.update(info) + } + }else { + self.setSrunStatus(.ready) } + return } + self.setSrunStatus(.unKnown) + } + } + + func setSrunStatus(_ status: SrunStatus) { + DispatchQueue.main.async { + self.srunStatus = status + self.statusMenuItem.title = self.srunStatusText[self.srunStatus] ?? "" + self.statusMenuItem.image = self.srunStatusImage[self.srunStatus] } } diff --git a/SrunBar/UpdateWindow.swift b/SrunBar/UpdateWindow.swift index 8a7733e..b18e9c5 100644 --- a/SrunBar/UpdateWindow.swift +++ b/SrunBar/UpdateWindow.swift @@ -14,16 +14,137 @@ class UpdateWindow: NSWindowController, NSWindowDelegate { override var windowNibName : String! { "UpdateWindow" } + var task : URLSessionTask! + + let titleNewVersion = "发现新版本" + let titleUpdateError = "更新错误" + let titleUpToDate = "无需更新" + + override func windowDidLoad() { super.windowDidLoad() self.window?.center() self.window?.makeKeyAndOrderFront(nil) NSApp.activate(ignoringOtherApps: true) self.progressBar.startAnimation(nil) + } + override func showWindow(_ sender: Any?) { + super.showWindow(sender) + self.task = self.requestTask() + DispatchQueue.global().async { + self.task.resume() + } + } + + func requestTask() -> URLSessionTask { + let timeout = TimeInterval.init(10) + let dst = "https://github.com/vouv/SrunBar/releases/latest" + + let addr = URLComponents(string: dst)! + var urlRequest = URLRequest(url: addr.url!) + urlRequest.httpMethod = "GET" + + let config = URLSessionConfiguration.default + config.timeoutIntervalForRequest = timeout + let session = URLSession(configuration: config) + let task = session.dataTask( + with: urlRequest, + completionHandler: { (data, response, error) in + DispatchQueue.main.async { + self.window?.close() + } + var errInfo = "" + if let error = error { + errInfo = error.localizedDescription + }else if let response = response { + let target = response.url?.absoluteString ?? "" + + let base = "https://github.com/vouv/SrunBar/releases/tag/" + if target.contains(base) { + let startIndex = target.index(target.startIndex, offsetBy: base.count) + let newVersion = String(target[startIndex.. String { + let def = UserDefaults.standard + return def.string(forKey: "version") ?? "" + } + + func compareVersion(current:String, remote:String) -> Bool { + // 先去掉v + let nowVersion = String(current[current.index(current.startIndex, offsetBy: 1).. newArray.count ? newArray.count : nowArray.count + for index in 0...big - 1 { + let first = nowArray[index] + let second = newArray[index] + if Int(first)! < Int(second)! { + return true + } + } + return false } + @objc func stopModal(_ sender: NSButton) { + NSApp.stopModal() + } + + @objc func openVersionUrl(_ sender: NSButton) { + // 关闭弹窗 + NSApp.stopModal() + + let link = "https://github.com/vouv/SrunBar/releases/latest" + + let url = URL(string: link) + DispatchQueue.global().async { + NSWorkspace.shared.open(url!) + } + } } diff --git a/SrunBar/srun/SrunAPI.swift b/SrunBar/srun/SrunAPI.swift index 0dd9502..b3851fd 100644 --- a/SrunBar/srun/SrunAPI.swift +++ b/SrunBar/srun/SrunAPI.swift @@ -8,6 +8,9 @@ import Cocoa +enum SrunError : Error { + case RequestError +} class SrunAPI { @@ -17,6 +20,8 @@ class SrunAPI { let InfoUrl = "/cgi-bin/rad_user_info" let hash = Hash() + + let timeout = TimeInterval.init(2) func login(username: String, password: String, handle: @escaping (RespLogin?, Error?) -> Void) { let (acid, err) = getAcid() @@ -25,8 +30,8 @@ class SrunAPI { return } - let (respChallenge, errc) = self.getChallenge(username: username) - if let err = errc { + let (respChallenge, errChallenge) = getChallenge(username: username) + if let err = errChallenge { handle(nil, err) return } @@ -158,7 +163,7 @@ class SrunAPI { private func getAcid() -> (Int, Error?) { let config = URLSessionConfiguration.default - config.timeoutIntervalForRequest = TimeInterval.init(3) + config.timeoutIntervalForRequest = self.timeout let session = URLSession(configuration: config) let semaphore = DispatchSemaphore.init(value: 0) @@ -215,7 +220,7 @@ class SrunAPI { urlRequest.httpMethod = "GET" let config = URLSessionConfiguration.default - config.timeoutIntervalForRequest = TimeInterval.init(3) + config.timeoutIntervalForRequest = timeout let session = URLSession(configuration: config) let task = session.dataTask( with: urlRequest, @@ -228,6 +233,10 @@ class SrunAPI { let body = String(data: data!, encoding: String.Encoding.utf8)! + if body.count < queryCallback.count { + handle(nil, SrunError.RequestError) + return + } let startIndex = body.index(body.startIndex, offsetBy: queryCallback.count+1) let endIndex = body.index(body.endIndex, offsetBy: -1)