mirror of
https://github.com/shadowsocks/ShadowsocksX-NG.git
synced 2026-10-31 14:53:49 +00:00
feat(rules): reorder presets and default to GFWList
This commit is contained in:
@@ -74,7 +74,7 @@ struct ProxyControlSnapshot: Equatable, Sendable {
|
||||
/// 当前已应用的代理模式(持久化成功的模式)。
|
||||
let proxyMode: ProxyMode
|
||||
/// 规则模式子选项:未匹配默认动作;仅规则模式呈现。
|
||||
var rulePreset: RulePreset = .chinaDirect
|
||||
var rulePreset: RulePreset = .gfwlist
|
||||
var ruleDefaultAction: RuleDefaultAction { rulePreset.defaultAction }
|
||||
/// 可用模式由 Domain 单点策略投影;UI 不自行判断可用性。
|
||||
let availableModes: [ProxyMode]
|
||||
|
||||
@@ -23,7 +23,7 @@ final class RulesWorkflow: ObservableObject {
|
||||
private let analysisDelay: @Sendable () async throws -> Void
|
||||
|
||||
init(
|
||||
preset: RulePreset = .chinaDirect,
|
||||
preset: RulePreset = .gfwlist,
|
||||
loadCustom: (@Sendable () throws -> [CustomRule])? = nil,
|
||||
loadDocument: (@MainActor () throws -> CustomRuleDocument)? = nil,
|
||||
commitDocument: (@MainActor (CustomRuleDocument) async -> RuleDocumentCommit)? = nil,
|
||||
|
||||
@@ -4,7 +4,7 @@ import Foundation
|
||||
/// Each preset owns an unchanged workflow, including its in-flight operations.
|
||||
@MainActor
|
||||
final class RulesWorkspaces: ObservableObject {
|
||||
@Published var selectedPreset: RulePreset = .chinaDirect
|
||||
@Published var selectedPreset: RulePreset = .gfwlist
|
||||
@Published private(set) var reportSource: RulesSourceSnapshot?
|
||||
private let workflows: [RulePreset: RulesWorkflow]
|
||||
private var reports: Set<AnyCancellable> = []
|
||||
|
||||
@@ -117,8 +117,8 @@ actor BuiltinRuleSnapshots {
|
||||
|
||||
/// The same policy supplies runtime candidates and the management collection.
|
||||
enum RulePreset: String, Codable, CaseIterable, Hashable, Sendable {
|
||||
case chinaDirect = "china-direct"
|
||||
case gfwlist = "gfwlist"
|
||||
case chinaDirect = "china-direct"
|
||||
case chinaProxy = "china-proxy"
|
||||
|
||||
init(legacy action: RuleDefaultAction) {
|
||||
|
||||
@@ -23,7 +23,7 @@ struct ProxyControlPreferences {
|
||||
}
|
||||
let legacy =
|
||||
defaults.string(forKey: "proxyControl.ruleDefaultAction")
|
||||
.flatMap(RuleDefaultAction.init(rawValue:)) ?? .proxyWhenUnmatched
|
||||
.flatMap(RuleDefaultAction.init(rawValue:)) ?? .directWhenUnmatched
|
||||
return RulePreset(legacy: legacy)
|
||||
}
|
||||
nonmutating set { defaults.set(newValue.rawValue, forKey: "proxyControl.rulePreset") }
|
||||
|
||||
@@ -11,7 +11,7 @@ struct ProxyRuntimeSettings: Equatable, Sendable {
|
||||
/// The persisted current mode: the mode selector's choice survives GUI
|
||||
/// restarts. First run defaults to rule mode.
|
||||
var preferredMode: ProxyModeKind
|
||||
/// 规则模式预设,出厂为中国大陆目标直连。
|
||||
/// 规则模式预设,首次启动默认为仅 GFW 列表内目标代理。
|
||||
var rulePreset: RulePreset
|
||||
var ruleDefaultAction: RuleDefaultAction {
|
||||
get { rulePreset.defaultAction }
|
||||
@@ -27,7 +27,7 @@ struct ProxyRuntimeSettings: Equatable, Sendable {
|
||||
listen: ProxyListeningConfiguration = ProxyListeningConfiguration(),
|
||||
proxyExceptions: String = ProxyRuntimeSettings.defaultProxyExceptions,
|
||||
preferredMode: ProxyModeKind = .rule,
|
||||
ruleDefaultAction: RuleDefaultAction = .proxyWhenUnmatched,
|
||||
ruleDefaultAction: RuleDefaultAction = .directWhenUnmatched,
|
||||
rulePreset: RulePreset? = nil,
|
||||
agentEnabled: Bool = false,
|
||||
systemProxyEnabled: Bool = false
|
||||
|
||||
@@ -93,7 +93,7 @@ extension RulePresetWorkflowTests {
|
||||
let defaults = try #require(UserDefaults(suiteName: suite))
|
||||
defer { defaults.removePersistentDomain(forName: suite) }
|
||||
let preferences = ProxyControlPreferences(defaults: defaults)
|
||||
#expect(preferences.rulePreset == .chinaDirect)
|
||||
#expect(preferences.rulePreset == .gfwlist)
|
||||
defaults.set("direct-when-unmatched", forKey: "proxyControl.ruleDefaultAction")
|
||||
#expect(preferences.rulePreset == .gfwlist)
|
||||
preferences.rulePreset = .chinaProxy
|
||||
|
||||
@@ -16,7 +16,7 @@ struct ProxyControlPreferencesTests {
|
||||
preferences: ProxyControlPreferences(defaults: defaults))
|
||||
|
||||
#expect(settings.preferredMode == .rule)
|
||||
#expect(settings.ruleDefaultAction == .proxyWhenUnmatched)
|
||||
#expect(settings.ruleDefaultAction == .directWhenUnmatched)
|
||||
#expect(!settings.agentEnabled)
|
||||
#expect(!settings.systemProxyEnabled)
|
||||
#expect(settings.proxyExceptions.isEmpty)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# 将隐式路由策略显式建模为规则预设
|
||||
|
||||
**状态**:已接受,已实现(2026-10-24)。
|
||||
**状态**:已接受,已实现(2026-10-24;默认项与展示顺序于 2026-10-25 调整)。
|
||||
|
||||
## 决定
|
||||
|
||||
规则、全局、直连仍是代理模式。规则模式内使用三种规则预设:“中国大陆目标直连”“仅GFW列表内目标代理”“中国大陆目标代理”。预设一起确定内置来源、命中行动和默认动作,替代原来的默认动作选择入口,不另设独立默认动作开关。新预设复用中国域名、`.cn` 和中国 IPv4 数据,将其用于代理,其余目标默认直连;固定本地目标仍直连,不维护视频专用集合,也不承诺平台内容可播放。
|
||||
规则、全局、直连仍是代理模式。规则模式内使用三种规则预设,展示顺序为“仅GFW列表内目标代理”“中国大陆目标直连”“中国大陆目标代理”。预设一起确定内置来源、命中行动和默认动作,替代原来的默认动作选择入口,不另设独立默认动作开关。新预设复用中国域名、`.cn` 和中国 IPv4 数据,将其用于代理,其余目标默认直连;固定本地目标仍直连,不维护视频专用集合,也不承诺平台内容可播放。
|
||||
|
||||
每项预设独立拥有自定义规则集合和规则停用选择。自定义规则保留自身行动,沿用现有冲突机制,用于补充规则而不保证覆盖内置规则。预设内继续使用“匹配条件+行动”的规则身份及跨来源停用语义,修改不影响其他预设。不增加共享自定义层或同一条目的多预设归属。
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
地址测试依据所选预设的完整规则和默认动作解释代理或直连结论,区分规则命中与未匹配时采用默认动作,并展示决定行动的规则。结果不受搜索、过滤、实际代理模式或运行状态影响,不要求该预设正在使用。测试输入和结果按预设独立保留;测试不解析 DNS、不测试连通性,域名测试明确说明未检查 DNS 解析后的 IP 规则。
|
||||
|
||||
保留原出厂默认及已有的路由选择映射。旧自定义规则和规则启用/禁用用户配置均不迁移,不按行动拆分,也不复制到新预设。新预设工作区不继承旧自定义条目或旧停用选择,按默认启用状态初始化;发版时明确说明这两项不兼容变化。
|
||||
没有显式保存的预设或旧版默认动作偏好时,默认选第一项“仅GFW列表内目标代理”;显式保存的预设继续生效,旧版默认动作继续映射到等价预设。旧自定义规则和规则启用/禁用用户配置均不迁移,不按行动拆分,也不复制到新预设。新预设工作区不继承旧自定义条目或旧停用选择,按默认启用状态初始化;发版时明确说明这两项不兼容变化。
|
||||
|
||||
## 取舍与替代
|
||||
|
||||
|
||||
Reference in New Issue
Block a user