Feature: Generate config with proxy group

This commit is contained in:
yicheng 2018-08-05 18:34:12 +08:00
parent 3f407a2c29
commit c68017d604
7 changed files with 69 additions and 45 deletions

View File

@ -16,6 +16,7 @@
4952C3CB2116E952004A4FA8 /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4952C3C82116E952004A4FA8 /* PreferencesWindowController.swift */; };
4952C3CC2116E952004A4FA8 /* PreferencesWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4952C3CA2116E952004A4FA8 /* PreferencesWindowController.xib */; };
4952C3CE2116EA2E004A4FA8 /* ProxyServerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4952C3CD2116EA2E004A4FA8 /* ProxyServerModel.swift */; };
4952C3D02117027C004A4FA8 /* ConfigFileFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4952C3CF2117027C004A4FA8 /* ConfigFileFactory.swift */; };
495340B020DE5F7200B0D3FF /* StatusItemView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 495340AF20DE5F7200B0D3FF /* StatusItemView.xib */; };
495340B320DE68C300B0D3FF /* StatusItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 495340B220DE68C300B0D3FF /* StatusItemView.swift */; };
495A44BF20D2660A00888A0A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 495A44BE20D2660A00888A0A /* AppDelegate.swift */; };
@ -81,6 +82,7 @@
4952C3C82116E952004A4FA8 /* PreferencesWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferencesWindowController.swift; sourceTree = "<group>"; };
4952C3CA2116E952004A4FA8 /* PreferencesWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PreferencesWindowController.xib; sourceTree = "<group>"; };
4952C3CD2116EA2E004A4FA8 /* ProxyServerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProxyServerModel.swift; sourceTree = "<group>"; };
4952C3CF2117027C004A4FA8 /* ConfigFileFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigFileFactory.swift; sourceTree = "<group>"; };
495340AF20DE5F7200B0D3FF /* StatusItemView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = StatusItemView.xib; sourceTree = "<group>"; };
495340B220DE68C300B0D3FF /* StatusItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusItemView.swift; sourceTree = "<group>"; };
495A44BC20D2660A00888A0A /* ClashXLaunchHelper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ClashXLaunchHelper.app; sourceTree = BUILT_PRODUCTS_DIR; };
@ -150,6 +152,7 @@
children = (
492C4868210EE6B9004554A0 /* ApiRequest.swift */,
4952C3BE2115C7CA004A4FA8 /* ProxyMenuItemFactory.swift */,
4952C3CF2117027C004A4FA8 /* ConfigFileFactory.swift */,
);
path = General;
sourceTree = "<group>";
@ -531,6 +534,7 @@
files = (
4989F98B20D0AD800001E564 /* SampleConfigViewController.swift in Sources */,
49CF3B5C20CE8068001EBF94 /* ProxyConfigManager.swift in Sources */,
4952C3D02117027C004A4FA8 /* ConfigFileFactory.swift in Sources */,
4997732520D251A60009B136 /* SWBApplication.m in Sources */,
495340B320DE68C300B0D3FF /* StatusItemView.swift in Sources */,
495A44D320D267D000888A0A /* LaunchAtLogin.swift in Sources */,

View File

@ -92,7 +92,7 @@
<action selector="actionGenConfig:" target="Voe-Tx-rLC" id="SBd-vV-e1R"/>
</connections>
</menuItem>
<menuItem title="Edit config" id="DwE-WX-ETZ">
<menuItem title="Edit config Manually" id="DwE-WX-ETZ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="openConfigFolder:" target="Voe-Tx-rLC" id="6Ke-Bi-AAZ"/>

View File

@ -0,0 +1,38 @@
//
// ConfigFileFactory.swift
// ClashX
//
// Created by CYC on 2018/8/5.
// Copyright © 2018 west2online. All rights reserved.
//
import Foundation
class ConfigFileFactory {
static func configFile(proxies:[ProxyServerModel]) -> String {
var proxyStr = ""
var proxyGroupStr = ""
for proxy in proxies {
let targetStr = "\(proxy.remark) = ss, \(proxy.serverHost), \(proxy.serverPort), \(proxy.method), \(proxy.password)\n"
proxyStr.append(targetStr)
proxyGroupStr.append("\(proxy.remark),")
}
proxyGroupStr = String(proxyGroupStr.dropLast())
let sampleConfig = NSData(contentsOfFile: Bundle.main.path(forResource: "sampleConfig", ofType: "ini")!)
var sampleConfigStr = String(data: sampleConfig! as Data, encoding: .utf8)
sampleConfigStr = sampleConfigStr?.replacingOccurrences(of: "{{ProxyPlaceHolder}}", with: proxyStr)
sampleConfigStr = sampleConfigStr?.replacingOccurrences(of: "{{ProxyGroupPlaceHolder}}", with: proxyGroupStr)
return sampleConfigStr!
}
static func saveToClashConfigFile(str:String) {
// save to ~/.config/clash/config.ini
let path = (NSHomeDirectory() as NSString).appendingPathComponent("/.config/clash/config.ini")
if (FileManager.default.fileExists(atPath: path)) {
try? FileManager.default.removeItem(at: URL(fileURLWithPath: path))
}
try? str.write(to: URL(fileURLWithPath: path), atomically: true, encoding: .utf8)
}
}

View File

@ -63,5 +63,11 @@ class ProxyServerModel: NSObject, Codable {
return true
}
override func copy() -> Any {
guard let data = try? JSONEncoder().encode(self) else {return ProxyServerModel()}
let copy = try? JSONDecoder().decode(ProxyServerModel.self, from: data)
return copy ?? ProxyServerModel()
}
}

