diff --git a/apps/desktop/README.i18n.yaml b/apps/desktop/README.i18n.yaml index f604997189..0c0db6e288 100644 --- a/apps/desktop/README.i18n.yaml +++ b/apps/desktop/README.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write apps/desktop/README.md -README.md: 2948fa988fb5dcc646430b5bade6d07de6b01056 -README.zh.md: f8e6469295f15addb36eff4b04ba8e687013d7dd +README.md: 531c168c0d3fc3091a330f5350d0a85ac3009f08 +README.zh.md: 6a20f83623a54e8f87d05104280b97ddfb2a796a diff --git a/apps/desktop/README.md b/apps/desktop/README.md index 2948fa988f..531c168c0d 100644 --- a/apps/desktop/README.md +++ b/apps/desktop/README.md @@ -263,7 +263,7 @@ An unpacked artifact contains Electron, the materialized dsh production tree, pn ## Updates -Packaged applications check fixed Nightly asynchronously at startup. Ordinary polling uses a ten-minute base interval with independently sampled ±20% jitter. Each check failure doubles the base delay up to one hour; success resets it. The randomized delay is bounded by that cap and starts after all joined callers settle. Foreground and system-resume checks respect the same monotonic deadline; the localized Check for Updates menu item, including in the Windows caption's Application menu, runs immediately and joins an in-flight check. A newly received mandatory policy also requests an immediate feed check. Automatic checks never open dialogs or download packages. Manual checks display checking, failure, or no-update feedback with the installed version. Ordinary update dialogs fade in and out in place; consecutive prompts replace the card content while retaining the backdrop and background blur. +Packaged applications check fixed Nightly asynchronously at startup. Ordinary polling uses a ten-minute base interval with independently sampled ±20% jitter. Each check failure doubles the base delay up to one hour; success resets it. The randomized delay is bounded by that cap and starts after all joined callers settle. Foreground and system-resume checks respect the same monotonic deadline; the localized Check for Updates menu item, including in the Windows caption's Application menu, runs immediately and joins an in-flight check. A newly received mandatory policy also requests an immediate feed check. Automatic checks never open dialogs or download packages. Manual checks display checking, failure, or no-update feedback with the installed version. Ordinary update dialogs fade in and out in place; consecutive prompts replace the card content and reset its scroll position while retaining the backdrop and background blur. `DSH_DESKTOP_UPDATE_CHECK_INTERVAL_MS` configures the ordinary base interval, and `DSH_DESKTOP_UPDATE_CHECK_MAX_BACKOFF_MS` configures the cap; both accept integer milliseconds from 1000 through 2147483647, with the cap at least the interval. An omitted cap defaults to the larger of one hour and the interval. `DSH_DESKTOP_UPDATE_CHECK_JITTER` sets the fractional jitter from 0 through 1, defaulting to `0.2`; the final delay is at least one second and never exceeds the cap. These settings do not change mandatory-policy polling or authorize download retries. diff --git a/apps/desktop/README.zh.md b/apps/desktop/README.zh.md index f8e6469295..6a20f83623 100644 --- a/apps/desktop/README.zh.md +++ b/apps/desktop/README.zh.md @@ -264,7 +264,7 @@ macOS 打包在组装 App 时、代码签名前写入 `Contents/Resources/app-up ## 更新 -打包应用在启动后异步检查固定 Nightly。常规轮询以十分钟为基础间隔,每次独立采样 ±20% 的随机抖动。每次检查失败将基础延迟翻倍,上限为一小时;成功后重置。随机延迟不超过该上限,并从全部复用调用结算后开始计时。本地化的“检查更新…”菜单项(Windows 可从顶栏的“应用”菜单进入)立即执行,并复用正在进行的检查。回到前台和系统恢复时遵守相同的单调时钟截止时间。新收到的强更策略也会立即请求检查更新清单。自动检查从不弹窗或下载安装包。手动检查显示正在检查、失败或包含已安装版本号的无更新反馈。常规更新弹窗原位渐入渐出;连续弹窗仅替换卡片内容,保留蒙层与背景模糊。 +打包应用在启动后异步检查固定 Nightly。常规轮询以十分钟为基础间隔,每次独立采样 ±20% 的随机抖动。每次检查失败将基础延迟翻倍,上限为一小时;成功后重置。随机延迟不超过该上限,并从全部复用调用结算后开始计时。本地化的“检查更新…”菜单项(Windows 可从顶栏的“应用”菜单进入)立即执行,并复用正在进行的检查。回到前台和系统恢复时遵守相同的单调时钟截止时间。新收到的强更策略也会立即请求检查更新清单。自动检查从不弹窗或下载安装包。手动检查显示正在检查、失败或包含已安装版本号的无更新反馈。常规更新弹窗原位渐入渐出;连续弹窗替换卡片内容并重置其滚动位置,保留蒙层与背景模糊。 `DSH_DESKTOP_UPDATE_CHECK_INTERVAL_MS` 配置常规基础间隔,`DSH_DESKTOP_UPDATE_CHECK_MAX_BACKOFF_MS` 配置上限;两者均接受 1000 至 2147483647 的整数毫秒数,且上限不能小于间隔。省略上限时取一小时与间隔中的较大值。`DSH_DESKTOP_UPDATE_CHECK_JITTER` 配置 0 至 1 的抖动比例,默认 `0.2`;最终延迟至少一秒,且不超过上限。这些配置不改变强更策略轮询,也不授权下载重试。 diff --git a/apps/desktop/renderer/update-dialog.js b/apps/desktop/renderer/update-dialog.js index fab2abf05e..d03eadadf7 100644 --- a/apps/desktop/renderer/update-dialog.js +++ b/apps/desktop/renderer/update-dialog.js @@ -47,6 +47,7 @@ function render(state) { document.getElementById('actions').append(button) } document.querySelector('main').hidden = false + document.getElementById('dialog').scrollTop = 0 document.body.classList.add('visible') document.getElementById('dialog').focus() } diff --git a/apps/desktop/tests/update-error-renderer.spec.ts b/apps/desktop/tests/update-error-renderer.spec.ts index 4f0103bb17..ad92f2df8f 100644 --- a/apps/desktop/tests/update-error-renderer.spec.ts +++ b/apps/desktop/tests/update-error-renderer.spec.ts @@ -58,14 +58,18 @@ it.each(['en', 'zh-CN'])('keeps ordinary diagnostics folded, text-only, and keyb expect(respond).toHaveBeenCalledWith(1, 0) const backdrop = p.document.body const dialog = p.element('dialog') + dialog.scrollTop = 170 publish({ ...state, revision: 2, message: locale.messages.updateChecking, technicalDetails: '', buttons: ['OK'] }) expect(p.document.body).toBe(backdrop) expect(p.element('dialog')).toBe(dialog) + expect(dialog.scrollTop).toBe(0) expect(backdrop.classList.contains('visible')).toBe(true) expect(p.element('actions').childElementCount).toBe(1) expect(disclosure.open).toBe(false) expect(p.document.activeElement).toBe(dialog) + dialog.scrollTop = 80 publish(state) + expect(dialog.scrollTop).toBe(80) expect(p.element('title').textContent).toBe(locale.messages.updateChecking) publish(null) expect(backdrop.classList.contains('visible')).toBe(false)