mirror of
https://github.com/shadowsocks/ShadowsocksX-NG.git
synced 2026-11-08 12:44:51 +00:00
91 lines
2.9 KiB
Swift
91 lines
2.9 KiB
Swift
import AppKit
|
|
import SwiftUI
|
|
|
|
struct PluginManagementSection: View {
|
|
@ObservedObject var model: PluginManagementModel
|
|
@ObservedObject private var catalog: PluginCatalog
|
|
@State private var editor: PluginEditorSession?
|
|
@State private var removal: PluginManagementRow?
|
|
@State private var failure: String?
|
|
|
|
init(model: PluginManagementModel) {
|
|
self.model = model
|
|
catalog = model.catalog
|
|
}
|
|
|
|
var body: some View {
|
|
Section {
|
|
if model.snapshot.mappingsUnreadable {
|
|
Text(PluginManagementCopy.error(PluginMappingError.unreadable))
|
|
.foregroundStyle(.red)
|
|
Button("重试读取") {
|
|
do { try model.retryReading() } catch { failure = PluginManagementCopy.error(error) }
|
|
}
|
|
} else {
|
|
ForEach(model.rows) { entry in
|
|
pluginRow(entry)
|
|
}
|
|
HStack {
|
|
Button {
|
|
editor = model.beginAdding()
|
|
} label: {
|
|
HStack(spacing: 8) {
|
|
Text("新增插件")
|
|
Image(systemName: "chevron.right")
|
|
.font(.caption.weight(.semibold))
|
|
}
|
|
}
|
|
.buttonStyle(.bordered)
|
|
Spacer()
|
|
Button("刷新") { model.refresh() }
|
|
}
|
|
}
|
|
} header: {
|
|
Text("插件").font(.headline).padding(.vertical, 2)
|
|
}
|
|
.onAppear { model.refresh() }
|
|
.onReceive(
|
|
NotificationCenter.default.publisher(for: NSApplication.didBecomeActiveNotification)
|
|
) { _ in
|
|
model.refresh()
|
|
}
|
|
.sheet(item: $editor) { session in
|
|
PluginEditorSheet(model: model, session: session)
|
|
}
|
|
.confirmationDialog(
|
|
"删除用户插件?",
|
|
isPresented: Binding(get: { removal != nil }, set: { if !$0 { removal = nil } }),
|
|
titleVisibility: .visible, presenting: removal
|
|
) { entry in
|
|
Button("删除", role: .destructive) {
|
|
guard let id = entry.recordID else { return }
|
|
do { try model.remove(id) } catch { failure = PluginManagementCopy.error(error) }
|
|
}
|
|
Button("取消", role: .cancel) {}
|
|
} message: { entry in
|
|
Text(
|
|
entry.names.joined(separator: ", ") + "\n\n"
|
|
+ String(localized: "删除此记录的全部名称。服务器引用保留,同名内置插件恢复;其他名称可能无法连接。"))
|
|
}
|
|
.alert(
|
|
"插件配置操作失败",
|
|
isPresented: Binding(
|
|
get: { failure != nil }, set: { if !$0 { failure = nil } }
|
|
)
|
|
) {
|
|
Button("确定", role: .cancel) { failure = nil }
|
|
} message: {
|
|
Text(failure ?? "")
|
|
}
|
|
}
|
|
|
|
private func pluginRow(_ entry: PluginManagementRow) -> some View {
|
|
PluginManagementRowView(
|
|
entry: entry, catalog: catalog,
|
|
beginManagedSettings: { editor = model.beginManagedSettings($0) },
|
|
beginOverriding: { editor = model.beginOverriding($0) },
|
|
beginEditing: { editor = model.beginEditing($0) },
|
|
remove: { removal = entry })
|
|
}
|
|
}
|