View File

@ -5,7 +5,15 @@ external-controller = 127.0.0.1:8080
[Proxy]
# name = ss, server, port, cipter, password
{{placeHolder}}
{{ProxyPlaceHolder}}
[Proxy Group]
Proxy = select, {{ProxyGroupPlaceHolder}}
# url-test select which proxy will be used by benchmarking speed to a URL.
# name = url-test, [proxys], url, interval(second)
ProxyAuto = url-test, {{ProxyGroupPlaceHolder}}, http://www.google.com/generate_204, 300
[Rule]

View File

@ -90,8 +90,14 @@ class PreferencesWindowController: NSWindowController
return
}
profilesTableView.beginUpdates()
let profile = ProxyServerModel()
profile.remark = "New Server"
let profile:ProxyServerModel
if (editingConfig != nil) {
profile = editingConfig!.copy() as! ProxyServerModel
profile.remark = "\(profile.remark)Copy"
} else {
profile = ProxyServerModel()
profile.remark = "NewServer"
}
serverConfigs.append(profile)
let index = IndexSet(integer: serverConfigs.count-1)
@ -126,6 +132,8 @@ class PreferencesWindowController: NSWindowController
shakeWindows()
return
}
let str = ConfigFileFactory.configFile(proxies: serverConfigs)
ConfigFileFactory.saveToClashConfigFile(str)
window?.performClose(nil)
}
@ -134,25 +142,6 @@ class PreferencesWindowController: NSWindowController
window?.performClose(self)
}
@IBAction func duplicate(_ sender: Any) {
var copyCount = 0
for (_, toDuplicateIndex) in profilesTableView.selectedRowIndexes.enumerated() {
print(serverConfigs.count)
let profile = serverConfigs[toDuplicateIndex + copyCount]
let duplicateProfile = profile.copy() as! ProxyServerModel
serverConfigs.insert(duplicateProfile, at:toDuplicateIndex + copyCount)
profilesTableView.beginUpdates()
let index = IndexSet(integer: toDuplicateIndex + copyCount)
profilesTableView.insertRows(at: index, withAnimation: NSTableView.AnimationOptions.effectFade)
self.profilesTableView.scrollRowToVisible(toDuplicateIndex + copyCount)
self.profilesTableView.selectRowIndexes(index, byExtendingSelection: false)
profilesTableView.endUpdates()
copyCount += 1
}
updateProfileBoxVisible()
}
@IBAction func togglePasswordVisible(_ sender: Any) {
if passwordTabView.selectedTabViewItem?.identifier as! String == "secure" {
@ -167,7 +156,7 @@ class PreferencesWindowController: NSWindowController
func updateProfileBoxVisible() {
if serverConfigs.count <= 0 {
if serverConfigs.count <= 1 {
removeButton.isEnabled = false
}else{
removeButton.isEnabled = true

View File

@ -46,15 +46,6 @@
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn identifier="status" width="20" minWidth="10" maxWidth="3.4028234663852886e+38" id="wR0-vc-Gtr">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</tableHeaderCell>
<imageCell key="dataCell" refusesFirstResponder="YES" alignment="left" identifier="status" imageScaling="proportionallyDown" id="aBb-XB-tD7"/>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
</tableColumn>
<tableColumn identifier="main" width="135" minWidth="40" maxWidth="1000" id="6gc-9b-Qnw">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
<font key="font" metaFont="smallSystem"/>
@ -72,7 +63,6 @@
<connections>
<outlet property="dataSource" destination="-2" id="fz3-X6-PbB"/>
<outlet property="delegate" destination="-2" id="6zR-v1-wZj"/>
<outlet property="menu" destination="QmU-th-vjP" id="J0d-c9-pYs"/>
</connections>
</tableView>
</subviews>
@ -374,17 +364,6 @@ Gw
<real key="minimum" value="1"/>
<real key="maximum" value="65535"/>
</numberFormatter>
<menu showsStateColumn="NO" id="QmU-th-vjP">
<items>
<menuItem title="Clone" id="bl9-lq-u9V">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="duplicate:" target="-2" id="dEb-Dt-yBW"/>
</connections>
</menuItem>
</items>
<point key="canvasLocation" x="-25.5" y="171.5"/>
</menu>
<userDefaultsController representsSharedInstance="YES" id="UV9-ar-oJ3"/>
</objects>
<resources>