mirror of
https://github.com/shadowsocks/ShadowsocksX-NG.git
synced 2026-11-15 18:59:52 +00:00
67 lines
2.2 KiB
Swift
67 lines
2.2 KiB
Swift
import Combine
|
|
|
|
/// 单一主 workspace 的有限 destination 词汇。它只描述导航位置,不携带功能区
|
|
/// 的选择、sheet、alert 或编辑草稿。
|
|
enum WorkspaceDestination: String, CaseIterable, Hashable, Identifiable, Sendable {
|
|
case home
|
|
case servers
|
|
case subscriptions
|
|
case settings
|
|
case diagnostics
|
|
|
|
var id: Self { self }
|
|
}
|
|
|
|
/// workspace 的跨入口意图。呈现意图会要求主 workspace 可见;workspace 内部
|
|
/// 导航只改变 destination,不重复执行窗口 effect。
|
|
enum WorkspaceRouteIntent: Equatable, Sendable {
|
|
case launch(legacyImportOffer: Bool)
|
|
case navigate(destination: WorkspaceDestination)
|
|
case present(destination: WorkspaceDestination)
|
|
case reopen
|
|
}
|
|
|
|
/// 窄的开窗 seam。实现可以连接 SwiftUI `openWindow` 或 AppKit 生命周期,route
|
|
/// module 本身不依赖任一 UI framework。
|
|
@MainActor
|
|
protocol WorkspaceWindowOpening {
|
|
func ensureWorkspaceVisible()
|
|
}
|
|
|
|
/// workspace route module:集中 destination、启动 policy、恢复 policy 与跨入口
|
|
/// intent 协调。路由状态只存在于进程内,新实例始终从 home 开始。
|
|
@MainActor
|
|
final class WorkspaceRoute: ObservableObject {
|
|
@Published private(set) var destination: WorkspaceDestination = .home
|
|
|
|
private var didApplyLaunchPolicy = false
|
|
|
|
/// workspace 内部导航只改变 route destination,不请求新的窗口呈现。
|
|
func navigate(to destination: WorkspaceDestination) {
|
|
self.destination = destination
|
|
}
|
|
|
|
/// 应用一个 route intent,并在需要时请求主 workspace 可见。
|
|
/// destination 总是在开窗 effect 之前更新,避免窗口先呈现旧位置再纠正。
|
|
func handle(
|
|
_ intent: WorkspaceRouteIntent,
|
|
using windowOpening: any WorkspaceWindowOpening
|
|
) {
|
|
switch intent {
|
|
case .launch(let legacyImportOffer):
|
|
guard !didApplyLaunchPolicy else { return }
|
|
didApplyLaunchPolicy = true
|
|
if legacyImportOffer {
|
|
windowOpening.ensureWorkspaceVisible()
|
|
}
|
|
case .navigate(let destination):
|
|
navigate(to: destination)
|
|
case .present(let destination):
|
|
self.destination = destination
|
|
windowOpening.ensureWorkspaceVisible()
|
|
case .reopen:
|
|
windowOpening.ensureWorkspaceVisible()
|
|
}
|
|
}
|
|
}
|