From c4d172030ece07442c9003c30ffaa9ba8945e516 Mon Sep 17 00:00:00 2001 From: liuqiufeng Date: Mon, 27 Jul 2026 22:09:20 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=B8=BA=E6=A3=80=E6=9F=A5=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E6=8C=89=E9=92=AE=E6=B7=BB=E5=8A=A0=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在更新管理 hook 中暴露检查更新中的 loading 状态 - 检查更新请求结束后统一复位 loading 状态 - 关于页检查更新按钮接入 loading 动画 - 补充测试覆盖检查中的 pending 状态 Fixes #730 --- frontend/src/App.tsx | 10 +++++- .../src/hooks/useAppUpdateManager.test.tsx | 32 +++++++++++++++++++ frontend/src/hooks/useAppUpdateManager.ts | 12 +++++-- 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 61ec4151..35f3df1e 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -2368,6 +2368,7 @@ function App() { hideUpdateDownloadProgress, isAboutOpen, isBackgroundProgressForLatestUpdate, + isCheckingForUpdates, isLatestUpdateDownloaded, isUpdateChannelLoading, isUpdateChannelSaving, @@ -5162,7 +5163,14 @@ function App() { lastUpdateInfo?.hasUpdate && !isLatestUpdateDownloaded && !isBackgroundProgressForLatestUpdate ? ( ) : null, - , + , closeAction ?? null, lastUpdateInfo?.hasUpdate && !isLatestUpdateDownloaded && !isBackgroundProgressForLatestUpdate ? ( diff --git a/frontend/src/hooks/useAppUpdateManager.test.tsx b/frontend/src/hooks/useAppUpdateManager.test.tsx index 88dea93d..200d463b 100644 --- a/frontend/src/hooks/useAppUpdateManager.test.tsx +++ b/frontend/src/hooks/useAppUpdateManager.test.tsx @@ -198,6 +198,38 @@ describe('useAppUpdateManager', () => { expect(backendApp.CheckForUpdates).not.toHaveBeenCalled(); }); + it('exposes a loading state while checking for updates', async () => { + let resolveCheck: ((result: Record) => void) | undefined; + const checkPromise = new Promise>((resolve) => { + resolveCheck = resolve; + }); + backendApp.CheckForUpdates.mockReturnValue(checkPromise); + + renderHook(); + + let pendingCheck: Promise | undefined; + act(() => { + pendingCheck = hook?.checkForUpdates(false); + }); + + expect(hook?.isCheckingForUpdates).toBe(true); + expect(hook?.aboutUpdateStatus).toBe('app.about.update_status.checking'); + + await act(async () => { + resolveCheck?.({ + success: true, + data: { + hasUpdate: false, + currentVersion: '0.8.1', + latestVersion: '0.8.1', + }, + }); + await pendingCheck; + }); + + expect(hook?.isCheckingForUpdates).toBe(false); + }); + it('merges complete MSI download metadata returned by the backend', async () => { backendApp.CheckForUpdates.mockResolvedValue({ success: true, diff --git a/frontend/src/hooks/useAppUpdateManager.ts b/frontend/src/hooks/useAppUpdateManager.ts index 3eccbc71..75b496f4 100644 --- a/frontend/src/hooks/useAppUpdateManager.ts +++ b/frontend/src/hooks/useAppUpdateManager.ts @@ -221,6 +221,7 @@ export const useAppUpdateManager = ({ const [installMode, setInstallMode] = useState('unknown'); const [isUpdateChannelLoading, setIsUpdateChannelLoading] = useState(false); const [isUpdateChannelSaving, setIsUpdateChannelSaving] = useState(false); + const [isCheckingForUpdates, setIsCheckingForUpdates] = useState(false); const [aboutInfo, setAboutInfo] = useState(() => DEFAULT_ABOUT_INFO); const [aboutUpdateStatus, setAboutUpdateStatus] = useState(''); const [lastUpdateInfo, setLastUpdateInfo] = useState(null); @@ -470,6 +471,7 @@ export const useAppUpdateManager = ({ const checkForUpdates = useCallback(async (silent: boolean) => { if (updateCheckInFlightRef.current) return; updateCheckInFlightRef.current = true; + setIsCheckingForUpdates(true); if (!silent) { setAboutUpdateStatus(t('app.about.update_status.checking')); } @@ -477,8 +479,13 @@ export const useAppUpdateManager = ({ const checkFn = silent && typeof updateAPI.CheckForUpdatesSilently === 'function' ? updateAPI.CheckForUpdatesSilently : updateAPI.CheckForUpdates; - const res = await checkFn(); - updateCheckInFlightRef.current = false; + let res: any = null; + try { + res = await checkFn(); + } finally { + updateCheckInFlightRef.current = false; + setIsCheckingForUpdates(false); + } if (!res?.success) { if (!silent) { const error = res?.message || t('common.unknown'); @@ -785,6 +792,7 @@ export const useAppUpdateManager = ({ hideUpdateDownloadProgress, isAboutOpen, isBackgroundProgressForLatestUpdate, + isCheckingForUpdates, isLatestUpdateDownloaded, isUpdateChannelLoading, isUpdateChannelSaving,