Feature: support url import

format: clashx:///install-config?url=http%3A%2F%2Fexample.com
This commit is contained in:
yichengchen 2019-07-28 18:56:30 +08:00
parent f51948b30f
commit 765541e07a
6 changed files with 69 additions and 40 deletions

View File

@ -30,7 +30,6 @@
49722FEF211F338B00650A41 /* FileEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49722FEA211F338B00650A41 /* FileEvent.swift */; };
49722FF0211F338B00650A41 /* EventStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49722FEB211F338B00650A41 /* EventStream.swift */; };
49722FF1211F338B00650A41 /* Witness.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49722FEC211F338B00650A41 /* Witness.swift */; };
49722FF2211F338B00650A41 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 49722FEE211F338B00650A41 /* Info.plist */; };
49761DA721C9497000AE13EF /* dashboard in Resources */ = {isa = PBXBuildFile; fileRef = 49761DA621C9497000AE13EF /* dashboard */; };
497F0DF320DE2FE50077AD41 /* Icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 497F0DF220DE2FE50077AD41 /* Icon.icns */; };
4981C88B216BAE4A008CC14A /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4981C88D216BAE4A008CC14A /* Localizable.strings */; };
@ -127,7 +126,6 @@
49722FEB211F338B00650A41 /* EventStream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventStream.swift; sourceTree = "<group>"; };
49722FEC211F338B00650A41 /* Witness.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Witness.swift; sourceTree = "<group>"; };
49722FED211F338B00650A41 /* Witness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Witness.h; sourceTree = "<group>"; };
49722FEE211F338B00650A41 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
49761DA621C9497000AE13EF /* dashboard */ = {isa = PBXFileReference; lastKnownFileType = folder; path = dashboard; sourceTree = "<group>"; };
497F0DF220DE2FE50077AD41 /* Icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = Icon.icns; sourceTree = "<group>"; };
4981C887216BAB8A008CC14A /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Main.strings"; sourceTree = "<group>"; };
@ -283,7 +281,6 @@
49722FEB211F338B00650A41 /* EventStream.swift */,
49722FEC211F338B00650A41 /* Witness.swift */,
49722FED211F338B00650A41 /* Witness.h */,
49722FEE211F338B00650A41 /* Info.plist */,
);
path = Witness;
sourceTree = "<group>";
@ -547,7 +544,6 @@
499A485A22ED781100F6C675 /* RemoteConfigAddView.xib in Resources */,
4989F98420D02D200001E564 /* Country.mmdb in Resources */,
497F0DF320DE2FE50077AD41 /* Icon.icns in Resources */,
49722FF2211F338B00650A41 /* Info.plist in Resources */,
4989F98E20D0AE990001E564 /* sampleConfig.yaml in Resources */,
49CF3B6320CED9CF001EBF94 /* check_proxy_helper.sh in Resources */,
);

View File

