Skip to content

refactor: 更新移至启动时安装 - #416

Open
HarcoChen wants to merge 4 commits into
MaaXYZ:mainfrom
HarcoChen:refactor/update-on-begin
Open

HarcoChen wants to merge 4 commits into
MaaXYZ:mainfrom
HarcoChen:refactor/update-on-begin

Conversation

@HarcoChen

@HarcoChen HarcoChen commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

不再闲时更新,改为在启动时统一更新


Ref:
MaaEnd/MaaEnd#7070
MaaEnd/MaaEnd#6808
MaaEnd/MaaEnd#6497


GPT 6A写的,先PR编译一下我测测
同时suppress #400

Sourcery 摘要

将更新安装统一调整至应用启动阶段,并增强旧版自动启动任务迁移的安全校验。

错误修复:

  • 限制旧版 Windows 计划任务迁移仅适用于当前可执行文件,避免错误迁移不同安装位置的任务。

功能增强:

  • 将更新安装流程调整为在启动时安装已下载的更新,不再于空闲时、任务结束后或下载完成后自动弹出安装程序。
  • 简化自动任务启动与更新安装的状态管理,并完善无可用安装包时的更新检查入口。

测试:

  • 增加对计划任务目标路径匹配、路径规范化及 XML 转义处理的测试。

维护工作:

  • 移除会话内安装失败后的自动重试状态及相关应用状态字段。
Original summary in English

Sourcery 摘要

将更新安装移至应用启动时进行,并提高旧版自动启动任务迁移的安全性。

新功能:

  • 在应用启动时安装已下载的更新,而不是在下载完成或任务进入空闲状态时提示安装。
  • 安装失败后,如果没有可安装的更新包,则提供检查更新操作。

错误修复:

  • 将旧版 Windows 计划任务的迁移范围限制为目标可执行文件为当前可执行文件的任务,避免从其他安装迁移任务。

改进:

  • 移除由空闲状态触发的安装协调机制和会话级自动重试状态,简化自动任务启动和更新安装的状态处理。

测试:

  • 增加对计划任务可执行文件匹配、路径规范化以及经过 XML 转义的命令路径的覆盖。
Original summary in English

Sourcery 摘要

将更新安装统一调整至应用启动阶段,并提升旧版自动启动任务迁移的安全性。

新功能:

  • 将已下载更新的安装流程集中到应用启动阶段,并在没有可用安装包时提供检查更新入口。

错误修复:

  • 限制旧版 Windows 计划任务迁移仅匹配当前安装位置的可执行文件,避免迁移其他安装位置的任务。

改进:

  • 简化自动任务启动与更新安装的状态管理,并保留安装失败或取消后的更新包记录,以便后续启动时处理。

测试:

  • 增加对计划任务目标路径匹配、路径规范化及 XML 转义处理的测试。

杂项:

  • 移除会话内安装失败后的自动重试状态及相关应用状态字段。
Original summary in English

Summary by Sourcery

将更新安装统一调整至应用启动阶段,并提升旧版自动启动任务迁移的安全性。

New Features:

  • 将已下载更新的安装流程集中到应用启动阶段,并在无可用安装包时提供更新检查入口。

Bug Fixes:

  • 限制旧版 Windows 计划任务迁移仅匹配当前安装位置的可执行文件,避免迁移其他安装位置的任务。

Enhancements:

  • 简化自动任务启动与更新安装的状态管理,并保留安装失败或取消后的更新包记录供后续启动处理。

Tests:

  • 增加计划任务目标路径匹配、路径规范化及 XML 转义处理的测试。

Chores:

  • 移除会话内安装失败后的自动重试状态及相关应用状态字段。

@HarcoChen HarcoChen changed the title [codex] refactor: 更新移至下次启动安装 refactor: 更新移至启动时安装 Nov 4, 2026
@HarcoChen
HarcoChen marked this pull request as ready for review November 6, 2026 14:08
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-06T14:15:26.918714Z 9b44806 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

你好——我发现了 4 个问题

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="src/App.tsx" line_range="1116-1117" />
<code_context>
-          // 先设置 installStatus,再设置 downloadStatus,
-          // 避免 subscribe 在 installStatus 还是 idle 时触发 tryAutoInstallUpdate 造成双发
+          // 启动时安装已下载的更新,完成重启后再执行自动任务。
           useAppStore.getState().setInstallStatus('installing');
           setDownloadStatus('completed');
           setShowInstallConfirmModal(true);
