cf19ca2d34
根因:launch_at_startup 0.5.1 在 macOS 无自带实现,需宿主接 MethodChannel,而我们 Runner 从没实现 → enable() 抛 MissingPluginException 被 try/catch 吞掉 → 登录项从未注册,自启失败。 学 Tailscale(LoginItemHelper-macsys + SMAppService): - 新增无界面 LoginItem helper(macos/login_helper,LSBackgroundOnly),登录时带 --autostart 拉起主 app(→隐藏到托盘); - build_login_helper.sh 构建期编译+签名+嵌入 Contents/Library/LoginItems/(新 Run Script 阶段); - MainFlutterWindow 接 launch_at_startup MethodChannel → SMAppService.loginItem 注册/注销。 构建通过:helper 嵌入+签名,主 app --deep --strict 校验过。Windows 自启(schtasks)不变。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
28 lines
1.3 KiB
Swift
28 lines
1.3 KiB
Swift
// PangolinLoginHelper — 无界面登录项 helper(学 Tailscale 的 LoginItemHelper)。
|
|
//
|
|
// 由 SMAppService.loginItem 在用户登录时拉起;它唯一的活儿:带 --autostart 启动主 app
|
|
// (让主 app 隐藏到托盘,见主 app main.dart / MainFlutterWindow),然后自己退出。
|
|
// 打进主 app 的 Contents/Library/LoginItems/PangolinLoginHelper.app(见 build_login_helper.sh)。
|
|
import AppKit
|
|
|
|
// helper 位于 <MainApp>.app/Contents/Library/LoginItems/PangolinLoginHelper.app
|
|
// 主 app = helper bundle 上溯 4 级(LoginItems → Library → Contents → <MainApp>.app)。
|
|
let helperURL = Bundle.main.bundleURL
|
|
let mainAppURL = helperURL
|
|
.deletingLastPathComponent() // LoginItems
|
|
.deletingLastPathComponent() // Library
|
|
.deletingLastPathComponent() // Contents
|
|
.deletingLastPathComponent() // <MainApp>.app
|
|
|
|
let config = NSWorkspace.OpenConfiguration()
|
|
config.arguments = ["--autostart"] // 主 app 据此隐藏到托盘
|
|
config.activates = false // 不抢焦点
|
|
config.addsToRecentItems = false
|
|
|
|
let done = DispatchSemaphore(value: 0)
|
|
NSWorkspace.shared.openApplication(at: mainAppURL, configuration: config) { _, _ in
|
|
done.signal()
|
|
}
|
|
// 等启动请求发出(最多 10s)再退出,避免 helper 过早结束导致启动被取消。
|
|
_ = done.wait(timeout: .now() + 10)
|