From 16ac892c93968ae0ec1ce8317bf1a788b261ad45 Mon Sep 17 00:00:00 2001 From: Misaka Date: Sat, 21 Mar 2026 19:28:01 +0800 Subject: [PATCH] refactor: isolate extractor and update dialog state --- src/renderer/src/components/UpdateDialog.tsx | 67 +++----------- src/renderer/src/hooks/useAppBootstrap.ts | 7 +- .../src/hooks/usePersistentTextState.ts | 15 ++++ .../src/hooks/useSharedProductionIds.ts | 36 ++++++++ .../src/hooks/useUpdateDialogState.ts | 89 +++++++++++++++++++ src/renderer/src/lib/session-storage/text.ts | 8 ++ src/renderer/src/pages/ExtractorPage.tsx | 23 ++--- 7 files changed, 168 insertions(+), 77 deletions(-) create mode 100644 src/renderer/src/hooks/usePersistentTextState.ts create mode 100644 src/renderer/src/hooks/useSharedProductionIds.ts create mode 100644 src/renderer/src/hooks/useUpdateDialogState.ts create mode 100644 src/renderer/src/lib/session-storage/text.ts diff --git a/src/renderer/src/components/UpdateDialog.tsx b/src/renderer/src/components/UpdateDialog.tsx index 8b4c72a..9939152 100644 --- a/src/renderer/src/components/UpdateDialog.tsx +++ b/src/renderer/src/components/UpdateDialog.tsx @@ -1,8 +1,9 @@ -import React, { useEffect, useState } from 'react' +import React, { startTransition } from 'react' import ReactMarkdown from 'react-markdown' import remarkGfm from 'remark-gfm' import { DownloadCloud, LoaderCircle, RefreshCw } from 'lucide-react' import Modal from './ui/Modal' +import { useUpdateDialogState } from '../hooks/useUpdateDialogState' import type { UserType } from '../../../main/types/user.types' import type { DownloadReleaseRequest, @@ -22,10 +23,6 @@ interface UpdateDialogProps { onRefreshCatalog: () => Promise } -function releaseKey(release: UpdateRelease): string { - return `${release.channel}:${release.version}` -} - export default function UpdateDialog({ isOpen, userType, @@ -36,54 +33,8 @@ export default function UpdateDialog({ onDownloadAndInstallAdminRelease, onRefreshCatalog }: UpdateDialogProps): React.JSX.Element { - const [selectedRelease, setSelectedRelease] = useState(undefined) - const [changelog, setChangelog] = useState('') - const [isLoadingChangelog, setIsLoadingChangelog] = useState(false) - - useEffect(() => { - if (!isOpen || !catalog) return - - if (catalog.mode === 'user') { - setSelectedRelease(catalog.recommendedRelease) - return - } - - if (catalog.mode === 'admin') { - setSelectedRelease( - catalog.recommendedRelease ?? catalog.channels?.stable[0] ?? catalog.channels?.preview[0] - ) - } - }, [catalog, isOpen]) - - useEffect(() => { - if (!isOpen || !selectedRelease) { - setChangelog('') - return - } - - let active = true - setIsLoadingChangelog(true) - - window.electron.update - .getChangelog(selectedRelease) - .then((result) => { - if (!active) return - setChangelog(result.success && result.data ? result.data : '暂无更新说明。') - }) - .catch(() => { - if (!active) return - setChangelog('暂无更新说明。') - }) - .finally(() => { - if (active) { - setIsLoadingChangelog(false) - } - }) - - return () => { - active = false - } - }, [isOpen, selectedRelease]) + const { selectedRelease, setSelectedRelease, changelog, isLoadingChangelog, isSelectedRelease } = + useUpdateDialogState(isOpen, catalog) const isBusy = status?.phase === 'downloading' || @@ -103,11 +54,15 @@ export default function UpdateDialog({
{title}
{releases.map((release) => { - const selected = selectedRelease && releaseKey(selectedRelease) === releaseKey(release) + const selected = isSelectedRelease(release) return (