From a3ff3c4f92322eb78dab21d2615aa8d29bdb7dec Mon Sep 17 00:00:00 2001 From: Qiu Yuzhou Date: Mon, 28 Sep 2026 21:07:51 +0800 Subject: [PATCH] Revert "fix(servers): align group action with list" This reverts commit 55d2a58e3e74a6ca219e339eb91b58f13df1df50. --- ShadowsocksX-NG2/App/ServersView.swift | 121 ++++--------------------- 1 file changed, 20 insertions(+), 101 deletions(-) diff --git a/ShadowsocksX-NG2/App/ServersView.swift b/ShadowsocksX-NG2/App/ServersView.swift index a29476cc..e90f5ff7 100644 --- a/ShadowsocksX-NG2/App/ServersView.swift +++ b/ShadowsocksX-NG2/App/ServersView.swift @@ -1,4 +1,3 @@ -import AppKit import SwiftUI /// 服务器 destination(spec #21 D11,issue #32/#34/#35/#41):承载服务器目录树、 @@ -28,21 +27,14 @@ struct ServersView: View { @State private var rootDropHovering = false var body: some View { - // 主窗口持有导航侧栏;此处保留服务器目录与详情的独立宽度。 + // 主窗口外壳(票 #53)已提供分栏框架;本分区用扁平双栏承载目录与详情 + // (票 #55 再按原型重排)。 HStack(alignment: .top, spacing: 0) { serverSidebar .frame(minWidth: 240, idealWidth: 280, maxWidth: 340) Divider() - GeometryReader { geometry in - serverDetailPane - .frame(maxWidth: .infinity, maxHeight: .infinity) - .background { - NewGroupTitlebarOverlay(detailWidth: geometry.size.width) { - presentNewGroup(in: workflow.importTargetParent(for: selection)) - } - .frame(width: 1, height: 1) - } - } + serverDetailPane + .frame(maxWidth: .infinity, maxHeight: .infinity) } .frame(minHeight: 420) .alert( @@ -139,6 +131,7 @@ struct ServersView: View { } isTargeted: { hovering in rootDropHovering = hovering } + .toolbar { toolbarContent } } /// 删除结果 → selection invalidation(story 18):仅清除失效选择,不自动 @@ -188,6 +181,21 @@ extension ServersView { } } + // MARK: - 工具栏(新建分组) + + @ToolbarContentBuilder + private var toolbarContent: some ToolbarContent { + ToolbarItem(placement: .primaryAction) { + Button { + presentNewGroup(in: workflow.importTargetParent(for: selection)) + } label: { + Label("新建分组", systemImage: "folder.badge.plus") + } + .labelStyle(.iconOnly) + .help("新建分组") + } + } + // MARK: - 告警动作 private func presentNewGroup(in parent: NodeID?) { @@ -270,92 +278,3 @@ private struct MoveContext: Identifiable { let nodeID: NodeID var id: NodeID { nodeID } } - -/// 将目录动作放到窗口标题栏中,并随详情栏宽度跟踪目录/详情分隔线。 -private struct NewGroupTitlebarOverlay: NSViewRepresentable { - let detailWidth: CGFloat - let onNewGroup: () -> Void - - func makeCoordinator() -> Coordinator { Coordinator() } - - func makeNSView(context: Context) -> WindowAnchorView { - let view = WindowAnchorView() - view.onWindowChange = { [weak coordinator = context.coordinator] window in - coordinator?.move(to: window) - } - return view - } - - func updateNSView(_ view: WindowAnchorView, context: Context) { - context.coordinator.update(detailWidth: detailWidth, onNewGroup: onNewGroup) - context.coordinator.move(to: view.window) - } - - static func dismantleNSView(_ view: WindowAnchorView, coordinator: Coordinator) { - coordinator.move(to: nil) - view.onWindowChange = nil - } - - @MainActor - final class Coordinator { - private weak var window: NSWindow? - private weak var titlebar: NSView? - private let button = NSHostingView(rootView: NewGroupTitlebarButton(action: {})) - private var detailWidth: CGFloat = 0 - - init() { - button.frame.size = NSSize(width: 52, height: 52) - } - - func update(detailWidth: CGFloat, onNewGroup: @escaping () -> Void) { - button.rootView = NewGroupTitlebarButton(action: onNewGroup) - self.detailWidth = detailWidth - layoutButton() - } - - func move(to newWindow: NSWindow?) { - let newTitlebar = newWindow?.standardWindowButton(.closeButton)?.superview - guard window !== newWindow || titlebar !== newTitlebar else { - layoutButton() - return - } - button.removeFromSuperview() - window = newWindow - titlebar = newTitlebar - newTitlebar?.addSubview(button, positioned: .above, relativeTo: nil) - layoutButton() - } - - private func layoutButton() { - guard let titlebar else { return } - button.frame.origin = NSPoint( - x: titlebar.bounds.maxX - detailWidth - 60, - y: titlebar.bounds.midY - 26) - } - } -} - -private final class WindowAnchorView: NSView { - var onWindowChange: ((NSWindow?) -> Void)? - - override func viewDidMoveToWindow() { - super.viewDidMoveToWindow() - onWindowChange?(window) - } -} - -private struct NewGroupTitlebarButton: View { - let action: () -> Void - - var body: some View { - Button(action: action) { - Image(systemName: "folder.badge.plus") - } - .buttonStyle(.bordered) - .buttonBorderShape(.circle) - .controlSize(.large) - .help("新建分组") - .accessibilityLabel("新建分组") - .frame(width: 52, height: 52) - } -}