Repository navigation
refactor: 更新移至启动时安装 #416
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
refactor: 更新移至启动时安装 #416
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -53,9 +53,9 @@ import { | |
| consumeUpdateCompleteInfo, | ||
| savePendingUpdateInfo, | ||
| getPendingUpdateInfo, | ||
| hasInstallFailedInSession, | ||
| clearPendingUpdateInfo, | ||
| isDebugVersion, | ||
| isExecutableInstaller, | ||
| } from '@/services/updateService'; | ||
| import { initTelemetry, isTelemetryBlockedByBuild } from '@/services/telemetryService'; | ||
| import { runAutoUpdateCheck } from '@/services/autoUpdateCheck'; | ||
|
|
@@ -433,41 +433,6 @@ function App() { | |
| const initialized = useRef(false); | ||
| const downloadStartedRef = useRef(false); | ||
| const pendingAutoTasksRef = useRef(false); | ||
| // 自动任务已分发但尚未完成启动时,也要阻止下载完成触发自动安装。 | ||
| // 否则小体积更新可能在 500ms 的任务分发延迟或连接准备期间先完成下载。 | ||
| const autoTaskLaunchPendingRef = useRef(false); | ||
| // 尝试自动安装更新(无任务运行中时触发) | ||
| const tryAutoInstallUpdate = useCallback(() => { | ||
| const state = useAppStore.getState(); | ||
| if (state.downloadStatus !== 'completed') return; | ||
| if (state.installStatus !== 'idle') return; | ||
| if (state.autoInstallPending) return; | ||
| if (autoTaskLaunchPendingRef.current) return; | ||
| if (state.instances.some((i) => i.isRunning)) return; | ||
| // 本次运行中安装失败过则不再自动重试,避免反复失败;手动安装和下次启动不受影响 | ||
| if (hasInstallFailedInSession()) { | ||
| log.info('自动安装更新:本次运行中已安装失败过,跳过自动安装'); | ||
| return; | ||
| } | ||
|
|
||
| log.info('自动安装更新:条件满足,弹出安装'); | ||
| state.setAutoInstallPending(true); | ||
| state.setShowInstallConfirmModal(true); | ||
| }, []); | ||
|
|
||
| // 监听任务结束 或 下载完成 后自动安装更新 | ||
| useEffect(() => { | ||
| return useAppStore.subscribe((state, prev) => { | ||
| const wasRunning = prev.instances.some((i) => i.isRunning); | ||
| const nowRunning = state.instances.some((i) => i.isRunning); | ||
| const downloadJustCompleted = | ||
| prev.downloadStatus !== 'completed' && state.downloadStatus === 'completed'; | ||
| if ((wasRunning && !nowRunning) || downloadJustCompleted) { | ||
| tryAutoInstallUpdate(); | ||
| } | ||
| }); | ||
| }, [tryAutoInstallUpdate]); | ||
|
|
||
| // 自动下载函数 | ||
| const startAutoDownload = useCallback( | ||
| async (updateResult: NonNullable<Awaited<ReturnType<typeof checkAndPrepareDownload>>>) => { | ||
|
|
@@ -520,9 +485,6 @@ function App() { | |
| downloadSource: updateResult.downloadSource, | ||
| timestamp: Date.now(), | ||
| }); | ||
|
|
||
| // 尝试自动安装更新 | ||
| tryAutoInstallUpdate(); | ||
| } else { | ||
| setDownloadStatus('failed'); | ||
| // 下载失败时重置标志,允许后续重新下载(如填入 CDK 后切换下载源) | ||
|
|
@@ -536,7 +498,7 @@ function App() { | |
| downloadStartedRef.current = false; | ||
| } | ||
| }, | ||
| [setDownloadStatus, setDownloadProgress, setDownloadSavePath, tryAutoInstallUpdate], | ||
| [setDownloadStatus, setDownloadProgress, setDownloadSavePath], | ||
| ); | ||
|
|
||
| // 启动检查和定时检查共用更新结果处理 | ||
|
|
@@ -1067,19 +1029,10 @@ function App() { | |
| const dispatchPendingAutoStartTasks = () => { | ||
| if (!autoStartTasksPending) return; | ||
| autoStartTasksPending = false; | ||
| autoTaskLaunchPendingRef.current = true; | ||
| setTimeout(() => { | ||
| document.dispatchEvent( | ||
| new CustomEvent('mxu-start-tasks', { | ||
| detail: { | ||
| source: 'autostart', | ||
| onSettled: () => { | ||
| autoTaskLaunchPendingRef.current = false; | ||
| // 启动失败时任务不会产生 running -> idle 状态变化,需要在这里补一次安装检查; | ||
| // 启动成功时仍处于运行态,本次检查会直接返回,并在任务结束后再次触发。 | ||
| tryAutoInstallUpdate(); | ||
| }, | ||
| }, | ||
| detail: { source: 'autostart' }, | ||
| }), | ||
| ); | ||
| }, 500); | ||
|
|
@@ -1114,6 +1067,7 @@ function App() { | |
| normalizeVersion(currentVersionNow) === normalizeVersion(updateCompleteInfo.newVersion) | ||
| ) { | ||
| log.info('版本已更新到目标版本'); | ||
| clearPendingUpdateInfo(); | ||
| if (isAutoStartModeNow) { | ||
| // 无人值守:跳过弹窗,继续检查是否有更新版本 | ||
| log.info('自启动模式,跳过更新完成弹窗'); | ||
|
|
@@ -1160,8 +1114,20 @@ function App() { | |
| downloadSource: pendingUpdate.downloadSource, | ||
| }); | ||
| setDownloadSavePath(pendingUpdate.downloadSavePath); | ||
| // 先设置 installStatus,再设置 downloadStatus, | ||
| // 避免 subscribe 在 installStatus 还是 idle 时触发 tryAutoInstallUpdate 造成双发 | ||
| // 前端刷新时后端任务可能仍在运行;隐藏自启动也不能等待交互式安装程序。 | ||
| const backendStates = await maaService.getAllStates(); | ||
| if ( | ||
| !backendStates || | ||
| Object.values(backendStates.instances).some((instance) => instance.isRunning) || | ||
| useAppStore.getState().instances.some((instance) => instance.isRunning) || | ||
| (isAutoStartModeNow && isExecutableInstaller(pendingUpdate.downloadSavePath)) | ||
| ) { | ||
| log.info('本次启动跳过安装,保留更新包并继续任务'); | ||
| setDownloadStatus('completed'); | ||
| dispatchPendingAutoStartTasks(); | ||
| return; | ||
| } | ||
| // 启动时安装已下载的更新,完成重启后再执行自动任务。 | ||
|
sourcery-ai[bot] marked this conversation as resolved.
Resolved
|
||
| useAppStore.getState().setInstallStatus('installing'); | ||
| setDownloadStatus('completed'); | ||
|
sourcery-ai[bot] marked this conversation as resolved.
Resolved
sourcery-ai[bot] marked this conversation as resolved.
Resolved
|
||
| setShowInstallConfirmModal(true); | ||
|
|
@@ -1572,12 +1538,8 @@ function App() { | |
| // 回到主界面时,根据状态弹出相应的弹窗 | ||
| useEffect(() => { | ||
| if (currentPage === 'main') { | ||
| // 下载完成:弹出安装模态框 | ||
| if (downloadStatus === 'completed') { | ||
| setShowInstallConfirmModal(true); | ||
| } | ||
| // 有更新、有错误或正在下载:弹出更新气泡 | ||
| else if (updateInfo?.hasUpdate || updateInfo?.errorCode || downloadStatus === 'downloading') { | ||
| // 更新状态通过气泡展示,已下载的更新在下次启动时自动安装。 | ||
| if (updateInfo?.hasUpdate || updateInfo?.errorCode || downloadStatus === 'downloading') { | ||
| setShowUpdateDialog(true); | ||
|
Comment on lines
+1541
to
1543
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When an update is downloaded through desktop Settings—via a manual check, retry, or CDK/source switch— AGENTS.md reference: AGENTS.md:L45-L45 Useful? React with 👍 / 👎.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
| } | ||
| } | ||
|
|
@@ -1587,16 +1549,8 @@ function App() { | |
| updateInfo?.errorCode, | ||
| downloadStatus, | ||
| setShowUpdateDialog, | ||
| setShowInstallConfirmModal, | ||
| ]); | ||
|
|
||
| // 下载完成时,强制弹出安装模态框 | ||
| useEffect(() => { | ||
| if (downloadStatus === 'completed') { | ||
| setShowInstallConfirmModal(true); | ||
| } | ||
| }, [downloadStatus, setShowInstallConfirmModal]); | ||
|
|
||
| // 下载失败或取消时,如果有挂起的自动任务,立即分发 | ||
| useEffect(() => { | ||
| if (pendingAutoTasksRef.current && (downloadStatus === 'failed' || downloadStatus === 'idle')) { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.