t194 二修:托盤 icon/右鍵選單/重複點擊/正常結束(leo 實測四點)

leo 真機測出四個問題,每個都查到真兇後才動手:

## ① 托盤 icon 變方塊
真兇:我塞 1024x1024 的**彩色 app icon** 當 template icon。
macOS 選單列規格是 **16-22pt、純黑+alpha**(由系統依深淺色自動上色)
⇒ 彩色大圖被縮成一坨方塊是必然。
修:用 CIS 的 chevron-double.svg 渲成 44x44 純黑 template icon。

## ②③ 右鍵沒選單/第一次能開之後就不再跳
真兇(energye/systray 原始碼註解白紙黑字寫著):
「該方法主動調用後 如果托盤菜單已創建則添加進去, **之後鼠標事件失效**」
⇒ 只要用 AddMenuItem 建了選單,SetOnClick/SetOnRClick **全部失效**。
修:SetMenuNil() 移除選單讓滑鼠事件生效,右鍵時自己 ShowMenu()。
另外 ShowWindow 只呼叫 WindowShow 對「已開但被蓋住」無效
⇒ 補 Unminimise + AlwaysOnTop 閃一下搶焦點。

## ④ 只能用強制結束
真兇:Wails 的 loop 不理 SIGTERM,且 collector 是我們自己 Start 的子行程
⇒ 主程式被殺後**子行程變孤兒繼續跑**。
實測(機械驗證,非目視):
  修前 kill -TERM → App 沒退、collector 孤兒還在
  修後 kill -TERM → App 正常退出 、collector 一起收掉 、殘留 0
修:installSignalHandler 收 TERM/INT → stopSupervisor() →
    waitCollectorGone(3s) 確認子行程真的不見(逾時補一刀)→ 才 os.Exit。
    「關了卻還在同步」比沒關更糟。

實跑驗證:App 活著 pid 88466、自己拉起 collector、crash 0、兩支機械閘全過。
This commit is contained in:
2026-08-05 01:41:31 +08:00
parent 643acc0f74
commit fcdb1df71d
4 changed files with 88 additions and 7 deletions
+19 -5
View File
@@ -35,6 +35,7 @@ func main() {
// 它不阻塞,接著再把主執行緒交給 wails.Run()。
setupTray(app)
trayStart()
installSignalHandler() // 收到 TERM/INT 要能正常退出(不必強制結束)
defer trayEnd()
err := wails.Run(&options.App{
@@ -87,15 +88,28 @@ var trayStart, trayEnd = func() {}, func() {}
func setupTray(app *App) {
trayStart, trayEnd = systray.RunWithExternalLoop(func() {
// ① icon**必須是 template icon**——選單列規格是 16-22pt、純黑+alpha
// 由系統依深淺色自動上色。先前塞 1024x1024 的彩色 app icon
// ⇒ 縮成一坨方塊(leo 實測)。改用 CIS 的 double chevron 渲成 44x44 純黑。
systray.SetTemplateIcon(trayIcon, trayIcon)
systray.SetTooltip("Arcrun — 你的知識庫同步小幫手")
// 左鍵:立刻展開主視窗
systray.SetOnClick(func(menu systray.IMenu) { app.ShowWindow() })
// 右鍵:只有「結束」一項
// 🔴 ②③ 的真兇(energye/systray 原始碼註解寫得很清楚):
// 「該方法主動調用後 如果托盤菜單已創建則添加進去, **之後鼠標事件失效**」
// ⇒ 只要用 AddMenuItem 建了選單,左右鍵 handler **全部失效**
// ⇒ leo 實測「右鍵沒跳出 quit」「第一次能開之後就不再跳」。
// 正解:SetMenuNil() 移除選單讓滑鼠事件生效,右鍵時**自己叫出選單**。
quit := systray.AddMenuItem("結束 Arcrun", "停止同步並關閉")
quit.Click(func() { app.Quit() })
systray.SetOnRClick(func(menu systray.IMenu) { _ = menu.ShowMenu() })
systray.SetMenuNil() // ← 沒有這行,下面兩個 handler 都不會被呼叫
// 左鍵:立刻展開主視窗(leo:「點擊托盤的 icon 就立刻展開界面」)
systray.SetOnClick(func(menu systray.IMenu) { app.ShowWindow() })
// 右鍵:把選單叫出來(只有「結束 Arcrun」一項)
systray.SetOnRClick(func(menu systray.IMenu) {
if menu != nil {
_ = menu.ShowMenu()
}
})
}, nil)
}