Add duplicate server profile

1. Add duplicate server profile button
2. Update status bar icon (改进了之前颜色太浅的问题)
3. Fix layout on server preference window
4. Add alert or shake window when profile is not completed
This commit is contained in:
qinyuhang
2016-08-22 19:18:35 +08:00
parent 1a8c171493
commit b24b9e9b14
6 changed files with 81 additions and 26 deletions
+2 -2
View File
@@ -92,6 +92,7 @@
/* Begin PBXFileReference section */
088EC3961D5F5B8600E40791 /* whitelist.pac */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = whitelist.pac; sourceTree = "<group>"; };
088EC3981D5F5BA300E40791 /* whiteiplist.pac */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = whiteiplist.pac; sourceTree = "<group>"; };
08AF56C01D6AFA7C00DC4F46 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/PreferencesWindowController.strings"; sourceTree = "<group>"; };
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 = "<group>"; };
9BB706A61D1B982300551F0E /* SWBApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWBApplication.h; sourceTree = "<group>"; };
9BE8FBBD1D0B1FB900CAFD01 /* libcrypto.1.0.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libcrypto.1.0.0.dylib; sourceTree = "<group>"; };
9BE8FBC11D0B71CF00CAFD01 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/PreferencesWindowController.strings"; sourceTree = "<group>"; };
9BEEF0651D04CB8500FC52B3 /* install_ss_local.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = install_ss_local.sh; sourceTree = "<group>"; };
9BEEF0661D04CE8D00FC52B3 /* start_ss_local.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = start_ss_local.sh; sourceTree = "<group>"; };
9BEEF0671D04CE9A00FC52B3 /* stop_ss_local.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = stop_ss_local.sh; sourceTree = "<group>"; };
@@ -708,7 +708,7 @@
isa = PBXVariantGroup;
children = (
9B2491B51D0ACC3A003BBECC /* Base */,
9BE8FBC11D0B71CF00CAFD01 /* zh-Hans */,
08AF56C01D6AFA7C00DC4F46 /* zh-Hans */,
);
name = PreferencesWindowController.xib;
sourceTree = "<group>";
@@ -12,6 +12,7 @@
<outlet property="ProtocolParamTextField" destination="5ze-PG-cOA" id="BJJ-5z-ngD"/>
<outlet property="ProtocolTextField" destination="CbS-wf-XMN" id="ZXD-Pp-1Gf"/>
<outlet property="copyURLBtn" destination="6mK-sY-xoH" id="YIO-RO-CXs"/>
<outlet property="duplicateProfileButton" destination="ZgM-eW-IFM" id="bbv-yc-5WJ"/>
<outlet property="hostTextField" destination="R4F-j7-GkK" id="a1I-WO-Qdj"/>
<outlet property="methodTextField" destination="ef4-8J-eFn" id="OXd-fC-ICR"/>
<outlet property="otaCheckBoxBtn" destination="9CP-zt-WuH" id="egZ-KB-iSv"/>
@@ -257,24 +258,24 @@
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="6ha-OP-X4G">
<rect key="frame" x="4" y="177" width="97" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Protocol Param" id="dCk-qx-L1X">
<rect key="frame" x="0.0" y="177" width="101" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Protocol Param:" id="dCk-qx-L1X">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Hzl-09-lcK">
<rect key="frame" x="68" y="138" width="33" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Obfs" id="aQj-D7-XWZ">
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Hzl-09-lcK">
<rect key="frame" x="64" y="138" width="37" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Obfs:" id="aQj-D7-XWZ">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="EgC-0w-FPq">
<rect key="frame" x="26" y="100" width="75" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Obfs Param" id="g7c-fW-7J4">
<rect key="frame" x="22" y="100" width="79" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Obfs Param:" id="g7c-fW-7J4">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
@@ -318,6 +319,7 @@
<constraint firstItem="ef4-8J-eFn" firstAttribute="top" secondItem="R4F-j7-GkK" secondAttribute="bottom" constant="17" id="iZy-gi-cPT"/>
<constraint firstItem="Kft-TG-O5S" firstAttribute="leading" secondItem="a3z-VL-3xV" secondAttribute="leading" constant="32" id="kZB-UQ-ow4"/>
<constraint firstItem="KdT-hY-ALS" firstAttribute="top" secondItem="ioe-Gj-Ufy" secondAttribute="bottom" constant="17" id="oAk-I1-Aka"/>
<constraint firstItem="ioe-Gj-Ufy" firstAttribute="centerY" secondItem="Hzl-09-lcK" secondAttribute="centerY" id="phR-CR-5cD"/>
<constraint firstItem="KdT-hY-ALS" firstAttribute="leading" secondItem="EgC-0w-FPq" secondAttribute="trailing" constant="12" id="qDU-rx-0FF"/>
<constraint firstItem="o4d-yF-Vi8" firstAttribute="centerX" secondItem="a3z-VL-3xV" secondAttribute="centerX" id="rhy-3Y-j7m"/>
<constraint firstItem="Qfe-Ql-iCO" firstAttribute="leading" secondItem="Baj-Yh-kmj" secondAttribute="leading" constant="21" id="rpw-Lk-g7f"/>
@@ -335,6 +337,7 @@
<constraint firstItem="KdT-hY-ALS" firstAttribute="baseline" secondItem="EgC-0w-FPq" secondAttribute="baseline" id="y9D-jH-UUw"/>
<constraint firstItem="R4F-j7-GkK" firstAttribute="top" secondItem="a3z-VL-3xV" secondAttribute="top" constant="20" symbolic="YES" id="ydG-iv-Ecv"/>
<constraint firstItem="q3C-S0-iNn" firstAttribute="trailing" secondItem="6mK-sY-xoH" secondAttribute="trailing" id="yiB-Nj-00X"/>
<constraint firstItem="EgC-0w-FPq" firstAttribute="trailing" secondItem="Hzl-09-lcK" secondAttribute="trailing" id="ytg-Zs-bNC"/>
</constraints>
</view>
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
@@ -401,6 +404,16 @@ DQ
<action selector="removeProfile:" target="-2" id="CJC-GL-qeS"/>
</connections>
</button>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ZgM-eW-IFM">
<rect key="frame" x="159" y="-1" width="64" height="21"/>
<buttonCell key="cell" type="smallSquare" title="Duplicate" bezelStyle="smallSquare" imagePosition="overlaps" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="s5r-hM-4Gh">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="duplicateProfile:" target="-2" id="IQ9-Cw-8es"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstItem="3ei-2f-kHB" firstAttribute="leading" secondItem="MbP-FS-YEs" secondAttribute="leading" constant="20" symbolic="YES" id="2tu-rA-iFm"/>
@@ -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 {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 338 B

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 575 B

After

Width:  |  Height:  |  Size: 15 KiB

@@ -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";