fix: restore Windows tray lifecycle
This commit is contained in:
+22
-5
@@ -11,6 +11,7 @@ import (
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
@@ -100,6 +101,8 @@ type App struct {
|
||||
browserInboxEvents map[string]bool
|
||||
browserInboxEnabled atomic.Bool
|
||||
allowQuit atomic.Bool
|
||||
trayReady atomic.Bool
|
||||
quitOnce sync.Once
|
||||
}
|
||||
|
||||
// SetNotificationService attaches the core-owned plugin notification scheduler.
|
||||
@@ -221,11 +224,23 @@ func (a *App) Shutdown(ctx context.Context) {
|
||||
cleanupNativeNotifications(ctx)
|
||||
}
|
||||
|
||||
// BeforeClose hides the primary window until the user explicitly quits from the tray.
|
||||
// SetTrayReady reports whether the native tray can safely return a hidden window.
|
||||
func (a *App) SetTrayReady(ready bool) {
|
||||
if a != nil {
|
||||
a.trayReady.Store(ready)
|
||||
}
|
||||
}
|
||||
|
||||
// BeforeClose hides the primary window only after the native tray has confirmed
|
||||
// that it can return the window. Otherwise the normal Wails close path exits.
|
||||
func (a *App) BeforeClose(ctx context.Context) bool {
|
||||
if a.allowQuit.Load() {
|
||||
return false
|
||||
}
|
||||
if !a.trayReady.Load() {
|
||||
log.Printf("[app] tray is unavailable; allowing normal window close")
|
||||
return false
|
||||
}
|
||||
hideNativeWindow(ctx)
|
||||
return true
|
||||
}
|
||||
@@ -243,10 +258,12 @@ func (a *App) Quit() {
|
||||
if a == nil {
|
||||
return
|
||||
}
|
||||
a.allowQuit.Store(true)
|
||||
if a.ctx != nil {
|
||||
quitNativeApplication(a.ctx)
|
||||
}
|
||||
a.quitOnce.Do(func() {
|
||||
a.allowQuit.Store(true)
|
||||
if a.ctx != nil {
|
||||
quitNativeApplication(a.ctx)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// NativeNotificationSender delivers scheduler items through the Wails runtime.
|
||||
|
||||
@@ -319,7 +319,7 @@ func TestNativeNotificationSenderUsesStablePluginScopedID(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBeforeCloseHidesWindowUntilUserChoosesQuit(t *testing.T) {
|
||||
func TestBeforeCloseAllowsExitUntilTrayIsReady(t *testing.T) {
|
||||
oldHide := hideNativeWindow
|
||||
defer func() { hideNativeWindow = oldHide }()
|
||||
|
||||
@@ -327,8 +327,25 @@ func TestBeforeCloseHidesWindowUntilUserChoosesQuit(t *testing.T) {
|
||||
hideNativeWindow = func(context.Context) { hideCalls++ }
|
||||
app := &App{}
|
||||
|
||||
if prevent := app.BeforeClose(context.Background()); prevent {
|
||||
t.Fatal("BeforeClose() = true, want false while tray is unavailable")
|
||||
}
|
||||
if hideCalls != 0 {
|
||||
t.Fatalf("hide calls = %d, want 0", hideCalls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBeforeCloseHidesWindowAfterTrayIsReady(t *testing.T) {
|
||||
oldHide := hideNativeWindow
|
||||
defer func() { hideNativeWindow = oldHide }()
|
||||
|
||||
hideCalls := 0
|
||||
hideNativeWindow = func(context.Context) { hideCalls++ }
|
||||
app := &App{}
|
||||
app.SetTrayReady(true)
|
||||
|
||||
if prevent := app.BeforeClose(context.Background()); !prevent {
|
||||
t.Fatal("BeforeClose() = false, want true while tray mode is active")
|
||||
t.Fatal("BeforeClose() = false, want true while tray is ready")
|
||||
}
|
||||
if hideCalls != 1 {
|
||||
t.Fatalf("hide calls = %d, want 1", hideCalls)
|
||||
@@ -353,6 +370,22 @@ func TestTrayQuitAllowsWindowCloseAndQuitsApplication(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTrayQuitRequestsNativeShutdownOnlyOnce(t *testing.T) {
|
||||
oldQuit := quitNativeApplication
|
||||
defer func() { quitNativeApplication = oldQuit }()
|
||||
|
||||
quitCalls := 0
|
||||
quitNativeApplication = func(context.Context) { quitCalls++ }
|
||||
app := &App{ctx: context.Background()}
|
||||
|
||||
app.Quit()
|
||||
app.Quit()
|
||||
|
||||
if quitCalls != 1 {
|
||||
t.Fatalf("native quit calls = %d, want 1", quitCalls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShowWindowUsesWailsContext(t *testing.T) {
|
||||
oldShow := showNativeWindow
|
||||
defer func() { showNativeWindow = oldShow }()
|
||||
|
||||
Reference in New Issue
Block a user