feat(desktop-client): split autostart and keep-alive per platform

Refactors openAtLogin and keepRunningInBackground to make the macOS/Windows
divergence explicit instead of leaning on Electron's cross-platform
abstraction:

- openAtLogin on Windows now passes path: process.execPath and args: []
  so the registry HKCU Run key always points at the right binary.
- keepRunningInBackground on Windows shows a one-shot tray balloon ("省心
  推已最小化到托盘…") so first-time users notice the app is still alive;
  persisted via a private hasShownBackgroundBalloon flag so it never fires
  again. macOS preserves the dock icon and stays silent.
- Sets AppUserModelID early on Windows so tray.displayBalloon's Win10+
  Toast routing actually fires.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-02 18:21:08 +08:00
parent de63d0be5b
commit a4c654782b
3 changed files with 138 additions and 26 deletions
+17 -1
View File
@@ -20,7 +20,9 @@ import {
} from './app-issue-indicator'
import {
getDesktopAppSettings,
hasShownBackgroundBalloon,
initDesktopAppSettings,
markBackgroundBalloonShown,
setDesktopAppSetting,
type DesktopAppSettingKey,
} from './app-settings'
@@ -50,7 +52,7 @@ import {
listDesktopPublishTasks,
retryDesktopPublishTask,
} from './transport/api-client'
import { initTray } from './tray'
import { initTray, showTrayBalloon } from './tray'
import { STANDARD_USER_AGENT } from './user-agent'
import { startHotViewReaper } from './view-pool'
@@ -64,6 +66,14 @@ app.commandLine.appendSwitch('disable-background-networking')
app.commandLine.appendSwitch('remote-debugging-port', String(getPlaywrightCDPPort()))
app.userAgentFallback = STANDARD_USER_AGENT
// Windows 10+ routes tray.displayBalloon through the Toast Notification API,
// which requires a registered AppUserModelID. electron-builder writes this on
// the Start Menu shortcut at install time, but we set it explicitly so dev
// runs and edge-case installs also fire the balloon reliably.
if (process.platform === 'win32') {
app.setAppUserModelId('com.geo.rankly.desktop')
}
const isDevelopmentRuntime = !app.isPackaged
function silencePackagedConsole(): void {
@@ -598,6 +608,12 @@ async function createAppWindow(mode: WindowMode): Promise<ElectronBrowserWindow>
) {
event.preventDefault()
window.hide()
// Windows: notify users once that the app is still running in the tray.
// displayBalloon is a no-op on macOS/Linux so the guard is in tray.ts.
if (process.platform === 'win32' && !hasShownBackgroundBalloon()) {
showTrayBalloon('省心推已最小化到托盘', '应用仍在后台运行,右键托盘图标可退出。')
markBackgroundBalloonShown()
}
}
})