Files
ShadowsocksX-NG/ShadowsocksX-NG2/App/MoveNodeSheet.swift
T
Qiu Yuzhou 5968b1fd0b feat(import): 统一服务器导入入口并支持 SIP-008 文件导入
新增统一导入面板(拖放多文件/剪贴板 ss:// 一键/旧版直接导入),来源按内容
嗅探分派(位图→二维码、JSON→SIP-008、其余→文本行),逐来源独立事务与
结果。深模块集中在 CatalogWorkflow.importServers 单一接缝,凭据统一经
journal,退役 ss:// 文本框、二维码预览、Legacy 专属 sheet 与首启主动弹窗。
SIP-008 导入语义见 ADR-0027(文档 ID 只作装配键,目录身份全新生成)。
2026-10-04 21:45:20 +08:00

63 lines
1.6 KiB
Swift

import SwiftUI
/// 「移动到」表单(issue #41):目的地由 seam 的 `moveDestinations` 提供——
/// 目录根与除自身子树外的全部手动组;跨来源与成环由领域层最终拒绝。
struct MoveNodeSheet: View {
let workflow: CatalogWorkflow
let errors: ErrorAlertPresenter
let nodeID: NodeID
@Environment(\.dismiss) private var dismiss
@State private var destination: NodeID?
private struct Destination: Identifiable {
let id: NodeID?
let title: String
}
private var destinations: [Destination] {
workflow.moveDestinations(for: nodeID).map { item in
let indent = String(repeating: " ", count: item.depth)
return Destination(id: item.id, title: indent + item.name)
}
}
var body: some View {
VStack(alignment: .leading, spacing: 12) {
Text("把「\(workflow.displayName(for: nodeID))」移动到:")
.font(.callout)
Picker(
"目的地",
selection: Binding(
get: { destination ?? destinations.first?.id },
set: { destination = $0 }
)
) {
ForEach(destinations) { target in
Text(target.title).tag(target.id as NodeID?)
}
}
.pickerStyle(.radioGroup)
HStack {
Spacer()
Button("取消", role: .cancel) { dismiss() }
Button("移动") { move() }
.keyboardShortcut(.defaultAction)
}
}
.padding(20)
.frame(minWidth: 380)
}
private func move() {
Task {
do {
try await workflow.move(nodeID, to: destination)
dismiss()
} catch {
errors.present(error)
}
}
}
}