mirror of
https://github.com/bolucat/Archive.git
synced 2025-12-24 13:28:37 +08:00
Update On Sat Jun 29 20:29:47 CEST 2024
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
66193A8923EE46BC00289B6A /* PreferenceRouting.xib in Resources */ = {isa = PBXBuildFile; fileRef = 66193A8723EE46BC00289B6A /* PreferenceRouting.xib */; };
|
||||
6633A43F2C0A120000C54CA5 /* Sparkle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6633A43E2C0A120000C54CA5 /* Sparkle.swift */; };
|
||||
663F040625ED4B2C00687600 /* V2rayLaunch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 663F040525ED4B2C00687600 /* V2rayLaunch.swift */; };
|
||||
664BAC472C2DB0E100654FB7 /* V2rayRouting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664BAC462C2DB0E100654FB7 /* V2rayRouting.swift */; };
|
||||
664EB375216C9A5E00B6AE0D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664EB374216C9A5E00B6AE0D /* AppDelegate.swift */; };
|
||||
664EB377216C9A5F00B6AE0D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 664EB376216C9A5F00B6AE0D /* Assets.xcassets */; };
|
||||
664EB392216CA9E800B6AE0D /* ConfigWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664EB390216CA9E800B6AE0D /* ConfigWindow.swift */; };
|
||||
@@ -124,6 +125,7 @@
|
||||
663F040525ED4B2C00687600 /* V2rayLaunch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = V2rayLaunch.swift; sourceTree = "<group>"; };
|
||||
664666A021CBD6C60094F0B7 /* libPods-V2rayUTool.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = "libPods-V2rayUTool.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
664B95DD217062A500DBC941 /* Alamofire */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Alamofire; path = Pods/Alamofire; sourceTree = "<group>"; };
|
||||
664BAC462C2DB0E100654FB7 /* V2rayRouting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = V2rayRouting.swift; sourceTree = "<group>"; };
|
||||
664EB371216C9A5E00B6AE0D /* V2rayU.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = V2rayU.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
664EB374216C9A5E00B6AE0D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
664EB376216C9A5F00B6AE0D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
@@ -272,6 +274,7 @@
|
||||
660D0E59216E0158000C2922 /* V2rayServer.swift */,
|
||||
663F040525ED4B2C00687600 /* V2rayLaunch.swift */,
|
||||
66BC2B88228C589E00FBB716 /* V2raySubscription.swift */,
|
||||
664BAC462C2DB0E100654FB7 /* V2rayRouting.swift */,
|
||||
66784AFB2170486D00AD307F /* Util.swift */,
|
||||
6D6DF87840CDA04AF0E9D36E /* Import.swift */,
|
||||
664EB37B216C9A5F00B6AE0D /* Info.plist */,
|
||||
@@ -544,6 +547,7 @@
|
||||
66AD5335241497000070529C /* Shortcut.m in Sources */,
|
||||
663F040625ED4B2C00687600 /* V2rayLaunch.swift in Sources */,
|
||||
6608D9E22182C9C100A0E0DD /* v2rayStream.swift in Sources */,
|
||||
664BAC472C2DB0E100654FB7 /* V2rayRouting.swift in Sources */,
|
||||
66784AFC2170486D00AD307F /* Util.swift in Sources */,
|
||||
660D0E5A216E0158000C2922 /* V2rayServer.swift in Sources */,
|
||||
6608D9DC2182C6D200A0E0DD /* v2rayInbound.swift in Sources */,
|
||||
|
||||
@@ -35,8 +35,8 @@ let preferencesWindowController = PreferencesWindowController(
|
||||
PreferenceGeneralViewController(),
|
||||
PreferenceAdvanceViewController(),
|
||||
PreferenceSubscribeViewController(),
|
||||
PreferencePacViewController(),
|
||||
PreferenceRoutingViewController(),
|
||||
PreferencePacViewController(),
|
||||
PreferenceDnsViewController(),
|
||||
PreferenceAboutViewController(),
|
||||
]
|
||||
@@ -112,6 +112,8 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
UserDefaults.set(forKey: .runMode, value: RunMode.global.rawValue)
|
||||
}
|
||||
V2rayServer.loadConfig()
|
||||
V2rayRoutings.loadConfig()
|
||||
V2raySubscription.loadConfig()
|
||||
}
|
||||
|
||||
@objc func handleAppleEvent(event: NSAppleEventDescriptor, replyEvent: NSAppleEventDescriptor) {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<outlet property="manualMode" destination="hTu-27-5OL" id="lHt-aQ-ZNU"/>
|
||||
<outlet property="newVersionItem" destination="SdL-DD-qZe" id="WXr-Gw-0HS"/>
|
||||
<outlet property="pacMode" destination="NrZ-oB-7yd" id="d3C-wO-jAI"/>
|
||||
<outlet property="routingMenu" destination="ykF-uD-Nb1" id="qTS-BH-9rV"/>
|
||||
<outlet property="routingMenu" destination="VNg-as-9we" id="NO1-L3-jsN"/>
|
||||
<outlet property="serverItems" destination="cio-ej-HL5" id="0Z8-41-eCi"/>
|
||||
<outlet property="statusMenu" destination="9n3-TW-9ur" id="Hgg-sa-fM8"/>
|
||||
<outlet property="toggleV2rayItem" destination="SML-EF-rdT" id="am7-ue-GN3"/>
|
||||
@@ -88,38 +88,7 @@
|
||||
<menuItem isSeparatorItem="YES" id="EF9-7H-2Xy"/>
|
||||
<menuItem title="Routing" id="VNg-as-9we" userLabel="Routing">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Routing" id="ykF-uD-Nb1">
|
||||
<items>
|
||||
<menuItem title="Routing..." tag="-1" id="tKM-4Z-Gyr">
|
||||
<attributedString key="attributedTitle"/>
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="goRouting:" target="hcZ-V7-Dui" id="gVK-Fb-7uq"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="pSb-Qp-dXC"/>
|
||||
<menuItem title="Global" identifier="routingGlobal" id="qhf-Kw-wBL" userLabel="Global">
|
||||
<connections>
|
||||
<action selector="switchRouting:" target="hcZ-V7-Dui" id="j4n-az-30A"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Bypassing the LAN Address" tag="1" identifier="routingLan" id="xcE-uG-T3N">
|
||||
<connections>
|
||||
<action selector="switchRouting:" target="hcZ-V7-Dui" id="ssU-OD-c6I"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Bypassing mainland address" tag="2" identifier="routingCn" id="Y6v-yx-HRg">
|
||||
<connections>
|
||||
<action selector="switchRouting:" target="hcZ-V7-Dui" id="oYE-YR-VSp"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Bypassing LAN and mainland address" tag="3" identifier="routingLanAncCn" id="YQd-ir-Ilb">
|
||||
<connections>
|
||||
<action selector="switchRouting:" target="hcZ-V7-Dui" id="OVM-pr-94W"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
<menu key="submenu" title="Routing" id="ykF-uD-Nb1"/>
|
||||
<connections>
|
||||
<action selector="switchRouting:" target="hcZ-V7-Dui" id="cPc-yB-1qO"/>
|
||||
</connections>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21225" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21225"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22690"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
@@ -23,7 +23,7 @@
|
||||
<rect key="frame" x="0.0" y="238" width="700" height="122"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dD5-t7-MtS">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="dD5-t7-MtS">
|
||||
<rect key="frame" x="18" y="79" width="192" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="GFW List URL" id="L8s-Y6-NP1">
|
||||
@@ -32,7 +32,7 @@
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="D20-Eu-3f8">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="D20-Eu-3f8">
|
||||
<rect key="frame" x="98" y="99" width="251" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="center" id="NE5-JO-Q74">
|
||||
@@ -41,7 +41,7 @@
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Uoq-RS-CX7">
|
||||
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Uoq-RS-CX7">
|
||||
<rect key="frame" x="20" y="20" width="660" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="Mzi-Yb-HhA">
|
||||
@@ -94,7 +94,7 @@
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LeF-Sd-TXL">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LeF-Sd-TXL">
|
||||
<rect key="frame" x="18" y="206" width="294" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="User Rules" id="W0g-B7-neT">
|
||||
|
||||
@@ -8,11 +8,18 @@
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="PreferenceRoutingViewController" customModule="V2rayU" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="blockTextView" destination="UmH-oj-OeF" id="F4L-ai-VLz"/>
|
||||
<outlet property="directTextView" destination="vYm-hy-3PV" id="duZ-Ja-Hlh"/>
|
||||
<outlet property="domainStrategy" destination="xjS-y0-GA2" id="R83-kT-QA0"/>
|
||||
<outlet property="proxyTextView" destination="yaM-kZ-d1d" id="7bQ-0C-yFh"/>
|
||||
<outlet property="routingRule" destination="y7v-vA-AiE" id="OTD-E9-5mu"/>
|
||||
<outlet property="addRemoveButton" destination="yay-tY-9RI" id="27u-4O-Oni"/>
|
||||
<outlet property="blockTextView" destination="Gg4-pf-FBq" id="sNf-j8-228"/>
|
||||
<outlet property="customView" destination="vIL-rw-NyK" id="eGd-9R-VkR"/>
|
||||
<outlet property="defaulRoutingRuleName" destination="Ghx-HQ-ZRg" id="yS4-cX-uLm"/>
|
||||
<outlet property="defaultView" destination="6dV-kQ-mRx" id="QLs-jh-yuK"/>
|
||||
<outlet property="directTextView" destination="bBl-6J-dn4" id="JKH-R5-yhZ"/>
|
||||
<outlet property="domainStrategy" destination="3TP-iM-Ceg" id="MRD-X0-E0s"/>
|
||||
<outlet property="errTip" destination="4I8-WZ-oKx" id="UFS-dt-gAX"/>
|
||||
<outlet property="proxyTextView" destination="OBa-Gy-6Sf" id="CB2-mh-AkQ"/>
|
||||
<outlet property="routingRuleContent" destination="HPL-Ee-PgQ" id="9Lu-aP-6ak"/>
|
||||
<outlet property="routingRuleName" destination="4qj-OR-LZe" id="aEK-PJ-Z3V"/>
|
||||
<outlet property="routingsTableView" destination="L49-ez-XJl" id="um4-rf-4zV"/>
|
||||
<outlet property="view" destination="bXz-rK-jao" id="sLH-5Q-KUz"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
@@ -23,187 +30,332 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="700" height="360"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="jcb-hK-ckn">
|
||||
<rect key="frame" x="18" y="323" width="109" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Domain Strategy:" id="22k-l7-G7a">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4I8-WZ-oKx" userLabel="errtip">
|
||||
<rect key="frame" x="179" y="335" width="337" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="center" id="h1X-Lz-CYG">
|
||||
<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 focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oz6-O3-feh">
|
||||
<rect key="frame" x="42" y="293" width="85" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Routing Rule:" id="4rB-9k-291">
|
||||
<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>
|
||||
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="xjS-y0-GA2" userLabel="domainStrategy">
|
||||
<rect key="frame" x="146" y="316" width="173" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<popUpButtonCell key="cell" type="push" title="AsIs" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="LX1-ye-51i" id="Z6S-ke-Pf5" userLabel="domainStrategy">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="bA6-aC-f9X">
|
||||
<items>
|
||||
<menuItem title="AsIs" state="on" id="LX1-ye-51i">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem title="IPIfNonMatch" id="92h-JU-wqn">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem title="IPOnDemand" id="Js7-cb-bWa">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="y7v-vA-AiE" userLabel="routingRule">
|
||||
<rect key="frame" x="146" y="285" width="173" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<popUpButtonCell key="cell" type="push" title="Global" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="zLf-pT-xlm" id="1JH-TF-90a" userLabel="routingRule">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="s7q-On-wcL">
|
||||
<items>
|
||||
<menuItem title="Global" state="on" id="zLf-pT-xlm" userLabel="Global"/>
|
||||
<menuItem title="Bypassing the LAN Address" tag="1" id="CoE-cp-7fn"/>
|
||||
<menuItem title="Bypassing mainland address" tag="2" id="EaD-tR-ldB"/>
|
||||
<menuItem title="Bypassing LAN and mainland address" tag="3" id="3qq-dt-TS9"/>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<tabView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Xt6-4C-beT">
|
||||
<rect key="frame" x="13" y="42" width="670" height="236"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<tabViewItems>
|
||||
<tabViewItem label="Proxy" identifier="" id="pnL-Z8-fIK">
|
||||
<view key="view" id="OH4-JV-ZAt">
|
||||
<rect key="frame" x="10" y="33" width="650" height="190"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<scrollView fixedFrame="YES" borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fKu-4w-nfA">
|
||||
<rect key="frame" x="12" y="12" width="625" height="171"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="52j-ry-0qA">
|
||||
<rect key="frame" x="0.0" y="0.0" width="625" height="171"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textView importsGraphics="NO" richText="NO" verticallyResizable="YES" spellingCorrection="YES" smartInsertDelete="YES" id="yaM-kZ-d1d">
|
||||
<rect key="frame" x="0.0" y="0.0" width="625" height="171"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<size key="minSize" width="625" height="171"/>
|
||||
<size key="maxSize" width="640" height="10000000"/>
|
||||
<color key="insertionPointColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
</textView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" name="windowBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="lEt-YZ-dkb">
|
||||
<rect key="frame" x="-100" y="-100" width="240" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="pbO-5s-0Pk">
|
||||
<rect key="frame" x="609" y="0.0" width="16" height="171"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
</subviews>
|
||||
</view>
|
||||
</tabViewItem>
|
||||
<tabViewItem label="Direct" identifier="" id="yc0-Po-cG1">
|
||||
<view key="view" id="mlE-HX-BcJ">
|
||||
<rect key="frame" x="10" y="33" width="650" height="190"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<scrollView fixedFrame="YES" borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kkR-uc-Qja">
|
||||
<rect key="frame" x="12" y="12" width="627" height="171"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="oot-vM-Y6a">
|
||||
<rect key="frame" x="0.0" y="0.0" width="627" height="171"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textView importsGraphics="NO" richText="NO" verticallyResizable="YES" spellingCorrection="YES" smartInsertDelete="YES" id="vYm-hy-3PV">
|
||||
<rect key="frame" x="0.0" y="0.0" width="627" height="171"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<size key="minSize" width="627" height="171"/>
|
||||
<size key="maxSize" width="628" height="10000000"/>
|
||||
<color key="insertionPointColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
</textView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" name="windowBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="J9m-5q-Nwm">
|
||||
<rect key="frame" x="-100" y="-100" width="240" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="9vp-fC-VPR">
|
||||
<rect key="frame" x="611" y="0.0" width="16" height="171"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
</subviews>
|
||||
</view>
|
||||
</tabViewItem>
|
||||
<tabViewItem label="Block" identifier="" id="nsT-BW-R2Z">
|
||||
<view key="view" id="OgP-Jb-qTh">
|
||||
<rect key="frame" x="10" y="33" width="650" height="190"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<scrollView fixedFrame="YES" borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" translatesAutoresizingMaskIntoConstraints="NO" id="GOX-0f-UYf">
|
||||
<rect key="frame" x="12" y="12" width="627" height="171"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="lep-5k-Lk2">
|
||||
<rect key="frame" x="0.0" y="0.0" width="627" height="171"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textView importsGraphics="NO" richText="NO" verticallyResizable="YES" spellingCorrection="YES" smartInsertDelete="YES" id="UmH-oj-OeF">
|
||||
<rect key="frame" x="0.0" y="0.0" width="627" height="171"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<size key="minSize" width="627" height="171"/>
|
||||
<size key="maxSize" width="633" height="10000000"/>
|
||||
<color key="insertionPointColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
</textView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" name="windowBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="KHQ-uv-0yY">
|
||||
<rect key="frame" x="-100" y="-100" width="240" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="c7l-Gi-Vwn">
|
||||
<rect key="frame" x="611" y="0.0" width="16" height="171"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
</subviews>
|
||||
</view>
|
||||
</tabViewItem>
|
||||
</tabViewItems>
|
||||
</tabView>
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="abB-zF-WFz" userLabel="Set the rules line by line: domain or ip">
|
||||
<rect key="frame" x="18" y="20" width="241" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="* Set the rules line by line: domain or ip" id="ccq-gn-C6Z" userLabel="Set the rules line by line: domain or ip">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="textColor" name="systemRedColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="RRU-nZ-itS">
|
||||
<rect key="frame" x="553" y="13" width="120" height="32"/>
|
||||
<view hidden="YES" id="6dV-kQ-mRx" userLabel="Default">
|
||||
<rect key="frame" x="260" y="20" width="420" height="320"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6af-jf-tia">
|
||||
<rect key="frame" x="18" y="259" width="109" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Domain Strategy:" id="Qp3-K0-xA9">
|
||||
<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>
|
||||
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3TP-iM-Ceg" userLabel="domainStrategy">
|
||||
<rect key="frame" x="140" y="251" width="173" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<popUpButtonCell key="cell" type="push" title="AsIs" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="Kl2-gr-bsh" id="FFA-RR-8Un" userLabel="domainStrategy">
|
||||
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="menu"/>
|
||||
<menu key="menu" id="B2F-Wu-yuF">
|
||||
<items>
|
||||
<menuItem title="AsIs" state="on" id="Kl2-gr-bsh">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem title="IPIfNonMatch" id="dSb-GT-n2n">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
<menuItem title="IPOnDemand" id="2ST-s0-RrI">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</popUpButtonCell>
|
||||
</popUpButton>
|
||||
<scrollView fixedFrame="YES" borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" translatesAutoresizingMaskIntoConstraints="NO" id="64w-Z6-GSi" userLabel="block">
|
||||
<rect key="frame" x="143" y="83" width="240" height="60"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="G9y-OO-6y5">
|
||||
<rect key="frame" x="0.0" y="0.0" width="240" height="60"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textView importsGraphics="NO" richText="NO" verticallyResizable="YES" spellingCorrection="YES" smartInsertDelete="YES" id="bBl-6J-dn4">
|
||||
<rect key="frame" x="0.0" y="0.0" width="240" height="60"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<size key="minSize" width="240" height="60"/>
|
||||
<size key="maxSize" width="633" height="10000000"/>
|
||||
</textView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" name="windowBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="bsW-PV-AtG">
|
||||
<rect key="frame" x="-100" y="-100" width="240" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="njY-6I-wSH">
|
||||
<rect key="frame" x="224" y="0.0" width="16" height="60"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<scrollView fixedFrame="YES" borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ig4-By-hS9" userLabel="direct">
|
||||
<rect key="frame" x="143" y="10" width="240" height="60"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="GwS-SF-CQa">
|
||||
<rect key="frame" x="0.0" y="0.0" width="240" height="60"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textView importsGraphics="NO" richText="NO" verticallyResizable="YES" spellingCorrection="YES" smartInsertDelete="YES" id="Gg4-pf-FBq">
|
||||
<rect key="frame" x="0.0" y="0.0" width="240" height="60"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<size key="minSize" width="240" height="60"/>
|
||||
<size key="maxSize" width="628" height="10000000"/>
|
||||
</textView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" name="windowBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="9gZ-fO-VEZ">
|
||||
<rect key="frame" x="-100" y="-100" width="240" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="KPQ-8d-YOS">
|
||||
<rect key="frame" x="224" y="0.0" width="16" height="60"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<scrollView fixedFrame="YES" borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" translatesAutoresizingMaskIntoConstraints="NO" id="TMv-k8-PCk" userLabel="proxy">
|
||||
<rect key="frame" x="143" y="153" width="240" height="60"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="uGK-ha-GOm">
|
||||
<rect key="frame" x="0.0" y="0.0" width="240" height="60"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textView importsGraphics="NO" richText="NO" verticallyResizable="YES" spellingCorrection="YES" smartInsertDelete="YES" id="OBa-Gy-6Sf">
|
||||
<rect key="frame" x="0.0" y="0.0" width="240" height="60"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<size key="minSize" width="240" height="60"/>
|
||||
<size key="maxSize" width="640" height="10000000"/>
|
||||
</textView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" name="windowBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="709-IY-EcB">
|
||||
<rect key="frame" x="-100" y="-100" width="240" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="GFh-eb-Tsf">
|
||||
<rect key="frame" x="224" y="0.0" width="16" height="60"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="jFM-iJ-CtS">
|
||||
<rect key="frame" x="18" y="289" width="109" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Routing Rule:" id="J2T-Pf-s5D">
|
||||
<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 focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gjh-yh-Xfh">
|
||||
<rect key="frame" x="23" y="200" width="100" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Proxy:" id="cfS-8I-8Au">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="aDJ-Pb-mQj">
|
||||
<rect key="frame" x="23" y="119" width="100" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Direct:" id="3hZ-qS-PUG">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fcp-vz-Yqj">
|
||||
<rect key="frame" x="23" y="51" width="100" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="Block:" id="0Cd-bg-07K">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qba-nL-flY" userLabel="Set the rules line by line: domain or ip">
|
||||
<rect key="frame" x="141" y="225" width="241" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="* Set the rules line by line: domain or ip" id="ymo-ds-No9" userLabel="Set the rules line by line: domain or ip">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="mvt-K4-emn">
|
||||
<rect key="frame" x="385" y="221" width="25" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="help" bezelStyle="helpButton" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Yjg-fg-Qnb">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="goHelp2:" target="-2" id="dbI-AV-ozZ"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ghx-HQ-ZRg">
|
||||
<rect key="frame" x="143" y="287" width="265" height="22"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" enabled="NO" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="C2A-lA-Xek">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
</view>
|
||||
<view id="vIL-rw-NyK" userLabel="Custom">
|
||||
<rect key="frame" x="260" y="20" width="420" height="320"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<scrollView fixedFrame="YES" borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" translatesAutoresizingMaskIntoConstraints="NO" id="seP-0K-2PM" userLabel="rule_content">
|
||||
<rect key="frame" x="12" y="36" width="396" height="197"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<clipView key="contentView" drawsBackground="NO" id="sw0-56-vxm">
|
||||
<rect key="frame" x="0.0" y="0.0" width="396" height="197"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textView wantsLayer="YES" importsGraphics="NO" richText="NO" verticallyResizable="YES" spellingCorrection="YES" smartInsertDelete="YES" id="HPL-Ee-PgQ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="396" height="197"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<size key="minSize" width="396" height="197"/>
|
||||
<size key="maxSize" width="602" height="10000000"/>
|
||||
</textView>
|
||||
</subviews>
|
||||
</clipView>
|
||||
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="vl1-cY-N6c">
|
||||
<rect key="frame" x="-100" y="-100" width="240" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="Kd9-5H-Ti7">
|
||||
<rect key="frame" x="380" y="0.0" width="16" height="197"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4qj-OR-LZe" userLabel="rule_name">
|
||||
<rect key="frame" x="12" y="266" width="396" height="22"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="rZe-pT-kYm">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2vP-Kp-xfO">
|
||||
<rect key="frame" x="10" y="294" width="120" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Custom Rule Name" id="Ecy-wl-v5i">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="q31-RU-ik5">
|
||||
<rect key="frame" x="10" y="240" width="149" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Custom Rule JSON Text" id="Q0v-Ic-TRt">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1MS-Rp-MSG">
|
||||
<rect key="frame" x="10" y="4" width="318" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="like: { "domainStrategy": "IPOnDemand", "rules": []}" id="ejH-X7-8Fb">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<button horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3IT-GN-64p">
|
||||
<rect key="frame" x="385" y="-4" width="25" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="help" bezelStyle="helpButton" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Ecr-ZM-mqE">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="goHelp2:" target="-2" id="qbe-WP-16k"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
<scrollView focusRingType="none" fixedFrame="YES" borderType="line" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="in5-Uo-f8c">
|
||||
<rect key="frame" x="25" y="66" width="220" height="241"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<clipView key="contentView" copiesOnScroll="NO" id="vCh-HN-u7f">
|
||||
<rect key="frame" x="1" y="1" width="218" height="239"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" columnResizing="NO" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" typeSelect="NO" id="L49-ez-XJl">
|
||||
<rect key="frame" x="0.0" y="0.0" width="218" height="239"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<size key="intercellSpacing" width="3" height="2"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
|
||||
<tableColumns>
|
||||
<tableColumn identifier="remark" width="206" minWidth="40" maxWidth="1000" id="0WD-Qv-ia2">
|
||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
|
||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
|
||||
</tableHeaderCell>
|
||||
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" title="Text Cell" usesSingleLineMode="YES" id="YQ1-7i-YOl">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</tableColumn>
|
||||
</tableColumns>
|
||||
</tableView>
|
||||
</subviews>
|
||||
</clipView>
|
||||
<edgeInsets key="contentInsets" left="0.0" right="0.0" top="0.0" bottom="0.0"/>
|
||||
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="dpI-Rq-Xuz">
|
||||
<rect key="frame" x="1" y="224" width="218" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="ys3-G3-wz7">
|
||||
<rect key="frame" x="224" y="17" width="15" height="102"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</scroller>
|
||||
</scrollView>
|
||||
<segmentedControl verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="yay-tY-9RI">
|
||||
<rect key="frame" x="25" y="55" width="220" height="23"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<segmentedCell key="cell" borderStyle="border" alignment="left" style="smallSquare" trackingMode="selectOne" id="GHx-a5-Me0">
|
||||
<font key="font" metaFont="system"/>
|
||||
<segments>
|
||||
<segment image="NSAddTemplate" imageScaling="none" width="62"/>
|
||||
<segment image="NSMenuMixedStateTemplate" imageScaling="none" width="61" tag="1"/>
|
||||
<segment width="89" enabled="NO"/>
|
||||
</segments>
|
||||
<connections>
|
||||
<action selector="addRemoveServer:" target="-2" id="icc-rY-Qe0"/>
|
||||
</connections>
|
||||
</segmentedCell>
|
||||
</segmentedControl>
|
||||
<button verticalHuggingPriority="750" id="RRU-nZ-itS">
|
||||
<rect key="frame" x="75" y="11" width="120" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="save" bezelStyle="rounded" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="8g2-Nj-m07">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES" changeBackground="YES" changeGray="YES"/>
|
||||
@@ -213,28 +365,15 @@
|
||||
<action selector="saveRouting:" target="-2" id="q5Z-CO-QXQ"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Hdf-GC-RW1">
|
||||
<rect key="frame" x="330" y="315" width="25" height="25"/>
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ntV-Ym-8MI">
|
||||
<rect key="frame" x="27" y="315" width="83" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="help" bezelStyle="helpButton" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="4Ml-by-67E">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Rouing Rules" id="E4W-rN-0eq">
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="goHelp:" target="-2" id="wWf-8M-Cj5"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="uaE-tl-Qk5">
|
||||
<rect key="frame" x="273" y="16" width="25" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="help" bezelStyle="helpButton" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="198-iA-PZS">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="goHelp2:" target="-2" id="w5e-XR-QvL"/>
|
||||
</connections>
|
||||
</button>
|
||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
</subviews>
|
||||
<point key="canvasLocation" x="-130" y="-187"/>
|
||||
</view>
|
||||
@@ -245,4 +384,8 @@
|
||||
</connections>
|
||||
</popover>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="NSAddTemplate" width="18" height="17"/>
|
||||
<image name="NSMenuMixedStateTemplate" width="18" height="5"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21225" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21225"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22690"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
@@ -28,7 +28,7 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="700" height="360"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Hdz-z4-E7U">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Hdz-z4-E7U">
|
||||
<rect key="frame" x="20" y="320" width="100" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" title="Update Logs" id="7e8-mr-923">
|
||||
@@ -107,11 +107,11 @@
|
||||
</textFieldCell>
|
||||
<prototypeCellViews>
|
||||
<tableCellView id="sbc-Q5-Cgb">
|
||||
<rect key="frame" x="1" y="1" width="151.5" height="20"/>
|
||||
<rect key="frame" x="1" y="1" width="152" height="20"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="uV2-VE-pu4">
|
||||
<rect key="frame" x="0.0" y="3" width="152" height="17"/>
|
||||
<textField focusRingType="none" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="uV2-VE-pu4">
|
||||
<rect key="frame" x="0.0" y="3" width="153" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" identifier="firstName" title="Table View Cell" id="2SR-49-K11">
|
||||
<font key="font" metaFont="system"/>
|
||||
@@ -139,11 +139,11 @@
|
||||
</textFieldCell>
|
||||
<prototypeCellViews>
|
||||
<tableCellView id="FLk-I9-55S">
|
||||
<rect key="frame" x="154.5" y="1" width="499.5" height="16"/>
|
||||
<rect key="frame" x="154.5" y="1" width="499" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9CU-oY-puz">
|
||||
<rect key="frame" x="0.0" y="0.0" width="499" height="16"/>
|
||||
<textField focusRingType="none" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9CU-oY-puz">
|
||||
<rect key="frame" x="0.0" y="0.0" width="498" height="16"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" alignment="justified" identifier="lastName" title="Table View Cell" id="OER-yL-Osv">
|
||||
<font key="font" metaFont="system"/>
|
||||
@@ -179,7 +179,7 @@
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</tableHeaderView>
|
||||
</scrollView>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NPq-js-UOI">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NPq-js-UOI">
|
||||
<rect key="frame" x="18" y="286" width="47" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="remark" id="8Lu-YS-kql">
|
||||
@@ -188,7 +188,7 @@
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="G8V-7i-NEX">
|
||||
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="G8V-7i-NEX">
|
||||
<rect key="frame" x="71" y="283" width="96" height="22"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="M3g-EG-XMY">
|
||||
@@ -197,7 +197,7 @@
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8Kr-tk-3lE">
|
||||
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8Kr-tk-3lE">
|
||||
<rect key="frame" x="18" y="316" width="45" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" lineBreakMode="clipping" alignment="right" title="url" id="J2v-eb-RUX">
|
||||
@@ -206,7 +206,7 @@
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="mlO-5h-gcH">
|
||||
<textField focusRingType="none" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="mlO-5h-gcH">
|
||||
<rect key="frame" x="71" y="316" width="608" height="22"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="dnA-jR-ayC">
|
||||
|
||||
@@ -188,23 +188,23 @@ class ConfigWindowController: NSWindowController, NSWindowDelegate, NSTabViewDel
|
||||
|
||||
// delete server config
|
||||
case 1:
|
||||
// get seleted index
|
||||
let idx = self.serversTableView.selectedRow
|
||||
// remove
|
||||
V2rayServer.remove(idx: idx)
|
||||
|
||||
// reload
|
||||
V2rayServer.loadConfig()
|
||||
menuController.showServers()
|
||||
|
||||
// selected prev row
|
||||
let cnt: Int = V2rayServer.count()
|
||||
var rowIndex: Int = idx - 1
|
||||
if idx > 0 && idx < cnt {
|
||||
rowIndex = idx
|
||||
}
|
||||
|
||||
DispatchQueue.main.sync {
|
||||
// get seleted index
|
||||
let idx = self.serversTableView.selectedRow
|
||||
// remove
|
||||
V2rayServer.remove(idx: idx)
|
||||
|
||||
// reload
|
||||
V2rayServer.loadConfig()
|
||||
menuController.showServers()
|
||||
|
||||
// selected prev row
|
||||
let cnt: Int = V2rayServer.count()
|
||||
var rowIndex: Int = idx - 1
|
||||
if idx > 0 && idx < cnt {
|
||||
rowIndex = idx
|
||||
}
|
||||
|
||||
// reload
|
||||
self.serversTableView.reloadData()
|
||||
// fix
|
||||
|
||||
@@ -27,7 +27,7 @@ class MenuController: NSObject, NSMenuDelegate {
|
||||
@IBOutlet weak var v2rayStatusItem: NSMenuItem!
|
||||
@IBOutlet weak var serverItems: NSMenuItem!
|
||||
@IBOutlet weak var newVersionItem: NSMenuItem!
|
||||
@IBOutlet weak var routingMenu: NSMenu!
|
||||
@IBOutlet weak var routingMenu: NSMenuItem!
|
||||
|
||||
// when menu.xib loaded
|
||||
override func awakeFromNib() {
|
||||
@@ -39,7 +39,7 @@ class MenuController: NSObject, NSMenuDelegate {
|
||||
// hide new version
|
||||
newVersionItem.isHidden = true
|
||||
|
||||
self.showRouring();
|
||||
self.showRouting();
|
||||
|
||||
// windowWillClose Notification
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(configWindowWillClose(notification:)), name: NSWindow.willCloseNotification, object: nil)
|
||||
@@ -127,21 +127,40 @@ class MenuController: NSObject, NSMenuDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func showRouring() {
|
||||
let routingRule = Int(UserDefaults.get(forKey: .routingRule) ?? "0") ?? 0
|
||||
DispatchQueue.main.async {
|
||||
// 假设 routingMenu 已经连接并且有一个子菜单
|
||||
if self.routingMenu.items != nil {
|
||||
// 确保 routingMenu 已经连接
|
||||
for item in self.routingMenu.items {
|
||||
if item.tag == routingRule {
|
||||
item.state = .on
|
||||
} else {
|
||||
item.state = .off
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
func showRouting() {
|
||||
DispatchQueue.global().async {
|
||||
let rules = V2rayRoutings.all()
|
||||
print("showRouting",rules)
|
||||
let sumMenus = NSMenu()
|
||||
// add Routing... menu and click event is goRouting
|
||||
let routingMenuItem = NSMenuItem()
|
||||
routingMenuItem.title = "Routing..."
|
||||
routingMenuItem.target = self
|
||||
routingMenuItem.action = #selector(self.goRouting(_:))
|
||||
sumMenus.addItem(routingMenuItem)
|
||||
// add separator menu item
|
||||
let separator = NSMenuItem.separator()
|
||||
sumMenus.addItem(separator)
|
||||
// now add all rules
|
||||
let routingRule = UserDefaults.get(forKey: .routingSelectedRule)
|
||||
for rule in rules {
|
||||
let menuItem = NSMenuItem()
|
||||
menuItem.title = rule.remark
|
||||
menuItem.target = self
|
||||
menuItem.action = #selector(self.switchRouting(_:))
|
||||
menuItem.representedObject = rule
|
||||
menuItem.isEnabled = true
|
||||
if rule.name == routingRule {
|
||||
menuItem.state = NSControl.StateValue.on
|
||||
}
|
||||
sumMenus.addItem(menuItem)
|
||||
}
|
||||
print("showRouting",sumMenus)
|
||||
// 假设 routingMenu 已经连接并且有一个子菜单
|
||||
DispatchQueue.main.async {
|
||||
self.routingMenu.submenu = sumMenus
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getServerMenus() -> NSMenu {
|
||||
@@ -261,6 +280,16 @@ class MenuController: NSObject, NSMenuDelegate {
|
||||
V2rayLaunch.restartV2ray()
|
||||
}
|
||||
|
||||
@IBAction func switchRouting(_ sender: NSMenuItem) {
|
||||
guard let obj = sender.representedObject as? RoutingItem else {
|
||||
NSLog("switchRouting err")
|
||||
return
|
||||
}
|
||||
UserDefaults.set(forKey: .routingSelectedRule, value: obj.name);
|
||||
self.showRouting();
|
||||
V2rayLaunch.restartV2ray()
|
||||
}
|
||||
|
||||
@IBAction func openConfig(_ sender: NSMenuItem) {
|
||||
OpenConfigWindow()
|
||||
}
|
||||
@@ -300,12 +329,6 @@ class MenuController: NSObject, NSMenuDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func switchRouting(_ sender: NSMenuItem) {
|
||||
UserDefaults.set(forKey: .routingRule, value: String(sender.tag));
|
||||
self.showRouring();
|
||||
V2rayLaunch.restartV2ray()
|
||||
}
|
||||
|
||||
@IBAction func switchGlobalMode(_ sender: NSMenuItem) {
|
||||
UserDefaults.set(forKey: .runMode, value: RunMode.global.rawValue)
|
||||
V2rayLaunch.restartV2ray()
|
||||
|
||||
@@ -9,18 +9,26 @@
|
||||
import Cocoa
|
||||
import Preferences
|
||||
|
||||
final class PreferenceRoutingViewController: NSViewController, PreferencePane {
|
||||
final class PreferenceRoutingViewController: NSViewController, PreferencePane, NSTabViewDelegate {
|
||||
|
||||
let preferencePaneIdentifier = PreferencePane.Identifier.routingTab
|
||||
let preferencePaneTitle = "Routing"
|
||||
let toolbarItemIcon = NSImage(named: NSImage.networkName)!
|
||||
let tableViewDragType: String = "v2ray.routing"
|
||||
|
||||
@IBOutlet weak var domainStrategy: NSPopUpButton!
|
||||
@IBOutlet weak var routingRule: NSPopUpButton!
|
||||
@IBOutlet var proxyTextView: NSTextView!
|
||||
@IBOutlet var directTextView: NSTextView!
|
||||
@IBOutlet var blockTextView: NSTextView!
|
||||
|
||||
@IBOutlet weak var proxyTextView: NSTextView!
|
||||
@IBOutlet weak var directTextView: NSTextView!
|
||||
@IBOutlet weak var blockTextView: NSTextView!
|
||||
@IBOutlet weak var routingRuleContent: NSTextView!
|
||||
@IBOutlet weak var routingRuleName: NSTextField!
|
||||
@IBOutlet weak var defaulRoutingRuleName: NSTextField!
|
||||
@IBOutlet weak var errTip: NSTextField!
|
||||
@IBOutlet weak var routingsTableView: NSTableView!
|
||||
@IBOutlet weak var addRemoveButton: NSSegmentedControl!
|
||||
@IBOutlet weak var customView: NSView!
|
||||
@IBOutlet weak var defaultView: NSView!
|
||||
|
||||
override var nibName: NSNib.Name? {
|
||||
return "PreferenceRouting"
|
||||
}
|
||||
@@ -29,30 +37,115 @@ final class PreferenceRoutingViewController: NSViewController, PreferencePane {
|
||||
super.viewDidLoad()
|
||||
// fix: https://github.com/sindresorhus/Preferences/issues/31
|
||||
self.preferredContentSize = NSMakeSize(self.view.frame.size.width, self.view.frame.size.height);
|
||||
// set table drag style
|
||||
self.routingsTableView.registerForDraggedTypes([NSPasteboard.PasteboardType(rawValue: tableViewDragType)])
|
||||
self.routingsTableView.allowsMultipleSelection = true
|
||||
|
||||
let domainStrategy = UserDefaults.get(forKey: .routingDomainStrategy) ?? "AsIs"
|
||||
self.domainStrategy.selectItem(withTitle: domainStrategy)
|
||||
|
||||
let routingRule = Int(UserDefaults.get(forKey: .routingRule) ?? "0") ?? 0
|
||||
self.routingRule.selectItem(withTag: routingRule)
|
||||
|
||||
let routingProxyDomains = UserDefaults.getArray(forKey: .routingProxyDomains) ?? [];
|
||||
let routingProxyIps = UserDefaults.getArray(forKey: .routingProxyIps) ?? [];
|
||||
let routingDirectDomains = UserDefaults.getArray(forKey: .routingDirectDomains) ?? [];
|
||||
let routingDirectIps = UserDefaults.getArray(forKey: .routingDirectIps) ?? [];
|
||||
let routingBlockDomains = UserDefaults.getArray(forKey: .routingBlockDomains) ?? [];
|
||||
let routingBlockIps = UserDefaults.getArray(forKey: .routingBlockIps) ?? [];
|
||||
|
||||
let routingProxy = routingProxyDomains + routingProxyIps
|
||||
let routingDirect = routingDirectDomains + routingDirectIps
|
||||
let routingBlock = routingBlockDomains + routingBlockIps
|
||||
|
||||
print("routingProxy", routingProxy, routingDirect, routingBlock)
|
||||
self.proxyTextView.string = routingProxy.joined(separator: "\n")
|
||||
self.directTextView.string = routingDirect.joined(separator: "\n")
|
||||
self.blockTextView.string = routingBlock.joined(separator: "\n")
|
||||
// reload tableview
|
||||
V2rayRoutings.loadConfig()
|
||||
// table view
|
||||
self.routingsTableView.delegate = self
|
||||
self.routingsTableView.dataSource = self
|
||||
self.routingsTableView.reloadData()
|
||||
}
|
||||
|
||||
func set_tip(str: String) {
|
||||
self.errTip.stringValue = str
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
|
||||
self.errTip.stringValue = ""
|
||||
}
|
||||
}
|
||||
|
||||
func loadJsonData(rowIndex: Int) {
|
||||
print("loadJsonData", rowIndex)
|
||||
DispatchQueue.main.async {
|
||||
self.defaultView.isHidden = true
|
||||
self.customView.isHidden = true
|
||||
if let item = V2rayRoutings.load(idx: rowIndex) {
|
||||
let isDefaultRule = V2rayRoutings.isDefaultRule(name: item.name)
|
||||
print("loadJsonData", item.domainStrategy,item.proxy,item.direct,item.block,item.json,isDefaultRule)
|
||||
if isDefaultRule {
|
||||
self.defaultView.isHidden = false
|
||||
self.domainStrategy.selectItem(withTitle: item.domainStrategy)
|
||||
self.proxyTextView.string = item.proxy
|
||||
self.directTextView.string = item.direct
|
||||
self.blockTextView.string = item.block
|
||||
self.defaulRoutingRuleName.stringValue = item.remark
|
||||
} else {
|
||||
self.customView.isHidden = false
|
||||
self.routingRuleName.stringValue = item.remark
|
||||
self.routingRuleContent.string = item.json
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@IBAction func addRemoveServer(_ sender: NSSegmentedCell) {
|
||||
// 0 add,1 remove
|
||||
let seg = addRemoveButton.indexOfSelectedItem
|
||||
print("addRemoveServer",seg)
|
||||
DispatchQueue.global().async {
|
||||
switch seg {
|
||||
// add server config
|
||||
case 0:
|
||||
// add
|
||||
V2rayRoutings.add(remark: "new-rule", json: V2rayRoutings.default_rule_content)
|
||||
|
||||
DispatchQueue.main.sync {
|
||||
V2rayRoutings.loadConfig()
|
||||
// reload data
|
||||
self.routingsTableView.reloadData()
|
||||
// selected current row
|
||||
self.routingsTableView.selectRowIndexes(NSIndexSet(index: V2rayRoutings.count() - 1) as IndexSet, byExtendingSelection: false)
|
||||
}
|
||||
break
|
||||
|
||||
// delete server config
|
||||
case 1:
|
||||
DispatchQueue.main.sync {
|
||||
// get seleted index
|
||||
let idx = self.routingsTableView.selectedRow
|
||||
// remove
|
||||
V2rayRoutings.remove(idx: idx)
|
||||
|
||||
// reload
|
||||
V2rayRoutings.loadConfig()
|
||||
|
||||
// selected prev row
|
||||
let cnt: Int = V2rayRoutings.count()
|
||||
var rowIndex: Int = idx - 1
|
||||
if idx > 0 && idx < cnt {
|
||||
rowIndex = idx
|
||||
}
|
||||
|
||||
// reload
|
||||
self.routingsTableView.reloadData()
|
||||
// fix
|
||||
if cnt > 1 {
|
||||
// selected row
|
||||
self.routingsTableView.selectRowIndexes(NSIndexSet(index: rowIndex) as IndexSet, byExtendingSelection: false)
|
||||
}
|
||||
|
||||
if rowIndex >= 0 {
|
||||
self.loadJsonData(rowIndex: rowIndex)
|
||||
} else {
|
||||
self.routingsTableView.becomeFirstResponder()
|
||||
}
|
||||
}
|
||||
|
||||
// refresh menu
|
||||
menuController.showRouting()
|
||||
break
|
||||
|
||||
// unknown action
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@IBAction func goHelp(_ sender: Any) {
|
||||
guard let url = URL(string: "https://toutyrater.github.io/basic/routing/") else {
|
||||
return
|
||||
@@ -68,73 +161,144 @@ final class PreferenceRoutingViewController: NSViewController, PreferencePane {
|
||||
}
|
||||
|
||||
@IBAction func saveRouting(_ sender: Any) {
|
||||
UserDefaults.set(forKey: .routingDomainStrategy, value: self.domainStrategy.titleOfSelectedItem!)
|
||||
UserDefaults.set(forKey: .routingRule, value: String(self.routingRule.selectedTag()))
|
||||
let selectedRule = self.routingsTableView.selectedRow
|
||||
if selectedRule == -1 {
|
||||
return
|
||||
}
|
||||
guard let rule = V2rayRoutings.load(idx: selectedRule) else {
|
||||
return
|
||||
}
|
||||
|
||||
var (domains, ips) = self.parseDomainOrIp(domainIpStr: self.proxyTextView.string)
|
||||
UserDefaults.setArray(forKey: .routingProxyDomains, value: domains)
|
||||
UserDefaults.setArray(forKey: .routingProxyIps, value: ips)
|
||||
|
||||
(domains, ips) = self.parseDomainOrIp(domainIpStr: self.directTextView.string)
|
||||
UserDefaults.setArray(forKey: .routingDirectDomains, value: domains)
|
||||
UserDefaults.setArray(forKey: .routingDirectIps, value: ips)
|
||||
|
||||
(domains, ips) = self.parseDomainOrIp(domainIpStr: self.blockTextView.string)
|
||||
UserDefaults.setArray(forKey: .routingBlockDomains, value: domains)
|
||||
UserDefaults.setArray(forKey: .routingBlockIps, value: ips)
|
||||
if V2rayRoutings.isDefaultRule(name: rule.name) {
|
||||
let domainStrategy = self.domainStrategy.titleOfSelectedItem
|
||||
if domainStrategy != nil {
|
||||
rule.domainStrategy = domainStrategy!
|
||||
}
|
||||
rule.proxy = self.proxyTextView.string
|
||||
rule.direct = self.directTextView.string
|
||||
rule.block = self.blockTextView.string
|
||||
} else {
|
||||
rule.remark = self.routingRuleName.stringValue
|
||||
let (res, err) = parseRoutingRuleJson(json: self.routingRuleContent.string)
|
||||
if err != nil {
|
||||
print("parseRoutingRuleJson err", err)
|
||||
self.errTip.stringValue = "parse json err: \(err)"
|
||||
// hide err
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
|
||||
self.errTip.stringValue = ""
|
||||
}
|
||||
return
|
||||
} else {
|
||||
self.errTip.stringValue = ""
|
||||
rule.json = self.routingRuleContent.string
|
||||
}
|
||||
}
|
||||
|
||||
// save update
|
||||
V2rayRoutings.save(routing: rule)
|
||||
|
||||
// reload table
|
||||
self.routingsTableView.reloadData()
|
||||
// set selected
|
||||
self.routingsTableView.selectRowIndexes(NSIndexSet(index: selectedRule) as IndexSet, byExtendingSelection: false)
|
||||
|
||||
// 更新菜单
|
||||
menuController.showRouring();
|
||||
menuController.showRouting();
|
||||
// if is selected rule name == rule.name, restart v2ray
|
||||
let selectedRuleName = UserDefaults.get(forKey: .routingSelectedRule)
|
||||
if selectedRuleName == rule.name {
|
||||
// restart v2ray
|
||||
V2rayLaunch.restartV2ray()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set current server item and reload v2ray-core
|
||||
V2rayLaunch.restartV2ray()
|
||||
// NSnameSource
|
||||
extension PreferenceRoutingViewController: NSTableViewDataSource {
|
||||
|
||||
func numberOfRows(in tableView: NSTableView) -> Int {
|
||||
return V2rayRoutings.count()
|
||||
}
|
||||
|
||||
func parseDomainOrIp(domainIpStr: String) -> (domains: [String], ips: [String]) {
|
||||
let all = domainIpStr.split(separator: "\n")
|
||||
// show cell
|
||||
func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
|
||||
let v2rayItemList = V2rayRoutings.list()
|
||||
// set cell data
|
||||
if v2rayItemList.count >= row {
|
||||
return v2rayItemList[row].remark
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var domains: [String] = []
|
||||
var ips: [String] = []
|
||||
// NSTableViewDelegate
|
||||
extension PreferenceRoutingViewController: NSTableViewDelegate {
|
||||
// For NSTableViewDelegate
|
||||
func tableViewSelectionDidChange(_ notification: Notification) {
|
||||
// Ensure there's a valid selected row before calling loadJsonData
|
||||
if self.routingsTableView.selectedRow >= 0 {
|
||||
self.loadJsonData(rowIndex: self.routingsTableView.selectedRow)
|
||||
} else {
|
||||
// Handle the case where no row is selected or add a default behavior
|
||||
print("No row selected")
|
||||
}
|
||||
self.errTip.stringValue = ""
|
||||
}
|
||||
|
||||
for item in all {
|
||||
let tmp = item.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
// Drag & Drop reorder rows
|
||||
func tableView(_ tableView: NSTableView, pasteboardWriterForRow row: Int) -> NSPasteboardWriting? {
|
||||
let item = NSPasteboardItem()
|
||||
item.setString(String(row), forType: NSPasteboard.PasteboardType(rawValue: tableViewDragType))
|
||||
return item
|
||||
}
|
||||
|
||||
// is ip
|
||||
if isIp(str: tmp) || tmp.contains("geoip:") {
|
||||
ips.append(tmp)
|
||||
continue
|
||||
func tableView(_ tableView: NSTableView, validateDrop info: NSDraggingInfo, proposedRow row: Int, proposedDropOperation dropOperation: NSTableView.DropOperation) -> NSDragOperation {
|
||||
if dropOperation == .above {
|
||||
return .move
|
||||
}
|
||||
return NSDragOperation()
|
||||
}
|
||||
|
||||
func tableView(_ tableView: NSTableView, acceptDrop info: NSDraggingInfo, row: Int, dropOperation: NSTableView.DropOperation) -> Bool {
|
||||
var oldIndexes = [Int]()
|
||||
info.enumerateDraggingItems(options: [], for: tableView, classes: [NSPasteboardItem.self], searchOptions: [:], using: {
|
||||
(draggingItem: NSDraggingItem, idx: Int, stop: UnsafeMutablePointer<ObjCBool>) in
|
||||
if let str = (draggingItem.item as! NSPasteboardItem).string(forType: NSPasteboard.PasteboardType(rawValue: self.tableViewDragType)),
|
||||
let index = Int(str) {
|
||||
oldIndexes.append(index)
|
||||
}
|
||||
})
|
||||
|
||||
// is domain
|
||||
if tmp.contains("domain:") || tmp.contains("geosite:") {
|
||||
domains.append(tmp)
|
||||
continue
|
||||
}
|
||||
var oldIndexOffset = 0
|
||||
var newIndexOffset = 0
|
||||
var oldIndexLast = 0
|
||||
var newIndexLast = 0
|
||||
|
||||
if isDomain(str: tmp) {
|
||||
domains.append(tmp)
|
||||
continue
|
||||
// For simplicity, the code below uses `tableView.moveRowAtIndex` to move rows around directly.
|
||||
// You may want to move rows in your content array and then call `tableView.reloadData()` instead.
|
||||
for oldIndex in oldIndexes {
|
||||
if oldIndex < row {
|
||||
oldIndexLast = oldIndex + oldIndexOffset
|
||||
newIndexLast = row - 1
|
||||
oldIndexOffset -= 1
|
||||
} else {
|
||||
oldIndexLast = oldIndex
|
||||
newIndexLast = row + newIndexOffset
|
||||
newIndexOffset += 1
|
||||
}
|
||||
}
|
||||
|
||||
print("ips", ips, "domains", domains)
|
||||
|
||||
return (domains, ips)
|
||||
}
|
||||
|
||||
func isIp(str: String) -> Bool {
|
||||
let pattern = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(/[0-9]{2})?$"
|
||||
if ((str.count == 0) || (str.range(of: pattern, options: .regularExpression) == nil)) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func isDomain(str: String) -> Bool {
|
||||
let pattern = "[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+"
|
||||
if ((str.count == 0) || (str.range(of: pattern, options: .regularExpression) == nil)) {
|
||||
return false
|
||||
DispatchQueue.global().async {
|
||||
print("move",oldIndexLast,newIndexLast)
|
||||
// move
|
||||
V2rayRoutings.move(oldIndex: oldIndexLast, newIndex: newIndexLast)
|
||||
DispatchQueue.main.async {
|
||||
// set selected
|
||||
self.routingsTableView.selectRowIndexes(NSIndexSet(index: newIndexLast) as IndexSet, byExtendingSelection: false)
|
||||
// reload table
|
||||
self.routingsTableView.reloadData()
|
||||
}
|
||||
// reload menu
|
||||
menuController.showRouting()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -63,16 +63,10 @@ extension UserDefaults {
|
||||
// pacPort
|
||||
case localPacPort
|
||||
|
||||
// for routing rule
|
||||
case routingDomainStrategy
|
||||
case routingRule
|
||||
case routingProxyDomains
|
||||
case routingProxyIps
|
||||
case routingDirectDomains
|
||||
case routingDirectIps
|
||||
case routingBlockDomains
|
||||
case routingBlockIps
|
||||
case Exception
|
||||
// custom routing list
|
||||
case routingCustomList
|
||||
// routing selected rule
|
||||
case routingSelectedRule
|
||||
}
|
||||
|
||||
static func setBool(forKey key: KEY, value: Bool) {
|
||||
|
||||
519
v2rayu/V2rayU/V2rayRouting.swift
Normal file
519
v2rayu/V2rayU/V2rayRouting.swift
Normal file
@@ -0,0 +1,519 @@
|
||||
//
|
||||
// V2rayRouting.swift
|
||||
// V2rayU
|
||||
//
|
||||
// Created by yanue on 2024/6/27.
|
||||
// Copyright © 2024 yanue. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
let RoutingRuleGlobal = "routing.global"
|
||||
let RoutingRuleLAN = "routing.lan"
|
||||
let RoutingRuleCn = "routing.cn"
|
||||
let RoutingRuleLANAndCn = "routing.lanAndCn"
|
||||
|
||||
let defaultRuleCn = Dictionary(uniqueKeysWithValues: [
|
||||
(RoutingRuleGlobal, "🌏全局"),
|
||||
(RoutingRuleLAN, "🌏 绕过局域网"),
|
||||
(RoutingRuleCn, "🌏 绕过中国大陆"),
|
||||
(RoutingRuleLANAndCn, "🌏 绕过局域网和中国大陆")
|
||||
])
|
||||
|
||||
let defaultRuleEn = Dictionary(uniqueKeysWithValues: [
|
||||
(RoutingRuleGlobal, "🌏 Global"),
|
||||
(RoutingRuleLAN, "🌏 Bypassing the LAN Address"),
|
||||
(RoutingRuleCn, "🌏 Bypassing mainland address"),
|
||||
(RoutingRuleLANAndCn, "🌏 Bypassing LAN and mainland address")
|
||||
])
|
||||
|
||||
let defaultRules = Dictionary(uniqueKeysWithValues: [
|
||||
(RoutingRuleGlobal,RoutingItem(name: RoutingRuleGlobal, remark: "")),
|
||||
(RoutingRuleLAN,RoutingItem(name: RoutingRuleLAN, remark: "")),
|
||||
(RoutingRuleCn,RoutingItem(name: RoutingRuleCn, remark: "")),
|
||||
(RoutingRuleLANAndCn,RoutingItem(name: RoutingRuleLANAndCn,remark:""))
|
||||
])
|
||||
|
||||
// ----- routing server manager -----
|
||||
class V2rayRoutings: NSObject {
|
||||
static var shared = V2rayRoutings()
|
||||
|
||||
static let lock = NSLock()
|
||||
|
||||
static let default_rule_content = """
|
||||
{
|
||||
"domainStrategy": "AsIs",
|
||||
"rules": [
|
||||
]
|
||||
}
|
||||
"""
|
||||
// Initialization
|
||||
override init() {
|
||||
super.init()
|
||||
V2rayRoutings.loadConfig()
|
||||
}
|
||||
|
||||
// routing server list
|
||||
static private var routings: [RoutingItem] = []
|
||||
|
||||
// (init) load routing server list from UserDefaults
|
||||
static func loadConfig() {
|
||||
self.lock.lock()
|
||||
defer {
|
||||
self.lock.unlock()
|
||||
}
|
||||
|
||||
// static reset
|
||||
self.routings = []
|
||||
|
||||
// load name list from UserDefaults
|
||||
var list = UserDefaults.getArray(forKey: .routingCustomList) ?? [];
|
||||
|
||||
print("V2rayRoutings-loadConfig", list)
|
||||
|
||||
let langStr = Locale.current.languageCode
|
||||
let isMainland = langStr == "zh-CN" || langStr == "zh" || langStr == "zh-Hans" || langStr == "zh-Hant"
|
||||
// for defaultRules
|
||||
for (key, rule) in defaultRules {
|
||||
// load and check
|
||||
if nil == RoutingItem.load(name: key) {
|
||||
if isMainland {
|
||||
rule.remark = defaultRuleCn[key] ?? rule.remark
|
||||
} else {
|
||||
rule.remark = defaultRuleEn[key] ?? rule.remark
|
||||
}
|
||||
// create new
|
||||
rule.store()
|
||||
}
|
||||
// if not in list, append
|
||||
if !list.contains(key) {
|
||||
list.append(key)
|
||||
}
|
||||
}
|
||||
|
||||
// load each RoutingItem
|
||||
for item in list {
|
||||
guard let routing = RoutingItem.load(name: item) else {
|
||||
// delete from UserDefaults
|
||||
RoutingItem.remove(name: item)
|
||||
continue
|
||||
}
|
||||
// append
|
||||
self.routings.append(routing)
|
||||
}
|
||||
print("V2rayRoutings-loadConfig", self.routings.count)
|
||||
}
|
||||
|
||||
static func isDefaultRule(name: String) -> Bool {
|
||||
return defaultRules.keys.contains(name)
|
||||
}
|
||||
|
||||
// get list from routing server list
|
||||
static func list() -> [RoutingItem] {
|
||||
return self.routings
|
||||
}
|
||||
|
||||
static func all() -> [RoutingItem] {
|
||||
// static reset
|
||||
var items : [RoutingItem] = []
|
||||
|
||||
// load name list from UserDefaults
|
||||
var list = UserDefaults.getArray(forKey: .routingCustomList)
|
||||
if list == nil {
|
||||
list = []
|
||||
}
|
||||
|
||||
// load each V2rayItem
|
||||
for item in list! {
|
||||
guard let routing = RoutingItem.load(name: item) else {
|
||||
// delete from UserDefaults
|
||||
RoutingItem.remove(name: item)
|
||||
continue
|
||||
}
|
||||
// append
|
||||
items.append(routing)
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
// get count from routing server list
|
||||
static func count() -> Int {
|
||||
return self.routings.count
|
||||
}
|
||||
|
||||
// move item to new index
|
||||
static func move(oldIndex: Int, newIndex: Int) {
|
||||
if !V2rayRoutings.routings.indices.contains(oldIndex) {
|
||||
NSLog("index out of range", oldIndex)
|
||||
return
|
||||
}
|
||||
if !V2rayRoutings.routings.indices.contains(newIndex) {
|
||||
NSLog("index out of range", newIndex)
|
||||
return
|
||||
}
|
||||
|
||||
let o = self.routings[oldIndex]
|
||||
self.routings.remove(at: oldIndex)
|
||||
self.routings.insert(o, at: newIndex)
|
||||
|
||||
// update server list UserDefaults
|
||||
self.saveItemList()
|
||||
}
|
||||
|
||||
// add routing server (by scan qrcode)
|
||||
static func add(remark: String, json: String) {
|
||||
var remark_ = remark
|
||||
if remark.count == 0 {
|
||||
remark_ = "new routing"
|
||||
}
|
||||
|
||||
// name is : routing. + uuid
|
||||
let name = "routing." + UUID().uuidString
|
||||
|
||||
let routing = RoutingItem(name: name, remark: remark_, json: json)
|
||||
// save to routing UserDefaults
|
||||
routing.store()
|
||||
|
||||
|
||||
// just add to mem
|
||||
self.routings.append(routing)
|
||||
print("routing", name, self.routings)
|
||||
|
||||
// update server list UserDefaults
|
||||
self.saveItemList()
|
||||
}
|
||||
|
||||
// remove routing server (tmp and UserDefaults and config json file)
|
||||
static func remove(idx: Int) {
|
||||
if !V2rayRoutings.routings.indices.contains(idx) {
|
||||
NSLog("index out of range", idx)
|
||||
return
|
||||
}
|
||||
|
||||
let routing = V2rayRoutings.routings[idx]
|
||||
|
||||
// delete from tmp
|
||||
self.routings.remove(at: idx)
|
||||
|
||||
// delete from routing UserDefaults
|
||||
RoutingItem.remove(name: routing.name)
|
||||
|
||||
// update server list UserDefaults
|
||||
self.saveItemList()
|
||||
|
||||
// if cuerrent item is default
|
||||
let curName = UserDefaults.get(forKey: .routingSelectedRule)
|
||||
if curName != nil && routing.name == curName {
|
||||
UserDefaults.del(forKey: .routingSelectedRule)
|
||||
}
|
||||
}
|
||||
|
||||
// update server list UserDefaults
|
||||
static func saveItemList() {
|
||||
var routingCustomList: Array<String> = []
|
||||
for item in V2rayRoutings.list() {
|
||||
routingCustomList.append(item.name)
|
||||
}
|
||||
|
||||
print("routingCustomList", routingCustomList);
|
||||
UserDefaults.setArray(forKey: .routingCustomList, value: routingCustomList)
|
||||
}
|
||||
|
||||
// load json file data
|
||||
static func load(idx: Int) -> RoutingItem? {
|
||||
if !V2rayRoutings.routings.indices.contains(idx) {
|
||||
NSLog("index out of range", idx)
|
||||
return nil
|
||||
}
|
||||
|
||||
return self.routings[idx]
|
||||
}
|
||||
|
||||
static func save(routing: RoutingItem) {
|
||||
// store
|
||||
routing.store()
|
||||
|
||||
// refresh data
|
||||
for (idx, item) in self.routings.enumerated() {
|
||||
if item.name == routing.name {
|
||||
self.routings[idx].remark = routing.remark
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get by name
|
||||
static func getIndex(name: String) -> Int {
|
||||
for (idx, item) in self.routings.enumerated() {
|
||||
if item.name == name {
|
||||
return idx
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
// ----- routing routing item -----
|
||||
class RoutingItem: NSObject, NSCoding {
|
||||
var name: String
|
||||
var remark: String
|
||||
var json: String
|
||||
var domainStrategy: String
|
||||
var block: String
|
||||
var proxy: String
|
||||
var direct: String
|
||||
|
||||
// Initializer
|
||||
init(name: String, remark: String, json: String = "", domainStrategy: String = "AsIs", block: String="", proxy: String="", direct: String="") {
|
||||
self.name = name
|
||||
self.remark = remark
|
||||
self.json = json
|
||||
self.domainStrategy = domainStrategy
|
||||
self.block = block
|
||||
self.proxy = proxy
|
||||
self.direct = direct
|
||||
}
|
||||
|
||||
// NSCoding required initializer (decoding)
|
||||
required init(coder decoder: NSCoder) {
|
||||
self.name = decoder.decodeObject(forKey: "Name") as? String ?? ""
|
||||
self.remark = decoder.decodeObject(forKey: "Remark") as? String ?? ""
|
||||
self.json = decoder.decodeObject(forKey: "Json") as? String ?? ""
|
||||
self.domainStrategy = decoder.decodeObject(forKey: "DomainStrategy") as? String ?? "AsIs"
|
||||
self.block = decoder.decodeObject(forKey: "Block") as? String ?? ""
|
||||
self.proxy = decoder.decodeObject(forKey: "Proxy") as? String ?? ""
|
||||
self.direct = decoder.decodeObject(forKey: "Direct") as? String ?? ""
|
||||
}
|
||||
|
||||
// NSCoding required method (encoding)
|
||||
func encode(with coder: NSCoder) {
|
||||
coder.encode(name, forKey: "Name")
|
||||
coder.encode(remark, forKey: "Remark")
|
||||
coder.encode(json, forKey: "Json")
|
||||
coder.encode(domainStrategy, forKey: "DomainStrategy")
|
||||
coder.encode(block, forKey: "Block")
|
||||
coder.encode(proxy, forKey: "Proxy")
|
||||
coder.encode(direct, forKey: "Direct")
|
||||
}
|
||||
|
||||
// Store into UserDefaults
|
||||
func store() {
|
||||
let modelData = NSKeyedArchiver.archivedData(withRootObject: self)
|
||||
UserDefaults.standard.set(modelData, forKey: self.name)
|
||||
}
|
||||
|
||||
func parseRule() -> V2rayRouting {
|
||||
if defaultRules.keys.contains(self.name) {
|
||||
return self.parseDefaultSettings()
|
||||
}
|
||||
let (res, err) = parseRoutingRuleJson(json: self.json)
|
||||
if err != nil {
|
||||
print("parseRule err", err)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// parse default settings
|
||||
func parseDefaultSettings() -> V2rayRouting {
|
||||
|
||||
var rules: [V2rayRoutingSettingRule] = []
|
||||
|
||||
let (blockDomains, blockIps) = parseDomainOrIp(domainIpStr: self.block)
|
||||
let (proxyDomains, proxyIps) = parseDomainOrIp(domainIpStr: self.proxy)
|
||||
let (directDomains, directIps) = parseDomainOrIp(domainIpStr: self.direct)
|
||||
|
||||
// // rules
|
||||
var ruleProxyDomain, ruleProxyIp, ruleDirectDomain, ruleDirectIp, ruleBlockDomain, ruleBlockIp, ruleDirectIpDefault, ruleDirectDomainDefault: V2rayRoutingSettingRule?
|
||||
// proxy
|
||||
if proxyDomains.count > 0 {
|
||||
ruleProxyDomain = getRoutingRule(outTag: "proxy", domain: proxyDomains, ip: nil, port: nil)
|
||||
}
|
||||
if proxyIps.count > 0 {
|
||||
ruleProxyIp = getRoutingRule(outTag: "proxy", domain: nil, ip: proxyIps, port: nil)
|
||||
}
|
||||
|
||||
// direct
|
||||
if directDomains.count > 0 {
|
||||
ruleDirectDomain = getRoutingRule(outTag: "direct", domain: directDomains, ip: nil, port: nil)
|
||||
}
|
||||
if directIps.count > 0 {
|
||||
ruleDirectIp = getRoutingRule(outTag: "direct", domain: nil, ip: directIps, port: nil)
|
||||
}
|
||||
|
||||
// block
|
||||
if blockDomains.count > 0 {
|
||||
ruleBlockDomain = getRoutingRule(outTag: "block", domain: blockDomains, ip: nil, port: nil)
|
||||
}
|
||||
if blockIps.count > 0 {
|
||||
ruleBlockIp = getRoutingRule(outTag: "block", domain: nil, ip: blockIps, port: nil)
|
||||
}
|
||||
|
||||
switch self.name {
|
||||
case RoutingRuleGlobal:
|
||||
break
|
||||
case RoutingRuleLAN:
|
||||
ruleDirectIpDefault = getRoutingRule(outTag: "direct", domain: nil, ip: ["geoip:private"], port: nil)
|
||||
ruleDirectDomainDefault = getRoutingRule(outTag: "direct", domain: ["localhost"], ip: nil, port: nil)
|
||||
break
|
||||
case RoutingRuleCn:
|
||||
ruleDirectIpDefault = getRoutingRule(outTag: "direct", domain: nil, ip: ["geoip:cn"], port: nil)
|
||||
ruleDirectDomainDefault = getRoutingRule(outTag: "direct", domain: ["geosite:cn"], ip: nil, port: nil)
|
||||
break
|
||||
case RoutingRuleLANAndCn:
|
||||
ruleDirectIpDefault = getRoutingRule(outTag: "direct", domain: nil, ip: ["geoip:cn","geoip:private"], port: nil)
|
||||
ruleDirectDomainDefault = getRoutingRule(outTag: "direct", domain: ["geosite:cn","localhost"], ip: nil, port: nil)
|
||||
break
|
||||
default: break
|
||||
|
||||
}
|
||||
// 域名阻断 -> 域名代理 -> 域名直连 -> IP阻断 -> IP代理 -> IP直连 的优先级进行匹配
|
||||
|
||||
// 域名阻断
|
||||
if ruleBlockDomain != nil {
|
||||
ruleBlockDomain?.ip = nil
|
||||
rules.append(ruleBlockDomain!)
|
||||
}
|
||||
// 域名代理
|
||||
if ruleProxyDomain != nil {
|
||||
ruleProxyDomain?.ip = nil
|
||||
rules.append(ruleProxyDomain!)
|
||||
}
|
||||
// 域名直连
|
||||
if ruleDirectDomain != nil {
|
||||
ruleDirectDomain!.ip = nil
|
||||
rules.append(ruleDirectDomain!)
|
||||
}
|
||||
// IP阻断
|
||||
if ruleBlockIp != nil {
|
||||
ruleBlockIp!.domain = nil
|
||||
rules.append(ruleBlockIp!)
|
||||
}
|
||||
// IP代理
|
||||
if ruleProxyIp != nil {
|
||||
ruleProxyIp!.domain = nil
|
||||
rules.append(ruleProxyIp!)
|
||||
}
|
||||
// IP直连
|
||||
if ruleDirectIp != nil {
|
||||
ruleDirectIp!.domain = nil
|
||||
rules.append(ruleDirectIp!)
|
||||
}
|
||||
// 如果匹配失败,则私有地址和大陆境内地址直连,否则走代理。
|
||||
if ruleDirectIpDefault != nil {
|
||||
ruleDirectIpDefault!.domain = nil
|
||||
rules.append(ruleDirectIpDefault!)
|
||||
}
|
||||
if ruleDirectDomainDefault != nil {
|
||||
ruleDirectDomainDefault!.ip = nil
|
||||
rules.append(ruleDirectDomainDefault!)
|
||||
}
|
||||
// 默认全部代理, 无需设置规则
|
||||
var settings = V2rayRouting()
|
||||
if V2rayRouting.domainStrategy(rawValue: self.domainStrategy) == nil {
|
||||
settings.domainStrategy = .AsIs
|
||||
} else {
|
||||
settings.domainStrategy = V2rayRouting.domainStrategy(rawValue: self.domainStrategy) ?? .AsIs
|
||||
}
|
||||
settings.rules = rules
|
||||
return settings
|
||||
}
|
||||
|
||||
func getRoutingRule(outTag: String, domain:[String]?, ip: [String]?, port:String?) -> V2rayRoutingSettingRule {
|
||||
var rule = V2rayRoutingSettingRule()
|
||||
rule.outboundTag = outTag
|
||||
rule.type = "field"
|
||||
rule.domain = domain
|
||||
rule.ip = ip
|
||||
rule.port = port
|
||||
return rule
|
||||
}
|
||||
|
||||
func parseDomainOrIp(domainIpStr: String) -> (domains: [String], ips: [String]) {
|
||||
let all = domainIpStr.split(separator: "\n")
|
||||
|
||||
var domains: [String] = []
|
||||
var ips: [String] = []
|
||||
|
||||
for item in all {
|
||||
let tmp = item.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
|
||||
// is ip
|
||||
if isIp(str: tmp) || tmp.contains("geoip:") {
|
||||
ips.append(tmp)
|
||||
continue
|
||||
}
|
||||
|
||||
// is domain
|
||||
if tmp.contains("domain:") || tmp.contains("geosite:") {
|
||||
domains.append(tmp)
|
||||
continue
|
||||
}
|
||||
|
||||
if isDomain(str: tmp) {
|
||||
domains.append(tmp)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
print("ips", ips, "domains", domains)
|
||||
|
||||
return (domains, ips)
|
||||
}
|
||||
|
||||
func isIp(str: String) -> Bool {
|
||||
let pattern = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(/[0-9]{2})?$"
|
||||
if ((str.count == 0) || (str.range(of: pattern, options: .regularExpression) == nil)) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func isDomain(str: String) -> Bool {
|
||||
let pattern = "[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+"
|
||||
if ((str.count == 0) || (str.range(of: pattern, options: .regularExpression) == nil)) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// static load from UserDefaults
|
||||
static func load(name: String) -> RoutingItem? {
|
||||
guard let myModelData = UserDefaults.standard.data(forKey: name) else {
|
||||
print("load userDefault not found:",name)
|
||||
return nil
|
||||
}
|
||||
do {
|
||||
// unarchivedObject(ofClass:from:)
|
||||
let result = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(myModelData)
|
||||
return result as? RoutingItem
|
||||
} catch let error {
|
||||
print("load userDefault error:", error)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// remove from UserDefaults
|
||||
static func remove(name: String) {
|
||||
UserDefaults.standard.removeObject(forKey: name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// parse json to V2rayRouting
|
||||
func parseRoutingRuleJson(json: String) -> (V2rayRouting, err: Error?) {
|
||||
// utf8
|
||||
let jsonData = json.data(using: String.Encoding.utf8, allowLossyConversion: false)
|
||||
if jsonData == nil {
|
||||
return (V2rayRouting(), nil)
|
||||
}
|
||||
let jsonDecoder = JSONDecoder()
|
||||
var res = V2rayRouting()
|
||||
var err: Error?
|
||||
do {
|
||||
res = try jsonDecoder.decode(V2rayRouting.self, from: jsonData!)
|
||||
} catch let error {
|
||||
print("parseJson err",error)
|
||||
err = error
|
||||
}
|
||||
return (res, err)
|
||||
}
|
||||
@@ -81,13 +81,6 @@ let jsSourceFormatConfig =
|
||||
|
||||
|
||||
class V2rayConfig: NSObject {
|
||||
// routing rule tag
|
||||
enum RoutingRule: Int {
|
||||
case RoutingRuleGlobal = 0 // Global
|
||||
case RoutingRuleLAN = 1 // Bypassing the LAN Address
|
||||
case RoutingRuleCn = 2 // Bypassing mainland address
|
||||
case RoutingRuleLANAndCn = 3 // Bypassing LAN and mainland address
|
||||
}
|
||||
|
||||
var v2ray: V2rayStruct = V2rayStruct()
|
||||
var isValid = false
|
||||
@@ -131,15 +124,6 @@ class V2rayConfig: NSObject {
|
||||
var streamSecurity = "none" // none|tls|xtls|reality
|
||||
var securityTls = TlsSettings() // tls|xtls
|
||||
var securityReality = RealitySettings() // reality
|
||||
|
||||
var routingDomainStrategy: V2rayRoutingSetting.domainStrategy = .AsIs
|
||||
var routingRule: RoutingRule = .RoutingRuleGlobal
|
||||
let routingProxyDomains = UserDefaults.getArray(forKey: .routingProxyDomains) ?? [];
|
||||
let routingProxyIps = UserDefaults.getArray(forKey: .routingProxyIps) ?? [];
|
||||
let routingDirectDomains = UserDefaults.getArray(forKey: .routingDirectDomains) ?? [];
|
||||
let routingDirectIps = UserDefaults.getArray(forKey: .routingDirectIps) ?? [];
|
||||
let routingBlockDomains = UserDefaults.getArray(forKey: .routingBlockDomains) ?? [];
|
||||
let routingBlockIps = UserDefaults.getArray(forKey: .routingBlockIps) ?? [];
|
||||
|
||||
private var foundHttpPort = false
|
||||
private var foundSockPort = false
|
||||
@@ -161,10 +145,6 @@ class V2rayConfig: NSObject {
|
||||
self.mux = Int(UserDefaults.get(forKey: .muxConcurrent) ?? "8") ?? 8
|
||||
|
||||
self.logLevel = UserDefaults.get(forKey: .v2rayLogLevel) ?? "info"
|
||||
|
||||
// routing
|
||||
self.routingDomainStrategy = V2rayRoutingSetting.domainStrategy(rawValue: UserDefaults.get(forKey: .routingDomainStrategy) ?? "AsIs") ?? .AsIs
|
||||
self.routingRule = RoutingRule(rawValue: Int(UserDefaults.get(forKey: .routingRule) ?? "0") ?? 0) ?? .RoutingRuleGlobal
|
||||
}
|
||||
|
||||
// combine manual edited data
|
||||
@@ -292,112 +272,14 @@ class V2rayConfig: NSObject {
|
||||
// ------------------------------------- outbound end ---------------------------------------------
|
||||
|
||||
// ------------------------------------- routing start --------------------------------------------
|
||||
|
||||
self.routing.settings.domainStrategy = self.routingDomainStrategy
|
||||
var rules: [V2rayRoutingSettingRule] = []
|
||||
|
||||
// rules
|
||||
var ruleProxyDomain, ruleProxyIp, ruleDirectDomain, ruleDirectIp, ruleBlockDomain, ruleBlockIp, ruleDirectIpDefault, ruleDirectDomainDefault: V2rayRoutingSettingRule?
|
||||
print("ruleBlockDomain",self.routingBlockDomains)
|
||||
// proxy
|
||||
if self.routingProxyDomains.count > 0 {
|
||||
ruleProxyDomain = getRoutingRule(outTag: "proxy", domain: self.routingProxyDomains, ip: nil, port: nil)
|
||||
let routingRule = UserDefaults.get(forKey: .routingSelectedRule) ?? RoutingRuleGlobal
|
||||
let rule = RoutingItem.load(name: routingRule)
|
||||
if rule != nil{
|
||||
self.v2ray.routing = rule!.parseRule()
|
||||
}
|
||||
if self.routingProxyIps.count > 0 {
|
||||
ruleProxyIp = getRoutingRule(outTag: "proxy", domain: nil, ip: self.routingProxyIps, port: nil)
|
||||
}
|
||||
|
||||
// direct
|
||||
if self.routingDirectDomains.count > 0 {
|
||||
ruleDirectDomain = getRoutingRule(outTag: "direct", domain: self.routingDirectDomains, ip: nil, port: nil)
|
||||
}
|
||||
if self.routingDirectIps.count > 0 {
|
||||
ruleDirectIp = getRoutingRule(outTag: "direct", domain: nil, ip: self.routingDirectIps, port: nil)
|
||||
}
|
||||
|
||||
// block
|
||||
if self.routingBlockDomains.count > 0 {
|
||||
ruleBlockDomain = getRoutingRule(outTag: "block", domain: self.routingBlockDomains, ip: nil, port: nil)
|
||||
}
|
||||
if self.routingBlockIps.count > 0 {
|
||||
ruleBlockIp = getRoutingRule(outTag: "block", domain: nil, ip: self.routingBlockIps, port: nil)
|
||||
}
|
||||
|
||||
switch self.routingRule {
|
||||
case .RoutingRuleGlobal:
|
||||
break
|
||||
case .RoutingRuleLAN:
|
||||
ruleDirectIpDefault = getRoutingRule(outTag: "direct", domain: nil, ip: ["geoip:private"], port: nil)
|
||||
ruleDirectDomainDefault = getRoutingRule(outTag: "direct", domain: ["localhost"], ip: nil, port: nil)
|
||||
break
|
||||
case .RoutingRuleCn:
|
||||
ruleDirectIpDefault = getRoutingRule(outTag: "direct", domain: nil, ip: ["geoip:cn"], port: nil)
|
||||
ruleDirectDomainDefault = getRoutingRule(outTag: "direct", domain: ["geosite:cn"], ip: nil, port: nil)
|
||||
break
|
||||
case .RoutingRuleLANAndCn:
|
||||
ruleDirectIpDefault = getRoutingRule(outTag: "direct", domain: nil, ip: ["geoip:cn","geoip:private"], port: nil)
|
||||
ruleDirectDomainDefault = getRoutingRule(outTag: "direct", domain: ["geosite:cn","localhost"], ip: nil, port: nil)
|
||||
break
|
||||
}
|
||||
// 域名阻断 -> 域名代理 -> 域名直连 -> IP阻断 -> IP代理 -> IP直连 的优先级进行匹配
|
||||
|
||||
// 域名阻断
|
||||
if ruleBlockDomain != nil {
|
||||
ruleBlockDomain?.ip = nil
|
||||
rules.append(ruleBlockDomain!)
|
||||
}
|
||||
// 域名代理
|
||||
if ruleProxyDomain != nil {
|
||||
ruleProxyDomain?.ip = nil
|
||||
rules.append(ruleProxyDomain!)
|
||||
}
|
||||
// 域名直连
|
||||
if ruleDirectDomain != nil {
|
||||
ruleDirectDomain!.ip = nil
|
||||
rules.append(ruleDirectDomain!)
|
||||
}
|
||||
// IP阻断
|
||||
if ruleBlockIp != nil {
|
||||
ruleBlockIp!.domain = nil
|
||||
rules.append(ruleBlockIp!)
|
||||
}
|
||||
// IP代理
|
||||
if ruleProxyIp != nil {
|
||||
ruleProxyIp!.domain = nil
|
||||
rules.append(ruleProxyIp!)
|
||||
}
|
||||
// IP直连
|
||||
if ruleDirectIp != nil {
|
||||
ruleDirectIp!.domain = nil
|
||||
rules.append(ruleDirectIp!)
|
||||
}
|
||||
// 如果匹配失败,则私有地址和大陆境内地址直连,否则走代理。
|
||||
if ruleDirectIpDefault != nil {
|
||||
ruleDirectIpDefault!.domain = nil
|
||||
rules.append(ruleDirectIpDefault!)
|
||||
}
|
||||
if ruleDirectDomainDefault != nil {
|
||||
ruleDirectDomainDefault!.ip = nil
|
||||
rules.append(ruleDirectDomainDefault!)
|
||||
}
|
||||
// 默认全部代理, 无需设置规则
|
||||
// 代理规则
|
||||
self.routing.settings.rules = rules
|
||||
// set v2ray routing
|
||||
self.v2ray.routing = self.routing
|
||||
// ------------------------------------- routing end ----------------------------------------------
|
||||
}
|
||||
|
||||
func getRoutingRule(outTag: String, domain:[String]?, ip: [String]?, port:String?) -> V2rayRoutingSettingRule {
|
||||
var rule = V2rayRoutingSettingRule()
|
||||
rule.outboundTag = outTag
|
||||
rule.type = "field"
|
||||
rule.domain = domain
|
||||
rule.ip = ip
|
||||
rule.port = port
|
||||
return rule
|
||||
}
|
||||
|
||||
func checkManualValid() {
|
||||
defer {
|
||||
if self.error != "" {
|
||||
|
||||
@@ -60,11 +60,6 @@ struct V2rayStats: Codable {
|
||||
}
|
||||
|
||||
struct V2rayRouting: Codable {
|
||||
// var strategy: String = "rules"
|
||||
var settings: V2rayRoutingSetting = V2rayRoutingSetting()
|
||||
}
|
||||
|
||||
struct V2rayRoutingSetting: Codable {
|
||||
enum domainStrategy: String, Codable {
|
||||
case AsIs
|
||||
case IPIfNonMatch
|
||||
|
||||
Reference in New Issue
Block a user