</code_context>
<issue_to_address>
**Update overwrites files during running tasks**

When the UI reloads while a backend task is still running and a pending update exists, `loadInterface` restores backend task states before reaching the pending-update branch, but that branch starts installation without checking whether any instance is running. When the UI reloads while a task is still active, `installUpdate` replaces the target files underneath it and the task can fail or use a mixed version.

Check restored instance run states before starting the update, and defer installation until all tasks have stopped.
</issue_to_address>

### Comment 2
<location path="src/App.tsx" line_range="1115" />
<code_context>
           setDownloadSavePath(pendingUpdate.downloadSavePath);
-          // 先设置 installStatus,再设置 downloadStatus,
-          // 避免 subscribe 在 installStatus 还是 idle 时触发 tryAutoInstallUpdate 造成双发
+          // 启动时安装已下载的更新,完成重启后再执行自动任务。
           useAppStore.getState().setInstallStatus('installing');
           setDownloadStatus('completed');
</code_context>
<issue_to_address>
**Hidden startup blocks auto-run tasks**

When an executable installer update is pending during an auto-start launch, `InstallConfirmModal` opens the executable installer and leaves the completed modal open without restarting the app; because auto-start mode keeps the window hidden, the user cannot close it, and the deferred auto-start tasks never dispatch.

For hidden auto-start launches, avoid waiting on an interactive modal for executable installers; dispatch the pending tasks or otherwise handle installer completion without requiring the hidden window to be closed.
</issue_to_address>

### Comment 3
<location path="src/App.tsx" line_range="1116-1117" />
<code_context>
-          // 先设置 installStatus,再设置 downloadStatus,
-          // 避免 subscribe 在 installStatus 还是 idle 时触发 tryAutoInstallUpdate 造成双发
+          // 启动时安装已下载的更新,完成重启后再执行自动任务。
           useAppStore.getState().setInstallStatus('installing');
           setDownloadStatus('completed');
           setShowInstallConfirmModal(true);
</code_context>
<issue_to_address>
**Canceled installer loses pending update**

When a recovered pending update is an executable installer and the user cancels or the external installer fails, `InstallConfirmModal` opens an executable installer and then clears the pending-update record when opening succeeds, before the external installer has actually updated the app. If the user cancels that installer, the app remains on the old version but no longer has the downloaded package marked for installation on the next launch.

Keep the pending update until the app confirms the installed version changed, or restore it when the startup version check finds the old version still installed.
</issue_to_address>

### Comment 4
<location path="src/App.tsx" line_range="1115" />
<code_context>
           setDownloadSavePath(pendingUpdate.downloadSavePath);
-          // 先设置 installStatus,再设置 downloadStatus,
-          // 避免 subscribe 在 installStatus 还是 idle 时触发 tryAutoInstallUpdate 造成双发
+          // 启动时安装已下载的更新,完成重启后再执行自动任务。
           useAppStore.getState().setInstallStatus('installing');
           setDownloadStatus('completed');
</code_context>
<issue_to_address>
**Settings downloads are not installed at startup**

When a user downloads an update from Settings rather than through the automatic or update-bubble flow, `UpdateSection.startDownload` sets the download status and path but never calls `savePendingUpdateInfo`, so `loadInterface` finds no pending package on the next launch and the update is not installed automatically.

Call `savePendingUpdateInfo` with the completed download’s metadata in the Settings download path as well.
</issue_to_address>

Sourcery 对开源项目免费——如果你喜欢我们的评审,请考虑分享 ✨
Original comment in English

Hey - I've found 4 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="src/App.tsx" line_range="1116-1117" />
<code_context>
-          // 先设置 installStatus,再设置 downloadStatus,
-          // 避免 subscribe 在 installStatus 还是 idle 时触发 tryAutoInstallUpdate 造成双发
+          // 启动时安装已下载的更新,完成重启后再执行自动任务。
           useAppStore.getState().setInstallStatus('installing');
           setDownloadStatus('completed');
           setShowInstallConfirmModal(true);
</code_context>
<issue_to_address>
**Update overwrites files during running tasks**

When the UI reloads while a backend task is still running and a pending update exists, `loadInterface` restores backend task states before reaching the pending-update branch, but that branch starts installation without checking whether any instance is running. When the UI reloads while a task is still active, `installUpdate` replaces the target files underneath it and the task can fail or use a mixed version.

