Added global Keyboard shortcut
So we could switch between different proxy modes with global shortcut.
This commit is contained in:
@ -57,6 +57,8 @@ So after you quit the app, the ss-local maybe be still running.
|
|||||||
Added a manual mode which won't configure the system proxy settings.
|
Added a manual mode which won't configure the system proxy settings.
|
||||||
Then you could configure your apps to use socks5 proxy manual.
|
Then you could configure your apps to use socks5 proxy manual.
|
||||||
|
|
||||||
|
Added global Keyboard shortcut <kbd>⌃</kbd> + <kbd>⌘</kbd> + <kbd>P</kbd> to switch between `global` mode and `auto` mode.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Contributions must be available on a separately named branch based on the latest version of the main branch develop.
|
Contributions must be available on a separately named branch based on the latest version of the main branch develop.
|
||||||
|
|||||||
@ -427,7 +427,7 @@
|
|||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastSwiftUpdateCheck = 0730;
|
LastSwiftUpdateCheck = 0730;
|
||||||
LastUpgradeCheck = 0730;
|
LastUpgradeCheck = 0810;
|
||||||
ORGANIZATIONNAME = qiuyuzhou;
|
ORGANIZATIONNAME = qiuyuzhou;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
9B0BFFE41D0460A70040E62B = {
|
9B0BFFE41D0460A70040E62B = {
|
||||||
@ -764,6 +764,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
@ -774,8 +775,10 @@
|
|||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||||
@ -809,6 +812,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
@ -819,8 +823,10 @@
|
|||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||||
@ -839,6 +845,7 @@
|
|||||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = macosx;
|
SDKROOT = macosx;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
@ -846,6 +853,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = FE3237E9FB24D9B924A0E630 /* Pods-ShadowsocksX-NG.debug.xcconfig */;
|
baseConfigurationReference = FE3237E9FB24D9B924A0E630 /* Pods-ShadowsocksX-NG.debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
@ -873,6 +881,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = E9E9FB3855DA55D0710EE7BD /* Pods-ShadowsocksX-NG.release.xcconfig */;
|
baseConfigurationReference = E9E9FB3855DA55D0710EE7BD /* Pods-ShadowsocksX-NG.release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "0730"
|
LastUpgradeVersion = "0810"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "0730"
|
LastUpgradeVersion = "0810"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "0730"
|
LastUpgradeVersion = "0810"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import Cocoa
|
import Cocoa
|
||||||
|
import Carbon
|
||||||
|
|
||||||
@NSApplicationMain
|
@NSApplicationMain
|
||||||
class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDelegate {
|
class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDelegate {
|
||||||
@ -19,6 +19,10 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
|
|||||||
var editUserRulesWinCtrl: UserRulesController!
|
var editUserRulesWinCtrl: UserRulesController!
|
||||||
var httpPreferencesWinCtrl : HTTPPreferencesWindowController!
|
var httpPreferencesWinCtrl : HTTPPreferencesWindowController!
|
||||||
|
|
||||||
|
let keyCode = kVK_ANSI_P
|
||||||
|
let modifierKeys = cmdKey+controlKey
|
||||||
|
var hotKeyRef: EventHotKeyRef?
|
||||||
|
|
||||||
var launchAtLoginController: LaunchAtLoginController = LaunchAtLoginController()
|
var launchAtLoginController: LaunchAtLoginController = LaunchAtLoginController()
|
||||||
|
|
||||||
@IBOutlet weak var window: NSWindow!
|
@IBOutlet weak var window: NSWindow!
|
||||||
@ -39,6 +43,22 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
|
|||||||
|
|
||||||
@IBOutlet weak var lanchAtLoginMenuItem: NSMenuItem!
|
@IBOutlet weak var lanchAtLoginMenuItem: NSMenuItem!
|
||||||
|
|
||||||
|
@IBOutlet weak var hudWindow: NSPanel!
|
||||||
|
@IBOutlet weak var panelView: NSView!
|
||||||
|
@IBOutlet weak var isNameTextField: NSTextField!
|
||||||
|
|
||||||
|
let kHudFadeInDuration: Double = 0.25
|
||||||
|
let kHudFadeOutDuration: Double = 0.5
|
||||||
|
let kHudDisplayDuration: Double = 2.0
|
||||||
|
|
||||||
|
let kHudAlphaValue: CGFloat = 0.75
|
||||||
|
let kHudCornerRadius: CGFloat = 18.0
|
||||||
|
let kHudHorizontalMargin: CGFloat = 30
|
||||||
|
let kHudHeight: CGFloat = 90.0
|
||||||
|
|
||||||
|
var timerToFadeOut: Timer? = nil
|
||||||
|
var fadingOut: Bool = false
|
||||||
|
|
||||||
var statusItem: NSStatusItem!
|
var statusItem: NSStatusItem!
|
||||||
|
|
||||||
static let StatusItemIconWidth:CGFloat = 20
|
static let StatusItemIconWidth:CGFloat = 20
|
||||||
@ -135,8 +155,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
|
|||||||
userNote.subtitle = "By Handle SS URL".localized
|
userNote.subtitle = "By Handle SS URL".localized
|
||||||
}
|
}
|
||||||
userNote.informativeText = "Host: \(profile.serverHost)"
|
userNote.informativeText = "Host: \(profile.serverHost)"
|
||||||
" Port: \(profile.serverPort)"
|
//" Port: \(profile.serverPort)"
|
||||||
" Encription Method: \(profile.method)".localized
|
//" Encription Method: \(profile.method)".localized
|
||||||
userNote.soundName = NSUserNotificationDefaultSoundName
|
userNote.soundName = NSUserNotificationDefaultSoundName
|
||||||
|
|
||||||
NSUserNotificationCenter.default
|
NSUserNotificationCenter.default
|
||||||
@ -165,6 +185,9 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
|
|||||||
ProxyConfHelper.startMonitorPAC()
|
ProxyConfHelper.startMonitorPAC()
|
||||||
applyConfig()
|
applyConfig()
|
||||||
SyncSSLocal()
|
SyncSSLocal()
|
||||||
|
|
||||||
|
// Register global hotkey
|
||||||
|
registerHotkey()
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationWillTerminate(_ aNotification: Notification) {
|
func applicationWillTerminate(_ aNotification: Notification) {
|
||||||
@ -172,6 +195,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
|
|||||||
StopSSLocal()
|
StopSSLocal()
|
||||||
StopPrivoxy()
|
StopPrivoxy()
|
||||||
ProxyConfHelper.disableProxy()
|
ProxyConfHelper.disableProxy()
|
||||||
|
if let ref = hotKeyRef { UnregisterEventHotKey(ref) }
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyConfig() {
|
func applyConfig() {
|
||||||
@ -196,6 +220,63 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Hotkey Methods
|
||||||
|
func registerHotkey() -> Void {
|
||||||
|
var gMyHotKeyID = EventHotKeyID()
|
||||||
|
gMyHotKeyID.signature = OSType(fourCharCodeFrom(string: "sxng"))
|
||||||
|
gMyHotKeyID.id = UInt32(keyCode)
|
||||||
|
|
||||||
|
var eventType = EventTypeSpec()
|
||||||
|
eventType.eventClass = OSType(kEventClassKeyboard)
|
||||||
|
eventType.eventKind = OSType(kEventHotKeyPressed)
|
||||||
|
|
||||||
|
// Void pointer to `self`:
|
||||||
|
let context = Unmanaged.passUnretained(self).toOpaque()
|
||||||
|
|
||||||
|
// Install handler.
|
||||||
|
InstallEventHandler(GetApplicationEventTarget(), {(nextHanlder, theEvent, userContext) -> OSStatus in
|
||||||
|
// Extract pointer to `self` from void pointer:
|
||||||
|
let mySelf = Unmanaged<AppDelegate>.fromOpaque(userContext!).takeUnretainedValue()
|
||||||
|
|
||||||
|
switch Globals.proxyType {
|
||||||
|
case .pac:
|
||||||
|
Globals.proxyType = .global
|
||||||
|
UserDefaults.standard.setValue("global", forKey: "ShadowsocksRunningMode")
|
||||||
|
mySelf.isNameTextField.stringValue = "Gobal Mode"
|
||||||
|
mySelf.updateRunningModeMenu()
|
||||||
|
mySelf.applyConfig()
|
||||||
|
case .global:
|
||||||
|
Globals.proxyType = .pac
|
||||||
|
UserDefaults.standard.setValue("auto", forKey: "ShadowsocksRunningMode")
|
||||||
|
mySelf.isNameTextField.stringValue = "Auto Mode"
|
||||||
|
mySelf.updateRunningModeMenu()
|
||||||
|
mySelf.applyConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
mySelf.fadeInHud()
|
||||||
|
|
||||||
|
return noErr
|
||||||
|
}, 1, &eventType, context, nil)
|
||||||
|
|
||||||
|
// Register hotkey.
|
||||||
|
RegisterEventHotKey(UInt32(keyCode),
|
||||||
|
UInt32(modifierKeys),
|
||||||
|
gMyHotKeyID,
|
||||||
|
GetApplicationEventTarget(),
|
||||||
|
0,
|
||||||
|
&hotKeyRef)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fourCharCodeFrom(string: String) -> FourCharCode {
|
||||||
|
assert(string.characters.count == 4, "String length must be 4")
|
||||||
|
var result: FourCharCode = 0
|
||||||
|
for char in string.utf16 {
|
||||||
|
result = (result << 8) + FourCharCode(char)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - UI Methods
|
||||||
@IBAction func toggleRunning(_ sender: NSMenuItem) {
|
@IBAction func toggleRunning(_ sender: NSMenuItem) {
|
||||||
let defaults = UserDefaults.standard
|
let defaults = UserDefaults.standard
|
||||||
var isOn = defaults.bool(forKey: "ShadowsocksOn")
|
var isOn = defaults.bool(forKey: "ShadowsocksOn")
|
||||||
@ -510,3 +591,93 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension AppDelegate {
|
||||||
|
func fadeInHud() -> Void {
|
||||||
|
if timerToFadeOut != nil {
|
||||||
|
timerToFadeOut?.invalidate()
|
||||||
|
timerToFadeOut = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fadingOut = false
|
||||||
|
|
||||||
|
hudWindow.orderFrontRegardless()
|
||||||
|
|
||||||
|
CATransaction.begin()
|
||||||
|
CATransaction.setAnimationDuration(kHudFadeInDuration)
|
||||||
|
CATransaction.setCompletionBlock { self.didFadeIn() }
|
||||||
|
panelView.layer?.opacity = 1.0
|
||||||
|
CATransaction.commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func didFadeIn() -> Void {
|
||||||
|
timerToFadeOut = Timer.scheduledTimer(
|
||||||
|
timeInterval: kHudDisplayDuration,
|
||||||
|
target: self,
|
||||||
|
selector: #selector(fadeOutHud),
|
||||||
|
userInfo: nil,
|
||||||
|
repeats: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fadeOutHud() -> Void {
|
||||||
|
fadingOut = true
|
||||||
|
|
||||||
|
CATransaction.begin()
|
||||||
|
CATransaction.setAnimationDuration(kHudFadeOutDuration)
|
||||||
|
CATransaction.setCompletionBlock { self.didFadeOut() }
|
||||||
|
panelView.layer?.opacity = 0.0
|
||||||
|
CATransaction.commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func didFadeOut() -> Void {
|
||||||
|
if fadingOut {
|
||||||
|
self.hudWindow.orderOut(nil)
|
||||||
|
}
|
||||||
|
fadingOut = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupHud() -> Void {
|
||||||
|
isNameTextField.stringValue = "Global Mode"
|
||||||
|
isNameTextField.sizeToFit()
|
||||||
|
|
||||||
|
var labelFrame: CGRect = isNameTextField.frame
|
||||||
|
var hudWindowFrame: CGRect = hudWindow.frame
|
||||||
|
hudWindowFrame.size.width = labelFrame.size.width + kHudHorizontalMargin * 2
|
||||||
|
hudWindowFrame.size.height = kHudHeight
|
||||||
|
|
||||||
|
let screenRect: NSRect = NSScreen.screens()![0].visibleFrame
|
||||||
|
hudWindowFrame.origin.x = (screenRect.size.width - hudWindowFrame.size.width) / 2
|
||||||
|
hudWindowFrame.origin.y = (screenRect.size.height - hudWindowFrame.size.height) / 2
|
||||||
|
hudWindow.setFrame(hudWindowFrame, display: true)
|
||||||
|
|
||||||
|
var viewFrame: NSRect = hudWindowFrame;
|
||||||
|
viewFrame.origin.x = 0
|
||||||
|
viewFrame.origin.y = 0
|
||||||
|
panelView.frame = viewFrame
|
||||||
|
|
||||||
|
labelFrame.origin.x = kHudHorizontalMargin
|
||||||
|
labelFrame.origin.y = (hudWindowFrame.size.height - labelFrame.size.height) / 2
|
||||||
|
isNameTextField.frame = labelFrame
|
||||||
|
}
|
||||||
|
|
||||||
|
func initUIComponent() -> Void {
|
||||||
|
hudWindow.isOpaque = false
|
||||||
|
hudWindow.backgroundColor = .clear
|
||||||
|
hudWindow.level = Int(CGWindowLevelForKey(.utilityWindow)) + 1000
|
||||||
|
hudWindow.styleMask = .borderless
|
||||||
|
hudWindow.hidesOnDeactivate = false
|
||||||
|
hudWindow.collectionBehavior = .canJoinAllSpaces
|
||||||
|
|
||||||
|
let viewLayer: CALayer = CALayer()
|
||||||
|
viewLayer.backgroundColor = CGColor.init(red: 0.05, green: 0.05, blue: 0.05, alpha: kHudAlphaValue)
|
||||||
|
viewLayer.cornerRadius = kHudCornerRadius
|
||||||
|
panelView.wantsLayer = true
|
||||||
|
panelView.layer = viewLayer
|
||||||
|
panelView.layer?.opacity = 0.0
|
||||||
|
|
||||||
|
setupHud()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func awakeFromNib() {
|
||||||
|
initUIComponent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11201" systemVersion="16A323" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11542" systemVersion="16B2555" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="macosx"/>
|
<deployment identifier="macosx"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11201"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11542"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||||
@ -14,11 +15,13 @@
|
|||||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="ShadowsocksX_NG" customModuleProvider="target">
|
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="ShadowsocksX_NG" customModuleProvider="target">
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="RunningStatusMenuItem" destination="fzk-mE-CEV" id="R4x-gK-Qcw"/>
|
|
||||||
<outlet property="autoModeMenuItem" destination="r07-Gu-aEz" id="9aH-pQ-Rgi"/>
|
<outlet property="autoModeMenuItem" destination="r07-Gu-aEz" id="9aH-pQ-Rgi"/>
|
||||||
<outlet property="globalModeMenuItem" destination="Mw3-Jm-eXA" id="ar5-Yx-3ze"/>
|
<outlet property="globalModeMenuItem" destination="Mw3-Jm-eXA" id="ar5-Yx-3ze"/>
|
||||||
|
<outlet property="hudWindow" destination="QWV-F6-ac1" id="K6D-a4-oqE"/>
|
||||||
|
<outlet property="isNameTextField" destination="rUN-Nq-HDb" id="ayK-aM-rSa"/>
|
||||||
<outlet property="lanchAtLoginMenuItem" destination="eUq-p7-ICK" id="w4p-0c-DZn"/>
|
<outlet property="lanchAtLoginMenuItem" destination="eUq-p7-ICK" id="w4p-0c-DZn"/>
|
||||||
<outlet property="manualModeMenuItem" destination="8PR-gs-c5N" id="9qz-mU-5kt"/>
|
<outlet property="manualModeMenuItem" destination="8PR-gs-c5N" id="9qz-mU-5kt"/>
|
||||||
|
<outlet property="panelView" destination="rai-SH-9tZ" id="5aU-ld-rWb"/>
|
||||||
<outlet property="proxyMenuItem" destination="diI-fB-Rss" id="Qjk-9U-3Qy"/>
|
<outlet property="proxyMenuItem" destination="diI-fB-Rss" id="Qjk-9U-3Qy"/>
|
||||||
<outlet property="runningStatusMenuItem" destination="fzk-mE-CEV" id="Vwm-Rg-Ykn"/>
|
<outlet property="runningStatusMenuItem" destination="fzk-mE-CEV" id="Vwm-Rg-Ykn"/>
|
||||||
<outlet property="scanQRCodeMenuItem" destination="Qe6-bF-paT" id="XHa-pa-nCa"/>
|
<outlet property="scanQRCodeMenuItem" destination="Qe6-bF-paT" id="XHa-pa-nCa"/>
|
||||||
@ -164,7 +167,7 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</menuItem>
|
</menuItem>
|
||||||
</items>
|
</items>
|
||||||
<point key="canvasLocation" x="22" y="89"/>
|
<point key="canvasLocation" x="-2367" y="-139"/>
|
||||||
</menu>
|
</menu>
|
||||||
<menu id="2oY-e9-q1Z">
|
<menu id="2oY-e9-q1Z">
|
||||||
<items>
|
<items>
|
||||||
@ -178,6 +181,30 @@
|
|||||||
<modifierMask key="keyEquivalentModifierMask"/>
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
</menuItem>
|
</menuItem>
|
||||||
</items>
|
</items>
|
||||||
|
<point key="canvasLocation" x="-2113" y="-132"/>
|
||||||
</menu>
|
</menu>
|
||||||
|
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" hidesOnDeactivate="YES" oneShot="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="QWV-F6-ac1" customClass="NSPanel">
|
||||||
|
<windowStyleMask key="styleMask" closable="YES" miniaturizable="YES" resizable="YES" utility="YES"/>
|
||||||
|
<rect key="contentRect" x="139" y="81" width="200" height="100"/>
|
||||||
|
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
|
||||||
|
<value key="minSize" type="size" width="200" height="100"/>
|
||||||
|
<value key="maxSize" type="size" width="200" height="100"/>
|
||||||
|
<view key="contentView" id="rai-SH-9tZ" userLabel="Panel View">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="200" height="100"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<textField verticalHuggingPriority="750" fixedFrame="YES" preferredMaxLayoutWidth="162" translatesAutoresizingMaskIntoConstraints="NO" id="rUN-Nq-HDb" userLabel="Is Name">
|
||||||
|
<rect key="frame" x="17" y="33" width="166" height="31"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
|
<textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="center" title="Label" usesSingleLineMode="YES" id="jcH-j9-Xl3">
|
||||||
|
<font key="font" metaFont="system" size="24"/>
|
||||||
|
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
|
<color key="backgroundColor" name="alternateSelectedControlColor" catalog="System" colorSpace="catalog"/>
|
||||||
|
</textFieldCell>
|
||||||
|
</textField>
|
||||||
|
</subviews>
|
||||||
|
</view>
|
||||||
|
<point key="canvasLocation" x="-2357" y="172"/>
|
||||||
|
</window>
|
||||||
</objects>
|
</objects>
|
||||||
</document>
|
</document>
|
||||||
|
|||||||
@ -51,7 +51,7 @@ class ServerProfileManager: NSObject {
|
|||||||
|
|
||||||
if activeProfileId != nil {
|
if activeProfileId != nil {
|
||||||
defaults.set(activeProfileId, forKey: "ActiveServerProfileId")
|
defaults.set(activeProfileId, forKey: "ActiveServerProfileId")
|
||||||
writeSSLocalConfFile((getActiveProfile()?.toJsonConfig())!)
|
_ = writeSSLocalConfFile((getActiveProfile()?.toJsonConfig())!)
|
||||||
} else {
|
} else {
|
||||||
defaults.removeObject(forKey: "ActiveServerProfileId")
|
defaults.removeObject(forKey: "ActiveServerProfileId")
|
||||||
removeSSLocalConfFile()
|
removeSSLocalConfFile()
|
||||||
|
|||||||
@ -8,14 +8,12 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
|
||||||
extension String {
|
extension String {
|
||||||
var localized: String {
|
var localized: String {
|
||||||
return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: "")
|
return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extension Data {
|
extension Data {
|
||||||
func sha1() -> String {
|
func sha1() -> String {
|
||||||
let data = self
|
let data = self
|
||||||
@ -25,3 +23,12 @@ extension Data {
|
|||||||
return hexBytes.joined(separator: "")
|
return hexBytes.joined(separator: "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ProxyType {
|
||||||
|
case pac
|
||||||
|
case global
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Globals {
|
||||||
|
static var proxyType = ProxyType.pac
|
||||||
|
}
|
||||||
|
|||||||
@ -44,9 +44,9 @@
|
|||||||
|
|
||||||
"Turn Shadowsocks On" = "打开 Shadowsocks";
|
"Turn Shadowsocks On" = "打开 Shadowsocks";
|
||||||
|
|
||||||
"Proxy - Auto By PAC" = "代理 - PAC自动";
|
"Proxy - Auto By PAC" = "代理 - PAC自动(⌃⌘P)";
|
||||||
|
|
||||||
"Proxy - Global" = "代理 - 全局";
|
"Proxy - Global" = "代理 - 全局(⌃⌘P)";
|
||||||
|
|
||||||
"Proxy - Manual" = "代理 - 手动";
|
"Proxy - Manual" = "代理 - 手动";
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user