Files
Qiu Yuzhou f6abd4343e feat(rules)!: add isolated routing presets
Add Mainland China proxy routing with independent rule workspaces.
Preserve existing routing choices through equivalent preset mappings.

BREAKING CHANGE: existing custom rules and enablement settings are
not migrated. Recreate them in the appropriate preset.
2026-10-25 14:32:12 +08:00

65 lines
2.2 KiB
Swift

import SwiftUI
struct RulesSourceSummaryView: View {
let source: RulesSourceSnapshot
let openReport: () -> Void
var body: some View {
if let metadata = source.metadata {
VStack(alignment: .leading, spacing: 6) {
Text(verbatim: String(metadata.source.upstreamVersion.prefix(12)))
.help(metadata.source.upstreamVersion)
Text(verbatim: metadata.license)
if source.conversionReport != nil {
Button(RulesCopy.text("快照制作时的转换报告"), action: openReport)
.fixedSize(horizontal: false, vertical: true)
}
}
.font(.caption)
.frame(maxWidth: .infinity, alignment: .leading)
.textSelection(.enabled)
}
}
}
struct RulesReportView: View {
static let sceneID = "rules-conversion-report"
@ObservedObject var workflow: RulesWorkspaces
var body: some View {
ScrollView {
if let source = workflow.reportSource, let metadata = source.metadata {
VStack(alignment: .leading, spacing: 12) {
Text(verbatim: "\(source.id.label) · \(metadata.source.upstreamVersion)")
Text(verbatim: metadata.upstreamReference)
Text(verbatim: "\(metadata.license) · \(metadata.attribution)")
if let report = source.conversionReport {
Divider()
Text(verbatim: "\(RulesCopy.text("已转换")): \(report.convertedCount)")
Text(verbatim: "\(RulesCopy.text("已吸收")): \(report.absorbedCount)")
counts(report.skipped, label: RulesCopy.text("已跳过"))
counts(report.rejected, label: RulesCopy.text("已拒绝"))
}
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
.textSelection(.enabled)
}
}
.navigationTitle(
(workflow.reportSource?.id.label ?? "") + " · " + RulesCopy.text("快照制作时的转换报告")
)
.frame(minWidth: 480, minHeight: 320)
}
private func counts(_ values: [String: Int], label: String) -> some View {
VStack(alignment: .leading, spacing: 4) {
Text(verbatim: label)
ForEach(values.keys.sorted(), id: \.self) { key in
Text(verbatim: "\(key): \(values[key, default: 0])")
}
if values.isEmpty { Text(verbatim: "0") }
}
}
}