diff --git a/ShadowsocksX-NG.xcodeproj/project.pbxproj b/ShadowsocksX-NG.xcodeproj/project.pbxproj index e97493d..d1c261c 100644 --- a/ShadowsocksX-NG.xcodeproj/project.pbxproj +++ b/ShadowsocksX-NG.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 0880CE401D6FE6D900BD39E2 /* example-gui-config.json in Resources */ = {isa = PBXBuildFile; fileRef = 0880CE3F1D6FE6D900BD39E2 /* example-gui-config.json */; }; 088EC3971D5F5B8600E40791 /* whitelist.pac in Resources */ = {isa = PBXBuildFile; fileRef = 088EC3961D5F5B8600E40791 /* whitelist.pac */; }; 088EC3991D5F5BA300E40791 /* whiteiplist.pac in Resources */ = {isa = PBXBuildFile; fileRef = 088EC3981D5F5BA300E40791 /* whiteiplist.pac */; }; + 08BDBB481E2361BD00C4BBC2 /* VersionChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08BDBB471E2361BD00C4BBC2 /* VersionChecker.swift */; }; 258E511BA910B0521B24DAB8 /* Pods_ShadowsocksX_NG.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 283ED1A8E9B711AC65670031 /* Pods_ShadowsocksX_NG.framework */; }; 9B07EFA71D048BBB0052D9DF /* ss-local in Resources */ = {isa = PBXBuildFile; fileRef = 9B07EFA61D048BBB0052D9DF /* ss-local */; }; 9B07EFAC1D048E880052D9DF /* menu_icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9B07EFA81D048E880052D9DF /* menu_icon@2x.png */; }; @@ -114,6 +115,7 @@ 088EC3961D5F5B8600E40791 /* whitelist.pac */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = whitelist.pac; sourceTree = ""; }; 088EC3981D5F5BA300E40791 /* whiteiplist.pac */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = whiteiplist.pac; sourceTree = ""; }; 08AF56C01D6AFA7C00DC4F46 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/PreferencesWindowController.strings"; sourceTree = ""; }; + 08BDBB471E2361BD00C4BBC2 /* VersionChecker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionChecker.swift; sourceTree = ""; }; 19083CFCED87354F006967FF /* Pods_ShadowsocksX_NGUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ShadowsocksX_NGUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 1E7783AEDB4A3BDDC9FF16AC /* libPods-proxy_conf_helper.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-proxy_conf_helper.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 283ED1A8E9B711AC65670031 /* Pods_ShadowsocksX_NG.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ShadowsocksX_NG.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -322,6 +324,7 @@ 9B0BFFEF1D0460A70040E62B /* Info.plist */, 9BEEF06D1D04DCE400FC52B3 /* ServerProfile.swift */, 9BEEF06F1D04DDB100FC52B3 /* ServerProfileManager.swift */, + 08BDBB471E2361BD00C4BBC2 /* VersionChecker.swift */, 083BF8381D82759600831C68 /* StatusItemView.swift */, 083BF83A1D8275A800831C68 /* SystemThemeChangeHelper.swift */, 9BEEF0771D04FE8A00FC52B3 /* LaunchAgentUtils.swift */, @@ -688,6 +691,7 @@ 08805F191D878CA5009B53E7 /* PingTest.swift in Sources */, 9B3FFF1E1D0732660019A709 /* Utils.m in Sources */, 9B3FFF321D08CEE40019A709 /* SWBQRCodeWindowController.m in Sources */, + 08BDBB481E2361BD00C4BBC2 /* VersionChecker.swift in Sources */, 083BF8371D82742200831C68 /* PingClient.swift in Sources */, 083BF8361D82742200831C68 /* NetWorkMonitor.swift in Sources */, 083BF8331D82731900831C68 /* SimplePing.m in Sources */, diff --git a/ShadowsocksX-NG/AppDelegate.swift b/ShadowsocksX-NG/AppDelegate.swift index 3d71dda..ae38148 100644 --- a/ShadowsocksX-NG/AppDelegate.swift +++ b/ShadowsocksX-NG/AppDelegate.swift @@ -48,6 +48,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele @IBOutlet weak var lanchAtLoginMenuItem: NSMenuItem! @IBOutlet weak var connectAtLaunchMenuItem: NSMenuItem! @IBOutlet weak var ShowNetworkSpeedItem: NSMenuItem! + @IBOutlet weak var checkUpdateMenuItem: NSMenuItem! // MARK: Variables var statusItemView:StatusItemView! @@ -206,6 +207,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele if defaults.bool(forKey: "ConnectAtLaunch") { toggleRunning(toggleRunningMenuItem) } + // Version Check! + checkForUpdate(mustShowAlert: false) } func applicationWillTerminate(_ aNotification: Notification) { @@ -468,6 +471,10 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele NSWorkspace.shared().open(URL(string: "https://github.com/qinyuhang/ShadowsocksX-NG/issues")!) } + @IBAction func checkForUpdate(_ sender: NSMenuItem) { + checkForUpdate(mustShowAlert: true) + } + @IBAction func showAbout(_ sender: NSMenuItem) { NSApp.orderFrontStandardAboutPanel(sender); NSApp.activate(ignoringOtherApps: true) @@ -720,6 +727,14 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele // } } + func checkForUpdate(mustShowAlert: Bool) -> Void { + DispatchQueue.global().async { + DispatchQueue.main.async { + _ = VersionChecker().checkNewVersion(showAlert: mustShowAlert) + } + } + } + // MARK: func handleURLEvent(_ event: NSAppleEventDescriptor, withReplyEvent replyEvent: NSAppleEventDescriptor) { diff --git a/ShadowsocksX-NG/Base.lproj/MainMenu.xib b/ShadowsocksX-NG/Base.lproj/MainMenu.xib index cf0386b..1099b6a 100644 --- a/ShadowsocksX-NG/Base.lproj/MainMenu.xib +++ b/ShadowsocksX-NG/Base.lproj/MainMenu.xib @@ -1,8 +1,8 @@ - + - + @@ -17,6 +17,7 @@ + @@ -214,6 +215,12 @@ + + + + + + diff --git a/ShadowsocksX-NG/Base.lproj/PreferencesWindowController.xib b/ShadowsocksX-NG/Base.lproj/PreferencesWindowController.xib index 59e89a2..e7fef5f 100644 --- a/ShadowsocksX-NG/Base.lproj/PreferencesWindowController.xib +++ b/ShadowsocksX-NG/Base.lproj/PreferencesWindowController.xib @@ -293,7 +293,7 @@ - + @@ -309,7 +309,7 @@ - + @@ -331,7 +331,7 @@ - + diff --git a/ShadowsocksX-NG/Info.plist b/ShadowsocksX-NG/Info.plist index 3d458f0..1db9b24 100644 --- a/ShadowsocksX-NG/Info.plist +++ b/ShadowsocksX-NG/Info.plist @@ -48,7 +48,7 @@ CFBundleVersion - 2 + 3 LSApplicationCategoryType public.app-category.utilities LSMinimumSystemVersion diff --git a/ShadowsocksX-NG/VersionChecker.swift b/ShadowsocksX-NG/VersionChecker.swift new file mode 100644 index 0000000..b0b7a32 --- /dev/null +++ b/ShadowsocksX-NG/VersionChecker.swift @@ -0,0 +1,95 @@ +// +// VersionChecker.swift +// ShadowsocksX-NG +// +// Created by 秦宇航 on 2017/1/9. +// Copyright © 2017年 qinyuhang. All rights reserved. +// + +import Foundation + +let _VERSION_XML_URL = "https://raw.githubusercontent.com/shadowsocksr/ShadowsocksX-NG/develop/ShadowsocksX-NG/Info.plist" +let _VERSION_XML_LOCAL:String = Bundle.main.bundlePath + "/Contents/Info.plist" + +class VersionChecker: NSObject { + var haveNewVersion: Bool = false + enum versionError: Error { + case CanNotGetOnlineData + } + func saveFile(fromURL: String, toPath: String, withName: String) -> Bool { + let manager = FileManager.default + let url = URL(string:fromURL)! + do { + let st = try String(contentsOf: url, encoding: String.Encoding.utf8) + print(st) + let data = st.data(using: String.Encoding.utf8) + manager.createFile( atPath: toPath + withName , contents: data, attributes: nil) + return true + + } catch { + print(error) + return false + } + } + func checkNewVersion(showAlert: Bool) -> Bool { + + func getOnlineData() throws -> NSDictionary{ + guard NSDictionary(contentsOf: URL(string:_VERSION_XML_URL)!) != nil else { + throw versionError.CanNotGetOnlineData + } + return NSDictionary(contentsOf: URL(string:_VERSION_XML_URL)!)! + } + + func showAlertView(Title: String, SubTitle: String, ConfirmBtn: String, CancelBtn: String) -> Int { + let alertView = NSAlert() + alertView.messageText = Title + alertView.informativeText = SubTitle + alertView.addButton(withTitle: ConfirmBtn) + if CancelBtn != "" { + alertView.addButton(withTitle: CancelBtn) + } + let action = alertView.runModal() + return action + } + + var localData: NSDictionary = NSDictionary() + var onlineData: NSDictionary = NSDictionary() + + localData = NSDictionary(contentsOfFile: _VERSION_XML_LOCAL)! + do{ + try onlineData = getOnlineData() + }catch{ + _ = showAlertView(Title: "网络错误", SubTitle: "由于网络错误无法检查更新", ConfirmBtn: "确认", CancelBtn: "") + return false + } + if (onlineData["CFBundleShortVersionString"] as! String == localData["CFBundleShortVersionString"] as! String && onlineData["CFBundleVersion"] as! String == localData["CFBundleVersion"] as! String){ + if showAlert { + let currentVersionString:String = localData["CFBundleShortVersionString"] as! String + let currentBuildString:String = localData["CFBundleVersion"] as! String + _ = showAlertView(Title: "已是最新版本!", SubTitle: "当前版本 " + currentVersionString + " build " + currentBuildString, ConfirmBtn: "确认", CancelBtn: "") + } + return false + } + else{ + haveNewVersion = true + // 弹窗提示有软件更新 + let versionString:String = onlineData["CFBundleShortVersionString"] as! String + let buildString:String = onlineData["CFBundleVersion"] as! String + let currentVersionString:String = localData["CFBundleShortVersionString"] as! String + let currentBuildString:String = localData["CFBundleVersion"] as! String + let action = showAlertView(Title: "软件有更新!", SubTitle: "新版本为 " + versionString + " build " + buildString + "\n" + "当前版本 " + currentVersionString + " build " + currentBuildString, ConfirmBtn: "前往下载", CancelBtn: "取消") + switch action { + case 1000: + // go to download + NSWorkspace.shared().open(URL(string: "https://github.com/shadowsocksr/ShadowsocksX-NG/releases")!) + break + case 1001: + // cancel + break + default: + break + } + return true + } + } +} diff --git a/ShadowsocksX-NG/ss-local b/ShadowsocksX-NG/ss-local index a9ff3a1..8dc5d41 100755 Binary files a/ShadowsocksX-NG/ss-local and b/ShadowsocksX-NG/ss-local differ diff --git a/ShadowsocksX-NG/zh-Hans.lproj/MainMenu.strings b/ShadowsocksX-NG/zh-Hans.lproj/MainMenu.strings index 6786c61..b8b1a16 100644 --- a/ShadowsocksX-NG/zh-Hans.lproj/MainMenu.strings +++ b/ShadowsocksX-NG/zh-Hans.lproj/MainMenu.strings @@ -100,3 +100,5 @@ /* Class = "NSMenuItem"; title = "HTTP Proxy Preference ..."; ObjectID = "uEp-Gz-cu0"; */ "uEp-Gz-cu0.title" = "HTTP代理设置..."; + +"wyZ-4G-qg9.title" = "检查更新"; diff --git a/ShadowsocksX-NG/zh-Hans.lproj/PreferencesWindowController.strings b/ShadowsocksX-NG/zh-Hans.lproj/PreferencesWindowController.strings index 04d1783..aa2937f 100644 --- a/ShadowsocksX-NG/zh-Hans.lproj/PreferencesWindowController.strings +++ b/ShadowsocksX-NG/zh-Hans.lproj/PreferencesWindowController.strings @@ -62,5 +62,5 @@ /* Class = "NSTextFieldCell"; title = "obfs-param:"; ObjectID = "aQv-HP-iKY"; */ "aQv-HP-iKY.title" = "混淆参数:"; /**/ -"j0N-8s-9Z3.title" = "分组:" +"j0N-8s-9Z3.title" = "分组:";