@ -95,6 +95,30 @@ class AppDelegate: NSObject, NSApplicationDelegate {
_ = ProxyConfigHelperManager.setUpSystemProxy(port: nil,socksPort: nil)
}
}
func application(_ application: NSApplication, open urls: [URL]) {
guard let url = urls.first else {return}
guard let components = URLComponents(string: url.absoluteString),
let scheme = components.scheme,
scheme == "clashx"
else {return}
switch components.path {
case "/install-config":
guard let url = components.queryItems?.first(where: { item in
item.name == "url"
})?.value else {return}
remoteConfigAutoupdateMenuItem.menu?.performActionForItem(at: 0)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
NotificationCenter.default.post(name: Notification.Name(rawValue: "didGetUrl"), object: nil, userInfo: ["url":url])
}
default:
Logger.log(msg: "unknown url path:\(components.path)")
}
}
func setupData() {

View File

@ -355,12 +355,12 @@
</viewController>
<customObject id="oHh-a0-cAY" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-41" y="355"/>
<point key="canvasLocation" x="-24" y="623"/>
</scene>
<!--Remote Configs-->
<scene sceneID="lXv-k7-YEi">
<objects>
<viewController title="Remote Configs" showSeguePresentationStyle="single" id="6WI-Hi-v9j" customClass="RemoteConfigViewController" customModule="ClashX" customModuleProvider="target" sceneMemberID="viewController">
<viewController title="Remote Configs" identifier="RemoteConfigViewController" storyboardIdentifier="RemoteConfigViewController" showSeguePresentationStyle="single" id="6WI-Hi-v9j" customClass="RemoteConfigViewController" customModule="ClashX" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" id="BIo-GY-n0C">
<rect key="frame" x="0.0" y="0.0" width="408" height="258"/>
<autoresizingMask key="autoresizingMask"/>
@ -567,7 +567,7 @@
<customObject id="1Mg-7q-ojs" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
<userDefaultsController id="r6q-tD-5zt"/>
</objects>
<point key="canvasLocation" x="459" y="334"/>
<point key="canvasLocation" x="531" y="514"/>
</scene>
<!--Clash Web View Contoller-->
<scene sceneID="hPF-qG-B6J">

View File

@ -18,6 +18,19 @@
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.10.1</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>com.west2online.ClashX</string>
<key>CFBundleURLSchemes</key>
<array>
<string>clashx</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>1.10.1</string>
<key>Fabric</key>

View File

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2015 Invisible Pixel. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View File

@ -7,6 +7,7 @@
//
import Cocoa
import RxSwift
class RemoteConfigViewController: NSViewController {
@ -16,6 +17,8 @@ class RemoteConfigViewController: NSViewController {
private var latestAddedConfigName: String?
let disposeBag = DisposeBag()
deinit {
print("RemoteConfigViewController deinit")
}
@ -23,6 +26,14 @@ class RemoteConfigViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
updateButtonStatus()
NotificationCenter.default.rx.notification(Notification.Name("didGetUrl")).bind {
[weak self] (note) in
guard let self = self else {return}
guard let url = note.userInfo?["url"] as? String else {return}
self.showAdd(defaultUrl: url)
}.disposed(by: disposeBag)
}
override func viewWillDisappear() {
@ -63,12 +74,15 @@ extension RemoteConfigViewController {
updateButton.isEnabled = !RemoteConfigManager.shared.configs[selectIdx].updating
}
func showAdd() {
func showAdd(defaultUrl: String? = nil) {
let alertView = NSAlert()
alertView.addButton(withTitle: NSLocalizedString("OK", comment: ""))
alertView.addButton(withTitle: NSLocalizedString("Cancel", comment: ""))
alertView.messageText = NSLocalizedString("Add a remote config", comment: "")
let remoteConfigInputView = RemoteConfigAddView.createFromNib()!
if let defaultUrl = defaultUrl {
remoteConfigInputView.setUrl(string: defaultUrl)
}
alertView.accessoryView = remoteConfigInputView
let response = alertView.runModal()
@ -86,7 +100,7 @@ extension RemoteConfigViewController {
guard !isDup else {
let alert = NSAlert()
alert.messageText = NSLocalizedString("the remote config name is duplicated", comment: "")
alert.messageText = NSLocalizedString("The remote config name is duplicated", comment: "")
alert.alertStyle = .warning
alert.runModal()
return
@ -188,6 +202,11 @@ class RemoteConfigAddView: NSView, NibLoadable {
return isUrlVaild() && getConfigName().count > 0
}
func setUrl(string: String) {
urlTextField.stringValue = string
updateConfigName()
}
private func isUrlVaild() -> Bool {
let urlString = urlTextField.stringValue
guard let url = URL(string: urlString) else {return false}
@ -199,13 +218,18 @@ class RemoteConfigAddView: NSView, NibLoadable {
return ["http","https"].contains(scheme)
}
private func updateConfigName() {
guard isUrlVaild() else {return}
let urlString = urlTextField.stringValue
configNameTextField.placeholderString = URL(string: urlString)?.host ?? "unknown"
}
}
extension RemoteConfigAddView: NSTextFieldDelegate {
func controlTextDidChange(_ obj: Notification) {
guard isUrlVaild() else {return}
let urlString = urlTextField.stringValue
configNameTextField.placeholderString = URL(string: urlString)?.host ?? "unknown"
updateConfigName()
}
}