Compare commits

...
11 Commits
Author SHA1 Message Date
Charlie Qiu e481860075 [BUG] Fix #215 2017-01-20 16:10:11 +08:00
Charlie Qiu c28be0134c Only show A/G/M on status bar. 2017-01-20 14:21:39 +08:00
Charlie Qiu 0e8098c631 Delete proxy.pac from project. 2017-01-20 00:25:13 +08:00
Charlie Qiu 41a02b41ae Update Bundle version to 3. 2017-01-20 00:08:49 +08:00
Charlie Qiu 196e48ddd0 Disable toggle ss on/off by shortcut.
Current hard coded shortcut is frequently-used in other softwares.
2017-01-20 00:07:52 +08:00
Charlie Qiu 568eabd5cc Refactor lauch agent utils. 2017-01-20 00:04:00 +08:00
Charlie Qiu 546fca160a Upgrade kcptun client to version 20170117. 2017-01-20 00:02:02 +08:00
Charlie Qiu fe2df2c5b7 [BUG] Fix typo #212 2017-01-17 02:15:13 +08:00
Charlie Qiu f730c5cba2 [BUG] Show import/export panel as modal panel.
This approach would ensure the panel show in most front and in center of screen.
2017-01-17 02:07:33 +08:00
Charlie Qiu e5c8e965d4 [BUG] Fix #211 Exported server settings JSON does not include KCPTUN related configuration 2017-01-17 01:57:49 +08:00
Charlie Qiu d4aa0f7b47 [BUG] Fix #210 Duplicating KCPTUN enabled profiles does not copy KCPTUN related settings 2017-01-17 01:42:05 +08:00
10 changed files with 94 additions and 6002 deletions
+4 -4
View File
@@ -244,7 +244,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
// MARK: - Hotkey Methods // MARK: - Hotkey Methods
func registerHotkey() -> Void { func registerHotkey() -> Void {
registerEventHotKey(keyCode: UInt32(keyCodeP)) // to toggle PAC and Global Mode registerEventHotKey(keyCode: UInt32(keyCodeP)) // to toggle PAC and Global Mode
registerEventHotKey(keyCode: UInt32(keyCodeS)) // to toggle SS on or off // registerEventHotKey(keyCode: UInt32(keyCodeS)) // to toggle SS on or off
registerEventHandler() registerEventHandler()
} }
@@ -564,11 +564,11 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
let defaults = UserDefaults.standard let defaults = UserDefaults.standard
let mode = defaults.string(forKey: "ShadowsocksRunningMode") let mode = defaults.string(forKey: "ShadowsocksRunningMode")
if mode == "auto" { if mode == "auto" {
statusItem.title = "Auto".localized statusItem.title = "A"
} else if mode == "global" { } else if mode == "global" {
statusItem.title = "Global".localized statusItem.title = "G"
} else if mode == "manual" { } else if mode == "manual" {
statusItem.title = "Manual".localized statusItem.title = "M"
} }
let titleWidth = statusItem.title!.size(withAttributes: [NSFontAttributeName: statusItem.button!.font!]).width let titleWidth = statusItem.title!.size(withAttributes: [NSFontAttributeName: statusItem.button!.font!]).width
let imageWidth:CGFloat = AppDelegate.StatusItemIconWidth let imageWidth:CGFloat = AppDelegate.StatusItemIconWidth
@@ -35,7 +35,7 @@
<window title="Server Preferences" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" oneShot="NO" animationBehavior="default" id="F0z-JX-Cv5"> <window title="Server Preferences" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" oneShot="NO" animationBehavior="default" id="F0z-JX-Cv5">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/> <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
<rect key="contentRect" x="423" y="365" width="590" height="504"/> <rect key="contentRect" x="423" y="365" width="590" height="504"/>
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1057"/> <rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<view key="contentView" id="se5-gp-TjO"> <view key="contentView" id="se5-gp-TjO">
<rect key="frame" x="0.0" y="0.0" width="590" height="504"/> <rect key="frame" x="0.0" y="0.0" width="590" height="504"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
@@ -250,8 +250,8 @@
</textFieldCell> </textFieldCell>
</textField> </textField>
<button translatesAutoresizingMaskIntoConstraints="NO" id="WiD-LX-WHu"> <button translatesAutoresizingMaskIntoConstraints="NO" id="WiD-LX-WHu">
<rect key="frame" x="117" y="117" width="151" height="18"/> <rect key="frame" x="117" y="117" width="148" height="18"/>
<buttonCell key="cell" type="check" title="Disable Compressing" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="ezp-Vb-ouI"> <buttonCell key="cell" type="check" title="Disable compression" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="ezp-Vb-ouI">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/> <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/> <font key="font" metaFont="system"/>
</buttonCell> </buttonCell>
@@ -481,9 +481,12 @@ DQ
<constraints> <constraints>
<constraint firstAttribute="width" constant="69" id="QPa-bs-qw0"/> <constraint firstAttribute="width" constant="69" id="QPa-bs-qw0"/>
</constraints> </constraints>
<buttonCell key="cell" type="push" title="Cacnel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="j03-9E-uHW"> <buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="j03-9E-uHW">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/> <font key="font" metaFont="system"/>
<string key="keyEquivalent" base64-UTF8="YES">
Gw
</string>
</buttonCell> </buttonCell>
<connections> <connections>
<action selector="cancel:" target="-2" id="514-4D-a6S"/> <action selector="cancel:" target="-2" id="514-4D-a6S"/>
+1 -1
View File
@@ -36,7 +36,7 @@
</dict> </dict>
</array> </array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>2</string> <string>3</string>
<key>LSApplicationCategoryType</key> <key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string> <string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>
+2 -1
View File
@@ -9,7 +9,7 @@
import Foundation import Foundation
class KcptunProfile: NSObject { class KcptunProfile: NSObject, NSCopying {
var mode: String = "fast" var mode: String = "fast"
@@ -29,6 +29,7 @@ class KcptunProfile: NSObject {
copy.nocomp = self.nocomp copy.nocomp = self.nocomp
copy.datashard = self.datashard copy.datashard = self.datashard
copy.parityshard = self.parityshard copy.parityshard = self.parityshard
copy.mtu = self.mtu
return copy; return copy;
} }
+18 -7
View File
@@ -9,7 +9,7 @@
import Foundation import Foundation
let SS_LOCAL_VERSION = "2.5.6" let SS_LOCAL_VERSION = "2.5.6"
let KCPTUN_CLIENT_VERSION = "20161222" let KCPTUN_CLIENT_VERSION = "20170117"
let PRIVOXY_VERSION = "3.0.26.static" let PRIVOXY_VERSION = "3.0.26.static"
let APP_SUPPORT_DIR = "/Library/Application Support/ShadowsocksX-NG/" let APP_SUPPORT_DIR = "/Library/Application Support/ShadowsocksX-NG/"
let LAUNCH_AGENT_DIR = "/Library/LaunchAgents/" let LAUNCH_AGENT_DIR = "/Library/LaunchAgents/"
@@ -156,8 +156,12 @@ func SyncSSLocal() {
let on = UserDefaults.standard.bool(forKey: "ShadowsocksOn") let on = UserDefaults.standard.bool(forKey: "ShadowsocksOn")
if on { if on {
StopSSLocal() if changed {
StopSSLocal()
}
StartSSLocal() StartSSLocal()
} else {
StopSSLocal()
} }
} else { } else {
removeSSLocalConfFile() removeSSLocalConfFile()
@@ -291,14 +295,17 @@ func SyncPrivoxy() {
let on = UserDefaults.standard.bool(forKey: "LocalHTTPOn") let on = UserDefaults.standard.bool(forKey: "LocalHTTPOn")
if on { if on {
StopPrivoxy() if changed {
StopPrivoxy()
}
StartPrivoxy() StartPrivoxy()
} else {
StopPrivoxy()
} }
else { } else {
removePrivoxyConfFile() removePrivoxyConfFile()
StopPrivoxy() StopPrivoxy()
} }
}
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
@@ -429,10 +436,14 @@ func SyncKcptun() {
let on = UserDefaults.standard.bool(forKey: "ShadowsocksOn") let on = UserDefaults.standard.bool(forKey: "ShadowsocksOn")
if on { if on {
StopKcptun() if changed {
StopKcptun()
}
StartKcptun() StartKcptun()
return } else {
StopKcptun()
} }
return
} }
} }
StopKcptun() StopKcptun()
+5 -1
View File
@@ -56,7 +56,8 @@ class ServerProfile: NSObject, NSCopying {
guard let decoded = String(data: data, encoding: String.Encoding.utf8) else { guard let decoded = String(data: data, encoding: String.Encoding.utf8) else {
return nil return nil
} }
return "ss://\(decoded)" let s = decoded.trimmingCharacters(in: CharacterSet(charactersIn: "\n"))
return "ss://\(s)"
} }
guard let decodedUrl = decodeUrl(url: url) else { guard let decodedUrl = decodeUrl(url: url) else {
@@ -101,6 +102,9 @@ class ServerProfile: NSObject, NSCopying {
copy.password = self.password copy.password = self.password
copy.remark = self.remark copy.remark = self.remark
copy.ota = self.ota copy.ota = self.ota
copy.enabledKcptun = self.enabledKcptun
copy.kcptunProfile = self.kcptunProfile.copy() as! KcptunProfile
return copy; return copy;
} }
+54 -44
View File
@@ -79,42 +79,48 @@ class ServerProfileManager: NSObject {
openPanel.canCreateDirectories = false openPanel.canCreateDirectories = false
openPanel.canChooseFiles = true openPanel.canChooseFiles = true
openPanel.becomeKey() openPanel.becomeKey()
openPanel.begin { (result) -> Void in let result = openPanel.runModal()
if (result == NSFileHandlingPanelOKButton && (openPanel.url) != nil) { if (result == NSFileHandlingPanelOKButton && (openPanel.url) != nil) {
let fileManager = FileManager.default let fileManager = FileManager.default
let filePath:String = (openPanel.url?.path)! let filePath:String = (openPanel.url?.path)!
if (fileManager.fileExists(atPath: filePath) && filePath.hasSuffix("json")) { if (fileManager.fileExists(atPath: filePath) && filePath.hasSuffix("json")) {
let data = fileManager.contents(atPath: filePath) let data = fileManager.contents(atPath: filePath)
let readString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)! let readString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)!
let readStringData = readString.data(using: String.Encoding.utf8.rawValue) let readStringData = readString.data(using: String.Encoding.utf8.rawValue)
let jsonArr1 = try! JSONSerialization.jsonObject(with: readStringData!, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary
for item in jsonArr1.object(forKey: "configs") as! [[String: AnyObject]]{
let profile = ServerProfile()
profile.serverHost = item["server"] as! String
profile.serverPort = UInt16((item["server_port"]?.integerValue)!)
profile.method = item["method"] as! String
profile.password = item["password"] as! String
profile.remark = item["remarks"] as! String
let jsonArr1 = try! JSONSerialization.jsonObject(with: readStringData!, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary // Kcptun
profile.enabledKcptun = item["enabled_kcptun"]?.boolValue ?? false
for item in jsonArr1.object(forKey: "configs") as! [[String: AnyObject]]{ if let kcptun = item["kcptun"] {
let profile = ServerProfile() profile.kcptunProfile = KcptunProfile.fromDictionary(kcptun as! [String : Any?])
profile.serverHost = item["server"] as! String
profile.serverPort = UInt16((item["server_port"]?.integerValue)!)
profile.method = item["method"] as! String
profile.password = item["password"] as! String
profile.remark = item["remarks"] as! String
self.profiles.append(profile)
self.save()
} }
NotificationCenter.default.post(name: NSNotification.Name(rawValue: NOTIFY_SERVER_PROFILES_CHANGED), object: nil)
let configsCount = (jsonArr1.object(forKey: "configs") as! [[String: AnyObject]]).count self.profiles.append(profile)
let notification = NSUserNotification() self.save()
notification.title = "Import Server Profile succeed!".localized
notification.informativeText = "Successful import \(configsCount) items".localized
NSUserNotificationCenter.default
.deliver(notification)
}else{
let notification = NSUserNotification()
notification.title = "Import Server Profile failed!".localized
notification.informativeText = "Invalid config file!".localized
NSUserNotificationCenter.default
.deliver(notification)
return
} }
NotificationCenter.default.post(name: NSNotification.Name(rawValue: NOTIFY_SERVER_PROFILES_CHANGED), object: nil)
let configsCount = (jsonArr1.object(forKey: "configs") as! [[String: AnyObject]]).count
let notification = NSUserNotification()
notification.title = "Import Server Profile succeed!".localized
notification.informativeText = "Successful import \(configsCount) items".localized
NSUserNotificationCenter.default
.deliver(notification)
}else{
let notification = NSUserNotification()
notification.title = "Import Server Profile failed!".localized
notification.informativeText = "Invalid config file!".localized
NSUserNotificationCenter.default
.deliver(notification)
return
} }
} }
} }
@@ -141,6 +147,11 @@ class ServerProfileManager: NSObject {
configProfile.setValue(profile.method, forKey: "method") configProfile.setValue(profile.method, forKey: "method")
configProfile.setValue(profile.remark, forKey: "remarks") configProfile.setValue(profile.remark, forKey: "remarks")
configProfile.setValue(profile.remark.data(using: String.Encoding.utf8)?.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0)), forKey: "remarks_base64") configProfile.setValue(profile.remark.data(using: String.Encoding.utf8)?.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0)), forKey: "remarks_base64")
// Kcptun
configProfile.setValue(profile.enabledKcptun, forKey: "enabled_kcptun")
configProfile.setValue(profile.kcptunProfile.toDictionary(), forKey: "kcptun")
configsArray.add(configProfile) configsArray.add(configProfile)
} }
jsonArr1.setValue(configsArray, forKey: "configs") jsonArr1.setValue(configsArray, forKey: "configs")
@@ -152,17 +163,16 @@ class ServerProfileManager: NSObject {
savePanel.allowedFileTypes = ["json"] savePanel.allowedFileTypes = ["json"]
savePanel.nameFieldStringValue = "export.json" savePanel.nameFieldStringValue = "export.json"
savePanel.becomeKey() savePanel.becomeKey()
savePanel.begin { (result) -> Void in let result = savePanel.runModal()
if (result == NSFileHandlingPanelOKButton && (savePanel.url) != nil) { if (result == NSFileHandlingPanelOKButton && (savePanel.url) != nil) {
//write jsonArr1 back to file //write jsonArr1 back to file
try! jsonString.write(toFile: (savePanel.url?.path)!, atomically: true, encoding: String.Encoding.utf8) try! jsonString.write(toFile: (savePanel.url?.path)!, atomically: true, encoding: String.Encoding.utf8)
NSWorkspace.shared().selectFile((savePanel.url?.path)!, inFileViewerRootedAtPath: (savePanel.directoryURL?.path)!) NSWorkspace.shared().selectFile((savePanel.url?.path)!, inFileViewerRootedAtPath: (savePanel.directoryURL?.path)!)
let notification = NSUserNotification() let notification = NSUserNotification()
notification.title = "Export Server Profile succeed!".localized notification.title = "Export Server Profile succeed!".localized
notification.informativeText = "Successful Export \(self.profiles.count) items".localized notification.informativeText = "Successful Export \(self.profiles.count) items".localized
NSUserNotificationCenter.default NSUserNotificationCenter.default
.deliver(notification) .deliver(notification)
}
} }
} }
+3 -3
View File
@@ -7,9 +7,9 @@
# Copyright © 2017年 qiuyuzhou. All rights reserved. # Copyright © 2017年 qiuyuzhou. All rights reserved.
cd `dirname "${BASH_SOURCE[0]}"` cd `dirname "${BASH_SOURCE[0]}"`
mkdir -p "$HOME/Library/Application Support/ShadowsocksX-NG/kcptun_20161222" mkdir -p "$HOME/Library/Application Support/ShadowsocksX-NG/kcptun_20170117"
cp -f kcptun_client "$HOME/Library/Application Support/ShadowsocksX-NG/kcptun_20161222/" cp -f kcptun_client "$HOME/Library/Application Support/ShadowsocksX-NG/kcptun_20170117/"
rm -f "$HOME/Library/Application Support/ShadowsocksX-NG/kcptun_client" rm -f "$HOME/Library/Application Support/ShadowsocksX-NG/kcptun_client"
ln -s "$HOME/Library/Application Support/ShadowsocksX-NG/kcptun_20161222/kcptun_client" "$HOME/Library/Application Support/ShadowsocksX-NG/kcptun_client" ln -s "$HOME/Library/Application Support/ShadowsocksX-NG/kcptun_20170117/kcptun_client" "$HOME/Library/Application Support/ShadowsocksX-NG/kcptun_client"
echo "install kcptun done" echo "install kcptun done"
Binary file not shown.
File diff suppressed because it is too large Load Diff