mirror of
https://github.com/shadowsocks/ShadowsocksX-NG.git
synced 2026-11-14 18:23:50 +00:00
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 阶段。
44 lines
2.0 KiB
Swift
44 lines
2.0 KiB
Swift
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
|
||
}
|
||
}
|