From f16feb5f0cb4ce5979109568ce4d7838bd2d5183 Mon Sep 17 00:00:00 2001 From: Qiu Yuzhou Date: Mon, 21 Sep 2026 15:17:21 +0800 Subject: [PATCH] fix(ng2): open settings from status menu Use an explicit settings window because the menu bar app has no application menu. Refs #33 --- ShadowsocksX-NG2/App/MainApp.swift | 5 ++++- ShadowsocksX-NG2/App/ProxyStatusMenu.swift | 12 +++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/ShadowsocksX-NG2/App/MainApp.swift b/ShadowsocksX-NG2/App/MainApp.swift index ae25ce80..06249566 100644 --- a/ShadowsocksX-NG2/App/MainApp.swift +++ b/ShadowsocksX-NG2/App/MainApp.swift @@ -65,12 +65,15 @@ struct ShadowsocksXNG2App: App { .defaultLaunchBehavior( catalogViewModel.shouldOfferLegacyImport ? .automatic : .suppressed) - Settings { + // 菜单栏 app 没有可依赖的常规应用菜单;设置窗口必须有显式 scene ID, + // 由状态菜单通过 openWindow(id:) 打开。 + Window("设置", id: "settings") { SettingsView( proxyController: proxyController, loginController: loginController ) .frame(width: 640, height: 760) } + .defaultLaunchBehavior(.suppressed) } } diff --git a/ShadowsocksX-NG2/App/ProxyStatusMenu.swift b/ShadowsocksX-NG2/App/ProxyStatusMenu.swift index b02b92c3..41296a6b 100644 --- a/ShadowsocksX-NG2/App/ProxyStatusMenu.swift +++ b/ShadowsocksX-NG2/App/ProxyStatusMenu.swift @@ -4,8 +4,8 @@ import SwiftUI /// 状态菜单(spec #21 D11 八项白名单,issue #31):①头部状态摘要(运行状态、 /// 当前模式、活动目标)②代理开关 ③模式选择(勾选态)④活动目标级联选择器 /// (组树子菜单、只读)⑤立即更新全部订阅 ⑥复制 HTTP 导出行 ⑦打开主窗口 -/// ⑧退出(明示代理仍在后台运行)。白名单外操作一律不进菜单栏;编辑类操作 -/// 只在主窗口。 +/// ⑧打开设置 ⑨退出(明示代理仍在后台运行)。白名单外操作一律不进菜单栏; +/// 编辑类操作只在主窗口或设置窗口。 struct ProxyStatusMenu: View { @Environment(\.openWindow) private var openWindow @ObservedObject var controller: ProxyRuntimeController @@ -85,9 +85,15 @@ struct ProxyStatusMenu: View { openWindow(id: "main") } + // 菜单栏 app 没有常规应用菜单;设置 scene 由这里显式打开。 + Button("打开设置…") { + NSApp.activate() + openWindow(id: "settings") + } + Divider() - // ⑧ 退出:仅退 GUI;agent 由 launchd 持有,代理不受影响(构造上成立)。 + // ⑨ 退出:仅退 GUI;agent 由 launchd 持有,代理不受影响(构造上成立)。 Button("退出 ShadowsocksX-NG 2.0(代理仍在后台运行)") { NSApp.terminate(nil) }