Check restored instance run states before starting the update, and defer installation until all tasks have stopped.
</issue_to_address>

### Comment 2
<location path="src/App.tsx" line_range="1115" />
<code_context>
           setDownloadSavePath(pendingUpdate.downloadSavePath);
-          // 先设置 installStatus,再设置 downloadStatus,
-          // 避免 subscribe 在 installStatus 还是 idle 时触发 tryAutoInstallUpdate 造成双发
+          // 启动时安装已下载的更新,完成重启后再执行自动任务。
           useAppStore.getState().setInstallStatus('installing');
           setDownloadStatus('completed');
</code_context>
<issue_to_address>
**Hidden startup blocks auto-run tasks**

When an executable installer update is pending during an auto-start launch, `InstallConfirmModal` opens the executable installer and leaves the completed modal open without restarting the app; because auto-start mode keeps the window hidden, the user cannot close it, and the deferred auto-start tasks never dispatch.

For hidden auto-start launches, avoid waiting on an interactive modal for executable installers; dispatch the pending tasks or otherwise handle installer completion without requiring the hidden window to be closed.
</issue_to_address>

### Comment 3
<location path="src/App.tsx" line_range="1116-1117" />
<code_context>
-          // 先设置 installStatus,再设置 downloadStatus,
-          // 避免 subscribe 在 installStatus 还是 idle 时触发 tryAutoInstallUpdate 造成双发
+          // 启动时安装已下载的更新,完成重启后再执行自动任务。
           useAppStore.getState().setInstallStatus('installing');
           setDownloadStatus('completed');
           setShowInstallConfirmModal(true);
</code_context>
<issue_to_address>
**Canceled installer loses pending update**

When a recovered pending update is an executable installer and the user cancels or the external installer fails, `InstallConfirmModal` opens an executable installer and then clears the pending-update record when opening succeeds, before the external installer has actually updated the app. If the user cancels that installer, the app remains on the old version but no longer has the downloaded package marked for installation on the next launch.

Keep the pending update until the app confirms the installed version changed, or restore it when the startup version check finds the old version still installed.
</issue_to_address>

### Comment 4
<location path="src/App.tsx" line_range="1115" />
<code_context>
           setDownloadSavePath(pendingUpdate.downloadSavePath);
-          // 先设置 installStatus,再设置 downloadStatus,
-          // 避免 subscribe 在 installStatus 还是 idle 时触发 tryAutoInstallUpdate 造成双发
+          // 启动时安装已下载的更新,完成重启后再执行自动任务。
           useAppStore.getState().setInstallStatus('installing');
           setDownloadStatus('completed');
</code_context>
<issue_to_address>
**Settings downloads are not installed at startup**

When a user downloads an update from Settings rather than through the automatic or update-bubble flow, `UpdateSection.startDownload` sets the download status and path but never calls `savePendingUpdateInfo`, so `loadInterface` finds no pending package on the next launch and the update is not installed automatically.

Call `savePendingUpdateInfo` with the completed download’s metadata in the Settings download path as well.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread src/App.tsx Resolved
Comment thread src/App.tsx Resolved
Comment thread src/App.tsx Resolved
Comment thread src/App.tsx Resolved

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9b44806712

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/App.tsx
Comment on lines +1526 to 1528
// 更新状态通过气泡展示,已下载的更新在下次启动时自动安装。
if (updateInfo?.hasUpdate || updateInfo?.errorCode || downloadStatus === 'downloading') {
setShowUpdateDialog(true);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Persist settings downloads before deferring their installation

When an update is downloaded through desktop Settings—via a manual check, retry, or CDK/source switch—UpdateSection.startDownload only updates the in-memory path and status (src/components/settings/UpdateSection.tsx:158–161); unlike the App and UpdatePanel paths, it never calls savePendingUpdateInfo. With completion-triggered installation removed, the next launch gets null from getPendingUpdateInfo and skips the already-downloaded package, so this workflow no longer installs automatically and can download the same update again. Persist successful Settings downloads too, or centralize persistence, before relying exclusively on startup installation.

AGENTS.md reference: AGENTS.md:L45-L45

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 4892363: The Settings download flow now saves completed update metadata with savePendingUpdateInfo, allowing startup to find and resume that package.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant