feat(updater): 定时检查更新与后台自动下载

设置 → 系统新增两个开关:定时检查更新(从不/4/12/24 小时,默认 4)与
自动下载更新(默认关)。安装时机仍交给用户——绝不因下载完成自动退出,
autoInstallOnAppQuit 只覆盖用户自己退出时装上。

- runCheck(source) 统一三条来源(启动/周期/手动),UpdateState.scheduled
  标记来源;已有在途检查返回同一 promise,避免 electron-updater 的去重把
  来源标记记到错的调用方
- 周期调度器经 settingsStore.setUpdateScheduleApplier 注入(updater 已
  import settingsStore,反向 import 成环);幂等重排,启动检查由
  startupArmed 保证每进程只武装一次;所有 timer 带 unref
- 自动下载由 settings.autoDownloadUpdate 驱动,autoUpdater.autoDownload
  保持 false(单一事实源在 settings);失败不重试,等下一周期
- 同版本抑制(actedRelease 单槽,actedFor 版本不同即替换):否则长开机
  的应用每 4 小时重复弹气泡、重复走一遍 downloadUpdate;手动检查无条件
  清空记录
- downloaded 与 fetchHandled 分开:前者仅在 update-downloaded 置位,用于
  阻止后续 update-available 把状态从 downloaded 翻回 available(否则「关于」
  页按钮会从「重启安装」退回「下载」)
- tray.notifyUpdate 弹 Windows 托盘气泡;非 win32 / 无 tray / 有可见窗口
  都不弹
This commit is contained in:
Bill committed 2026-10-10 13:36:53 +08:00
1 parent d3529bb9dc
commit 9cc856fc8f
6 files changed
+371 -27

No files matched your search

+7 -2
View File
@@ -5,12 +5,12 @@ import { pathToFileURL } from 'url'
import { devRendererUrl } from './devEnv'
import { isTrustedRendererUrl, registerIpc } from './ipc'
import { killAllPtys, killPtysByOwner } from './pty'
import { applyStartupSystemSettings, loadSettings } from './settingsStore'
import { applyStartupSystemSettings, loadSettings, setUpdateScheduleApplier } from './settingsStore'
import { getLockController, initLockController } from './lockController'
import { applyMenuLockState } from './lockMenu'
import { isLockBlockedShortcut, isPanicLockChord } from './lockShortcuts'
import { initTray, markQuitting, onMainWindowClose, refreshTrayMenu } from './tray'
import { configureAutoUpdater, registerUpdateIpc } from './updater'
import { applyUpdateSchedule, configureAutoUpdater, registerUpdateIpc } from './updater'
import { applyWindowChrome } from './windowChrome'
import { onLanguageChange, t } from '@shared/i18n'
import { getThemeById } from '@shared/theme'
@@ -90,6 +90,11 @@ if (!gotSingleInstanceLock) {
// Before the window exists: a renderer-triggered check must not run against
// the updater's defaults (feed, proxy, autoDownload are set in here).
configureAutoUpdater()
// Arms the startup + periodic update checks and re-arms them on every
// settings save. Injected rather than imported by settingsStore because
// updater.ts already imports settingsStore: the reverse import would be a
// cycle, arming the timer against a half-initialised updater.
setUpdateScheduleApplier(applyUpdateSchedule)
// OS-level effects (login item, sleep blocker) must apply even if the
// settings dialog is never opened this run.
applyStartupSystemSettings(loadSettings())