diff --git a/ShadowsocksX-NG.xcodeproj/project.pbxproj b/ShadowsocksX-NG.xcodeproj/project.pbxproj index 1d5d472..f0f01bd 100644 --- a/ShadowsocksX-NG.xcodeproj/project.pbxproj +++ b/ShadowsocksX-NG.xcodeproj/project.pbxproj @@ -92,6 +92,7 @@ /* Begin PBXFileReference section */ 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 = ""; }; 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; }; @@ -154,7 +155,6 @@ 9BB706A51D1B982300551F0E /* SWBApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SWBApplication.m; sourceTree = ""; }; 9BB706A61D1B982300551F0E /* SWBApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWBApplication.h; sourceTree = ""; }; 9BE8FBBD1D0B1FB900CAFD01 /* libcrypto.1.0.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libcrypto.1.0.0.dylib; sourceTree = ""; }; - 9BE8FBC11D0B71CF00CAFD01 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/PreferencesWindowController.strings"; sourceTree = ""; }; 9BEEF0651D04CB8500FC52B3 /* install_ss_local.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = install_ss_local.sh; sourceTree = ""; }; 9BEEF0661D04CE8D00FC52B3 /* start_ss_local.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = start_ss_local.sh; sourceTree = ""; }; 9BEEF0671D04CE9A00FC52B3 /* stop_ss_local.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = stop_ss_local.sh; sourceTree = ""; }; @@ -708,7 +708,7 @@ isa = PBXVariantGroup; children = ( 9B2491B51D0ACC3A003BBECC /* Base */, - 9BE8FBC11D0B71CF00CAFD01 /* zh-Hans */, + 08AF56C01D6AFA7C00DC4F46 /* zh-Hans */, ); name = PreferencesWindowController.xib; sourceTree = ""; diff --git a/ShadowsocksX-NG/Base.lproj/PreferencesWindowController.xib b/ShadowsocksX-NG/Base.lproj/PreferencesWindowController.xib index 4a8296f..c3ff705 100644 --- a/ShadowsocksX-NG/Base.lproj/PreferencesWindowController.xib +++ b/ShadowsocksX-NG/Base.lproj/PreferencesWindowController.xib @@ -12,6 +12,7 @@ + @@ -257,24 +258,24 @@ - - + + - - - + + + - - + + @@ -318,6 +319,7 @@ + @@ -335,6 +337,7 @@ + @@ -401,6 +404,16 @@ DQ + diff --git a/ShadowsocksX-NG/PreferencesWindowController.swift b/ShadowsocksX-NG/PreferencesWindowController.swift index ade9abc..fbfcf86 100644 --- a/ShadowsocksX-NG/PreferencesWindowController.swift +++ b/ShadowsocksX-NG/PreferencesWindowController.swift @@ -24,6 +24,7 @@ class PreferencesWindowController: NSWindowController @IBOutlet weak var ObfsTextField: NSComboBox! @IBOutlet weak var ObfsParamTextField: NSTextField! + @IBOutlet weak var duplicateProfileButton: NSButton! @IBOutlet weak var passwordTextField: NSTextField! @IBOutlet weak var remarkTextField: NSTextField! @@ -120,7 +121,26 @@ class PreferencesWindowController: NSWindowController @IBAction func ok(sender: NSButton) { if editingProfile != nil { if !editingProfile.isValid() { - // TODO Shake window? + let numberOfShakes:Int = 8 + let durationOfShake:Float = 0.5 + let vigourOfShake:Float = 0.05 + + let frame:CGRect = (self.window?.frame)! + let shakeAnimation = CAKeyframeAnimation() + + let shakePath = CGPathCreateMutable() + CGPathMoveToPoint(shakePath, nil, NSMinX(frame), NSMinY(frame)) + + for _ in 1...numberOfShakes{ + CGPathAddLineToPoint(shakePath, nil, NSMinX(frame) - frame.size.width * CGFloat(vigourOfShake), NSMinY(frame)) + CGPathAddLineToPoint(shakePath, nil, NSMinX(frame) + frame.size.width * CGFloat(vigourOfShake), NSMinY(frame)) + } + + CGPathCloseSubpath(shakePath) + shakeAnimation.path = shakePath + shakeAnimation.duration = CFTimeInterval(durationOfShake) + self.window?.animations = ["frameOrigin":shakeAnimation] + self.window?.animator().setFrameOrigin(self.window!.frame.origin) return } } @@ -135,6 +155,25 @@ class PreferencesWindowController: NSWindowController window?.performClose(self) } + @IBAction func duplicateProfile(sender: NSButton) { + //读取当前profile,并且保存 + if editingProfile != nil && !editingProfile.isValid(){ + return + } + let index = profilesTableView.selectedRow + if index >= 0 { + let profile = profileMgr.profiles[index] + profilesTableView.beginUpdates() + profileMgr.profiles.append(profile) + let index = NSIndexSet(index: profileMgr.profiles.count-1) + profilesTableView.insertRowsAtIndexes(index, withAnimation: .EffectFade) + self.profilesTableView.scrollRowToVisible(self.profileMgr.profiles.count-1) + self.profilesTableView.selectRowIndexes(index, byExtendingSelection: false) + profilesTableView.endUpdates() + updateProfileBoxVisible() + } + } + @IBAction func copyCurrentProfileURL2Pasteboard(sender: NSButton) { let index = profilesTableView.selectedRow if index >= 0 { diff --git a/ShadowsocksX-NG/menu_icon_disabled.png b/ShadowsocksX-NG/menu_icon_disabled.png index 5cf230e..2d09313 100644 Binary files a/ShadowsocksX-NG/menu_icon_disabled.png and b/ShadowsocksX-NG/menu_icon_disabled.png differ diff --git a/ShadowsocksX-NG/menu_icon_disabled@2x.png b/ShadowsocksX-NG/menu_icon_disabled@2x.png index b041e91..c899fc8 100644 Binary files a/ShadowsocksX-NG/menu_icon_disabled@2x.png and b/ShadowsocksX-NG/menu_icon_disabled@2x.png differ diff --git a/ShadowsocksX-NG/zh-Hans.lproj/PreferencesWindowController.strings b/ShadowsocksX-NG/zh-Hans.lproj/PreferencesWindowController.strings index 7158303..b599efe 100644 --- a/ShadowsocksX-NG/zh-Hans.lproj/PreferencesWindowController.strings +++ b/ShadowsocksX-NG/zh-Hans.lproj/PreferencesWindowController.strings @@ -14,6 +14,18 @@ /* Class = "NSTextFieldCell"; title = "Remarks:"; ObjectID = "MiN-VE-FtC"; */ "MiN-VE-FtC.title" = "备注:"; +/* Class = "NSTextFieldCell"; title = "SSR Settings (Left empty if not sure what it is)"; ObjectID = "Vtp-4J-er7"; */ +"Vtp-4J-er7.title" = "SSR设置,不清楚请留空"; + +/* Class = "NSTextFieldCell"; title = "Obfs"; ObjectID = "aQj-D7-XWZ"; */ +"aQj-D7-XWZ.title" = "混淆:"; + +/* Class = "NSTextFieldCell"; title = "Protocol Param"; ObjectID = "dCk-qx-L1X"; */ +"dCk-qx-L1X.title" = "协议参数:"; + +/* Class = "NSTextFieldCell"; title = "Obfs Param"; ObjectID = "g7c-fW-7J4"; */ +"g7c-fW-7J4.title" = "混淆参数:"; + /* Class = "NSButtonCell"; title = "Enable OTA"; ObjectID = "hRZ-Rp-I5e"; */ "hRZ-Rp-I5e.title" = "启用 OTA"; @@ -26,6 +38,12 @@ /* Class = "NSTextFieldCell"; title = "Encryption:"; ObjectID = "mOh-nD-7EX"; */ "mOh-nD-7EX.title" = "加密方法:"; +/* Class = "NSTextFieldCell"; title = "Protocol:"; ObjectID = "nmk-Ue-wYb"; */ +"nmk-Ue-wYb.title" = "协议"; + +/* Class = "NSButtonCell"; title = "Duplicate"; ObjectID = "s5r-hM-4Gh"; */ +"s5r-hM-4Gh.title" = "复制"; + /* Class = "NSButtonCell"; title = "Copy URL to Clipboard"; ObjectID = "t3T-Kd-5La"; */ "t3T-Kd-5La.title" = "复制服务器URL到剪贴板"; @@ -33,19 +51,4 @@ "yHs-XE-XEB.title" = "地址:"; /* Class = "NSButtonCell"; title = "OK"; ObjectID = "zPE-oD-PwK"; */ -"zPE-oD-PwK.title" = "确定"; - -/* Class = "NSTextFieldCell"; title = "SSR Settings (Left empty if not sure what it is"; ObjectID = "Vtp-4J-er7.title";*/ -"Vtp-4J-er7.title" = "SSR设置,不清楚请留空"; - -/* Class = "NSTextFieldCell"; title = "Obfs"; ObjectID = "Vtp-4J-er7.title";*/ -"aQj-D7-XWZ.title" = "混淆" - -/* Class = "NSTextFieldCell"; title = "Obfs Param"; ObjectID = "Vtp-4J-er7.title";*/ -"g7c-fW-7J4.title" = "混淆参数" - -/* Class = "NSTextFieldCell"; title = "Protocol"; ObjectID = "nmk-Ue-wYb,title";*/ -"nmk-Ue-wYb,title" = "协议" - -/* Class = "NSTextFieldCell"; title = "Protocol Param"; ObjectID = "Vtp-4J-er7.title";*/ -"dCk-qx-L1X.title" = "协议参数" +"zPE-oD-PwK.title" = "OK";