From 99833f65d80efb441ccbf609bb0ccc567fc5456c Mon Sep 17 00:00:00 2001 From: Zongrong Li Date: Tue, 2 Jun 2026 10:41:01 +0200 Subject: [PATCH] refactor(web): migrate NEED_REFRESH_APP_LIST_KEY to useLocalStorage/useSetLocalStorage (#36908) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: yyh --- eslint-suppressions.json | 32 ------------------- .../[appId]/overview/card-view.tsx | 5 ++- .../app-info/use-app-info-actions.ts | 5 ++- .../__tests__/index.spec.tsx | 2 +- .../app/create-app-dialog/app-list/index.tsx | 5 ++- .../components/app/create-app-modal/index.tsx | 5 ++- .../app/create-from-dsl-modal/index.tsx | 6 ++-- .../components/app/switch-app-modal/index.tsx | 5 ++- web/app/components/apps/app-card.tsx | 4 ++- web/hooks/use-import-dsl.ts | 6 ++-- 10 files changed, 32 insertions(+), 43 deletions(-) diff --git a/eslint-suppressions.json b/eslint-suppressions.json index 7892c03b58..7142991cb6 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -119,11 +119,6 @@ "count": 1 } }, - "web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/card-view.tsx": { - "no-restricted-globals": { - "count": 1 - } - }, "web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/__tests__/svg-attribute-error-reproduction.spec.tsx": { "no-console": { "count": 19 @@ -252,11 +247,6 @@ "count": 4 } }, - "web/app/components/app-sidebar/app-info/use-app-info-actions.ts": { - "no-restricted-globals": { - "count": 1 - } - }, "web/app/components/app-sidebar/index.tsx": { "no-restricted-globals": { "count": 2 @@ -551,9 +541,6 @@ } }, "web/app/components/app/create-app-dialog/app-list/index.tsx": { - "no-restricted-globals": { - "count": 1 - }, "no-restricted-imports": { "count": 1 } @@ -567,9 +554,6 @@ } }, "web/app/components/app/create-app-modal/index.tsx": { - "no-restricted-globals": { - "count": 1 - }, "no-restricted-imports": { "count": 1 } @@ -578,9 +562,6 @@ "erasable-syntax-only/enums": { "count": 1 }, - "no-restricted-globals": { - "count": 2 - }, "no-restricted-imports": { "count": 1 }, @@ -646,9 +627,6 @@ } }, "web/app/components/app/switch-app-modal/index.tsx": { - "no-restricted-globals": { - "count": 1 - }, "no-restricted-imports": { "count": 1 }, @@ -684,11 +662,6 @@ "count": 1 } }, - "web/app/components/apps/app-card.tsx": { - "no-restricted-globals": { - "count": 1 - } - }, "web/app/components/apps/list.tsx": { "no-restricted-globals": { "count": 2 @@ -5168,11 +5141,6 @@ "count": 1 } }, - "web/hooks/use-import-dsl.ts": { - "no-restricted-globals": { - "count": 2 - } - }, "web/hooks/use-metadata.ts": { "ts/no-explicit-any": { "count": 1 diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/card-view.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/card-view.tsx index 8ef0b65e0f..3e73e210eb 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/card-view.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/card-view.tsx @@ -18,6 +18,7 @@ import { collaborationManager } from '@/app/components/workflow/collaboration/co import { webSocketClient } from '@/app/components/workflow/collaboration/core/websocket-manager' import { isTriggerNode } from '@/app/components/workflow/types' import { NEED_REFRESH_APP_LIST_KEY } from '@/config' +import { useSetLocalStorage } from '@/hooks/use-local-storage' import { fetchAppDetail, updateAppSiteAccessToken, @@ -75,6 +76,8 @@ const CardView: FC = ({ appId, isInPanel, className }) => { ? buildTriggerModeMessage(t('mcp.server.title', { ns: 'tools' })) : null + const setNeedRefresh = useSetLocalStorage(NEED_REFRESH_APP_LIST_KEY, { raw: true }) + const updateAppDetail = useCallback(async () => { try { const res = await fetchAppDetail({ url: '/apps', id: appId }) @@ -155,7 +158,7 @@ const CardView: FC = ({ appId, isInPanel, className }) => { }) as Promise, ) if (!err) - localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1') + setNeedRefresh('1') handleCallbackResult(err) } diff --git a/web/app/components/app-sidebar/app-info/use-app-info-actions.ts b/web/app/components/app-sidebar/app-info/use-app-info-actions.ts index 134726a50c..289af67371 100644 --- a/web/app/components/app-sidebar/app-info/use-app-info-actions.ts +++ b/web/app/components/app-sidebar/app-info/use-app-info-actions.ts @@ -8,6 +8,7 @@ import { useTranslation } from 'react-i18next' import { useStore as useAppStore } from '@/app/components/app/store' import { NEED_REFRESH_APP_LIST_KEY } from '@/config' import { useProviderContext } from '@/context/provider-context' +import { useSetLocalStorage } from '@/hooks/use-local-storage' import { useRouter } from '@/next/navigation' import { copyApp, deleteApp, exportAppConfig, fetchAppDetail, updateAppInfo } from '@/service/apps' import { useInvalidateAppList } from '@/service/use-apps' @@ -107,6 +108,8 @@ export function useAppInfoActions({ onDetailExpand, resetKey }: UseAppInfoAction setActiveModal(null) }, [setActiveModal]) + const setNeedRefresh = useSetLocalStorage(NEED_REFRESH_APP_LIST_KEY, { raw: true }) + const emitAppMetaUpdate = useCallback(() => { if (!appDetail?.id) return @@ -208,7 +211,7 @@ export function useAppInfoActions({ onDetailExpand, resetKey }: UseAppInfoAction }) closeModal() toast(t('newApp.appCreated', { ns: 'app' }), { type: 'success' }) - localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1') + setNeedRefresh('1') onPlanInfoChanged() getRedirection(true, newApp, replace) } diff --git a/web/app/components/app/configuration/debug/debug-with-single-model/__tests__/index.spec.tsx b/web/app/components/app/configuration/debug/debug-with-single-model/__tests__/index.spec.tsx index 634dd6217f..1cc359fe85 100644 --- a/web/app/components/app/configuration/debug/debug-with-single-model/__tests__/index.spec.tsx +++ b/web/app/components/app/configuration/debug/debug-with-single-model/__tests__/index.spec.tsx @@ -1,4 +1,4 @@ -/* eslint-disable react/no-create-ref, ts/no-explicit-any */ +/* eslint-disable ts/no-explicit-any */ import type { ReactNode, RefObject } from 'react' import type { DebugWithSingleModelRefType } from '../index' import type { ChatItem } from '@/app/components/base/chat/types' diff --git a/web/app/components/app/create-app-dialog/app-list/index.tsx b/web/app/components/app/create-app-dialog/app-list/index.tsx index 73334b5214..51ce7c076f 100644 --- a/web/app/components/app/create-app-dialog/app-list/index.tsx +++ b/web/app/components/app/create-app-dialog/app-list/index.tsx @@ -17,6 +17,7 @@ import CreateAppModal from '@/app/components/explore/create-app-modal' import { usePluginDependencies } from '@/app/components/workflow/plugin-dependency/hooks' import { NEED_REFRESH_APP_LIST_KEY } from '@/config' import { useAppContext } from '@/context/app-context' +import { useSetLocalStorage } from '@/hooks/use-local-storage' import { DSLImportMode } from '@/models/app' import { useRouter } from '@/next/navigation' import { importDSL } from '@/service/apps' @@ -47,6 +48,8 @@ const Apps = ({ const { push } = useRouter() const allCategoriesEn = AppCategories.RECOMMENDED + const setNeedRefresh = useSetLocalStorage(NEED_REFRESH_APP_LIST_KEY, { raw: true }) + const [keywords, setKeywords] = useState('') const [searchKeywords, setSearchKeywords] = useState('') @@ -135,7 +138,7 @@ const Apps = ({ onSuccess() if (app.app_id) await handleCheckPluginDependencies(app.app_id) - localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1') + setNeedRefresh('1') getRedirection(isCurrentWorkspaceEditor, { id: app.app_id!, mode }, push) } catch { diff --git a/web/app/components/app/create-app-modal/index.tsx b/web/app/components/app/create-app-modal/index.tsx index c24e5f886c..f3236f899a 100644 --- a/web/app/components/app/create-app-modal/index.tsx +++ b/web/app/components/app/create-app-modal/index.tsx @@ -20,6 +20,7 @@ import AppsFull from '@/app/components/billing/apps-full-in-dialog' import { NEED_REFRESH_APP_LIST_KEY } from '@/config' import { useAppContext } from '@/context/app-context' import { useProviderContext } from '@/context/provider-context' +import { useSetLocalStorage } from '@/hooks/use-local-storage' import useTheme from '@/hooks/use-theme' import { useRouter } from '@/next/navigation' import { createApp } from '@/service/apps' @@ -58,6 +59,8 @@ function CreateApp({ onClose, onSuccess, onCreateFromTemplate, defaultAppMode }: const isCreatingRef = useRef(false) + const setNeedRefresh = useSetLocalStorage(NEED_REFRESH_APP_LIST_KEY, { raw: true }) + const onCreate = useCallback(async () => { if (!appMode) { toast.error(t('newApp.appTypeRequired', { ns: 'app' })) @@ -85,7 +88,7 @@ function CreateApp({ onClose, onSuccess, onCreateFromTemplate, defaultAppMode }: toast.success(t('newApp.appCreated', { ns: 'app' })) onSuccess() onClose() - localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1') + setNeedRefresh('1') getRedirection(isCurrentWorkspaceEditor, app, push) } catch (error) { diff --git a/web/app/components/app/create-from-dsl-modal/index.tsx b/web/app/components/app/create-from-dsl-modal/index.tsx index f6cf347820..72eac7ef79 100644 --- a/web/app/components/app/create-from-dsl-modal/index.tsx +++ b/web/app/components/app/create-from-dsl-modal/index.tsx @@ -16,6 +16,7 @@ import { usePluginDependencies } from '@/app/components/workflow/plugin-dependen import { NEED_REFRESH_APP_LIST_KEY } from '@/config' import { useAppContext } from '@/context/app-context' import { useProviderContext } from '@/context/provider-context' +import { useSetLocalStorage } from '@/hooks/use-local-storage' import { DSLImportMode, DSLImportStatus, @@ -54,6 +55,7 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS const [versions, setVersions] = useState<{ importedVersion: string, systemVersion: string }>() const [importId, setImportId] = useState() const { handleCheckPluginDependencies } = usePluginDependencies() + const setNeedRefresh = useSetLocalStorage(NEED_REFRESH_APP_LIST_KEY, { raw: true }) const readFile = useCallback((file: File) => { const reader = new FileReader() @@ -124,7 +126,7 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS ? t('newApp.appCreateDSLWarning', { ns: 'app' }) : undefined, }) - localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1') + setNeedRefresh('1') if (app_id) await handleCheckPluginDependencies(app_id) getRedirection(isCurrentWorkspaceEditor, { id: app_id!, mode: app_mode }, push) @@ -178,7 +180,7 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose, activeTab = CreateFromDS toast.success(t('newApp.appCreated', { ns: 'app' })) if (app_id) await handleCheckPluginDependencies(app_id) - localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1') + setNeedRefresh('1') getRedirection(isCurrentWorkspaceEditor, { id: app_id!, mode: app_mode }, push) } else if (status === DSLImportStatus.FAILED) { diff --git a/web/app/components/app/switch-app-modal/index.tsx b/web/app/components/app/switch-app-modal/index.tsx index d01138ed90..f94f6735bf 100644 --- a/web/app/components/app/switch-app-modal/index.tsx +++ b/web/app/components/app/switch-app-modal/index.tsx @@ -26,6 +26,7 @@ import AppsFull from '@/app/components/billing/apps-full-in-dialog' import { NEED_REFRESH_APP_LIST_KEY } from '@/config' import { useAppContext } from '@/context/app-context' import { useProviderContext } from '@/context/provider-context' +import { useSetLocalStorage } from '@/hooks/use-local-storage' import { useRouter } from '@/next/navigation' import { deleteApp, switchApp } from '@/service/apps' import { AppModeEnum } from '@/types/app' @@ -60,6 +61,8 @@ const SwitchAppModal = ({ show, appDetail, inAppDetail = false, onSuccess, onClo const [removeOriginal, setRemoveOriginal] = useState(false) const [showConfirmDelete, setShowConfirmDelete] = useState(false) + const setNeedRefresh = useSetLocalStorage(NEED_REFRESH_APP_LIST_KEY, { raw: true }) + const goStart = async () => { try { const { new_app_id: newAppID } = await switchApp({ @@ -78,7 +81,7 @@ const SwitchAppModal = ({ show, appDetail, inAppDetail = false, onSuccess, onClo setAppDetail() if (removeOriginal) await deleteApp(appDetail.id) - localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1') + setNeedRefresh('1') getRedirection( isCurrentWorkspaceEditor, { diff --git a/web/app/components/apps/app-card.tsx b/web/app/components/apps/app-card.tsx index 3f640e4daf..3f120a7bc4 100644 --- a/web/app/components/apps/app-card.tsx +++ b/web/app/components/apps/app-card.tsx @@ -42,6 +42,7 @@ import { useProviderContext } from '@/context/provider-context' import { systemFeaturesQueryOptions } from '@/features/system-features/client' import { AppCardTags } from '@/features/tag-management/components/app-card-tags' import { useAsyncWindowOpen } from '@/hooks/use-async-window-open' +import { useSetLocalStorage } from '@/hooks/use-local-storage' import { AccessMode } from '@/models/access-control' import dynamic from '@/next/dynamic' import { useRouter } from '@/next/navigation' @@ -223,6 +224,7 @@ const AppCard = ({ app, onlineUsers = [], onRefresh, onOpenTagManagement = () => const [isOperationsMenuOpen, setIsOperationsMenuOpen] = useState(false) const [secretEnvList, setSecretEnvList] = useState([]) const { mutateAsync: mutateDeleteApp, isPending: isDeleting } = useDeleteAppMutation() + const setNeedRefresh = useSetLocalStorage(NEED_REFRESH_APP_LIST_KEY, { raw: true }) const onConfirmDelete = useCallback(async () => { try { @@ -334,7 +336,7 @@ const AppCard = ({ app, onlineUsers = [], onRefresh, onOpenTagManagement = () => }) setShowDuplicateModal(false) toast.success(t('newApp.appCreated', { ns: 'app' })) - localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1') + setNeedRefresh('1') if (onRefresh) onRefresh() onPlanInfoChanged() diff --git a/web/hooks/use-import-dsl.ts b/web/hooks/use-import-dsl.ts index 83b11157cf..bfcb8dc194 100644 --- a/web/hooks/use-import-dsl.ts +++ b/web/hooks/use-import-dsl.ts @@ -13,6 +13,7 @@ import { useTranslation } from 'react-i18next' import { usePluginDependencies } from '@/app/components/workflow/plugin-dependency/hooks' import { NEED_REFRESH_APP_LIST_KEY } from '@/config' import { useSelector } from '@/context/app-context' +import { useSetLocalStorage } from '@/hooks/use-local-storage' import { DSLImportStatus } from '@/models/app' import { useRouter } from '@/next/navigation' import { @@ -44,6 +45,7 @@ export const useImportDSL = () => { const { push } = useRouter() const [versions, setVersions] = useState<{ importedVersion: string, systemVersion: string }>() const importIdRef = useRef('') + const setNeedRefresh = useSetLocalStorage(NEED_REFRESH_APP_LIST_KEY, { raw: true }) const handleImportDSL = useCallback(async ( payload: DSLPayload, @@ -86,7 +88,7 @@ export const useImportDSL = () => { else toast.warning(message, { description }) onSuccess?.(response) - localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1') + setNeedRefresh('1') await handleCheckPluginDependencies(app_id) getRedirection(isCurrentWorkspaceEditor, { id: app_id, mode: app_mode }, push) } @@ -137,7 +139,7 @@ export const useImportDSL = () => { onSuccess?.(response) toast.success(t('newApp.appCreated', { ns: 'app' })) await handleCheckPluginDependencies(app_id) - localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1') + setNeedRefresh('1') getRedirection(isCurrentWorkspaceEditor, { id: app_id!, mode: app_mode }, push) } else if (status === DSLImportStatus.FAILED) {