Files
ShadowsocksX-NG/ShadowsocksX-NG2/App/UI/Workspace/WorkspaceRoute.swift
T
Qiu Yuzhou fb428f12bc refactor(app): 按分层重组 App/ 源码目录
App/ 根目录原有 73 个散落源文件,已无法从目录读出任何分组信息。

按「目录即分层」重组为 Composition / Application / Presentation / UI /
PlatformEffects / Resources 六个目录,UI 层再按子视图分目录(Workspace、
Home、Servers(含 Plugin)、Subscriptions、Rules、Settings、Diagnostics、
StatusMenu)。纯移动:类型名、模块名与 import 均未改动,App/ 根层不再有
散落文件。

配套改动:

- project.yml:Core 测试镜像的 excludes 由裸文件名改为 `**/` 递归形式。
  XcodeGen 的 exclude 不跨 `/`,裸名只匹配 App 根层;MainApp.swift 下移后
  旧写法会静默失效,把 @main 组合根编进测试镜像。info.path 与
  entitlements.path 指向 App/Resources/;并排除 `**/*.md`——App/ 下任何
  非源码文件都会被 XcodeGen 收进 Resources 阶段并封进签名后的 bundle。
- SkeletonTests 的架构守卫由「默认扫描全部 App/ + 7 个豁免文件 + 1 个豁免
  前缀 + 4 个豁免目录」改为正面圈定 App/UI/,豁免登记全部删除;新增运行时
  适配器放进 Application/ 即自动落在扫描范围外,无需再登记。
- README 工程结构说明同步;根 .gitignore 的生成物路径随 Resources/ 归位。

验证:clean build 0 error;task test 1022 用例全通过(含两个架构守卫);
task format 无改动(证明纯移动);task lint 与移动前同为 21 条内容型
warning;packaging-gate.sh ALL CHECKS PASSED,确认 plist/entitlements 归位
后签名与 entitlements 语义不变。

注意:迁移时须先删旧的生成物再 xcodegen generate,否则遗留的 App/Info.plist
会被当作普通资源扫进 Resources 阶段。
2026-10-05 19:56:18 +08:00

44 lines
2.0 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Combine
/// 单一主 workspace 的有限 destination 词汇。它只描述导航位置,不携带功能区
/// 的选择、sheet、alert 或编辑草稿。
enum WorkspaceDestination: String, CaseIterable, Hashable, Identifiable, Sendable {
case home
case servers
case subscriptions
case rules
case settings
case diagnostics
var id: Self { self }
}
/// workspace route module:集中 destination 与 workspace 内部导航。路由状态
/// 只存在于进程内,新实例始终从 home 开始。主窗口的呈现:启动由 Window
/// scene 的 defaultLaunchBehavior(.presented) 自动呈现,关窗后由状态菜单经
/// SwiftUI `openWindow` 重开(scene id 单点定义见 workspaceSceneID);本
/// module 不依赖任何 UI framework,也不持有开窗 effect。
@MainActor
final class WorkspaceRoute: ObservableObject {
/// 主 workspace 的 SwiftUI `Window` scene id:scene 在组合根(MainApp)
/// 以此常量声明,状态菜单是关窗后的重开入口。字面量单点定义在此,防
/// scene id 散落(架构测试锚定)。
static let workspaceSceneID = "workspace"
/// 实例初始 destination。MainWindowView 侧栏 @State 选中项的初值须与此
/// 对齐,否则首帧侧栏无高亮行。
static let initialDestination: WorkspaceDestination = .home
@Published private(set) var destination: WorkspaceDestination = initialDestination
/// workspace 内部导航只改变 route destination;开窗不由 route 驱动。
/// 同值导航必须是无操作:外部导航经 onChange 回填侧栏选中项后会再触发
/// 一次 selection onChange(导航回声),由同值短路变成无操作;publish
/// 一旦发生在视图更新期间(List/NavigationSplitView 的选择再同步回写)
/// 会触发 "Publishing changes from within view updates" 运行时警告。
func navigate(to destination: WorkspaceDestination) {
guard destination != self.destination else { return }
self.destination = destination
}
}