From 8874837dc3119df0653195cdd2fff551a10fa2d6 Mon Sep 17 00:00:00 2001 From: StyleZhang Date: Fri, 1 Nov 2024 16:08:05 +0800 Subject: [PATCH] feat: plugin tasks --- .../steps/install.tsx | 3 + .../components/plugins/plugin-page/hooks.ts | 37 -------- .../components/plugins/plugin-page/index.tsx | 27 ++---- .../plugins/plugin-page/install-info.tsx | 86 +++++++++++++++++++ .../plugin-page/install-plugin-dropdown.tsx | 2 +- .../components/plugins/plugin-page/store.tsx | 40 +++++++++ 6 files changed, 138 insertions(+), 57 deletions(-) delete mode 100644 web/app/components/plugins/plugin-page/hooks.ts create mode 100644 web/app/components/plugins/plugin-page/install-info.tsx create mode 100644 web/app/components/plugins/plugin-page/store.tsx diff --git a/web/app/components/plugins/install-plugin/install-from-local-package/steps/install.tsx b/web/app/components/plugins/install-plugin/install-from-local-package/steps/install.tsx index 8461eeb425..da5357d87d 100644 --- a/web/app/components/plugins/install-plugin/install-from-local-package/steps/install.tsx +++ b/web/app/components/plugins/install-plugin/install-from-local-package/steps/install.tsx @@ -10,6 +10,7 @@ import { RiLoader2Line } from '@remixicon/react' import Badge, { BadgeState } from '@/app/components/base/badge/index' import { installPackageFromLocal } from '@/service/plugins' import checkTaskStatus from '../../base/check-task-status' +import { usePluginTasksStore } from '@/app/components/plugins/plugin-page/store' const i18nPrefix = 'plugin.installModal' @@ -42,6 +43,7 @@ const Installed: FC = ({ onCancel() } + const setPluginTasksWithPolling = usePluginTasksStore(s => s.setPluginTasksWithPolling) const handleInstall = async () => { if (isInstalling) return setIsInstalling(true) @@ -56,6 +58,7 @@ const Installed: FC = ({ onInstalled() return } + setPluginTasksWithPolling() await check({ taskId, pluginUniqueIdentifier: uniqueIdentifier, diff --git a/web/app/components/plugins/plugin-page/hooks.ts b/web/app/components/plugins/plugin-page/hooks.ts deleted file mode 100644 index 395d90164a..0000000000 --- a/web/app/components/plugins/plugin-page/hooks.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { - useCallback, - useEffect, - useState, -} from 'react' -import { useRequest } from 'ahooks' -import type { PluginTask } from '../types' -import { fetchPluginTasks } from '@/service/plugins' - -export const usePluginTasks = () => { - const [pluginTasks, setPluginTasks] = useState([]) - - const handleUpdatePluginTasks = async (callback: (tasks: PluginTask[]) => void) => { - const { tasks } = await fetchPluginTasks() - setPluginTasks(tasks) - callback(tasks) - } - - const { run, cancel } = useRequest(handleUpdatePluginTasks, { - manual: true, - pollingInterval: 3000, - pollingErrorRetryCount: 2, - }) - - const checkHasPluginTasks = useCallback((tasks: PluginTask[]) => { - if (!tasks.length) - cancel() - }, [cancel]) - - useEffect(() => { - run(checkHasPluginTasks) - }, [run, checkHasPluginTasks]) - - return { - pluginTasks, - } -} diff --git a/web/app/components/plugins/plugin-page/index.tsx b/web/app/components/plugins/plugin-page/index.tsx index d8b7d649d8..c5f8d382b3 100644 --- a/web/app/components/plugins/plugin-page/index.tsx +++ b/web/app/components/plugins/plugin-page/index.tsx @@ -5,7 +5,6 @@ import { useTranslation } from 'react-i18next' import { RiDragDropLine, RiEqualizer2Line, - RiInstallFill, } from '@remixicon/react' import { useBoolean } from 'ahooks' import InstallFromLocalPackage from '../install-plugin/install-from-local-package' @@ -17,7 +16,8 @@ import InstallPluginDropdown from './install-plugin-dropdown' import { useUploader } from './use-uploader' import usePermission from './use-permission' import DebugInfo from './debug-info' -import { usePluginTasks } from './hooks' +import { usePluginTasksStore } from './store' +import InstallInfo from './install-info' import { useTabSearchParams } from '@/hooks/use-tab-searchparams' import Button from '@/app/components/base/button' import TabSlider from '@/app/components/base/tab-slider' @@ -125,7 +125,11 @@ const PluginPage = ({ const { dragging, fileUploader, fileChangeHandle, removeFile } = uploaderProps - const { pluginTasks } = usePluginTasks() + const setPluginTasksWithPolling = usePluginTasksStore(s => s.setPluginTasksWithPolling) + + useEffect(() => { + setPluginTasksWithPolling() + }, [setPluginTasksWithPolling]) return (
-
- -
+ {canManagement && ( setActiveTab('discover')} diff --git a/web/app/components/plugins/plugin-page/install-info.tsx b/web/app/components/plugins/plugin-page/install-info.tsx new file mode 100644 index 0000000000..4d3b076883 --- /dev/null +++ b/web/app/components/plugins/plugin-page/install-info.tsx @@ -0,0 +1,86 @@ +import { + useState, +} from 'react' +import { + RiCheckboxCircleFill, + RiErrorWarningFill, + RiInstallLine, +} from '@remixicon/react' +import { + PortalToFollowElem, + PortalToFollowElemContent, + PortalToFollowElemTrigger, +} from '@/app/components/base/portal-to-follow-elem' +import Tooltip from '@/app/components/base/tooltip' +import Button from '@/app/components/base/button' +// import ProgressCircle from '@/app/components/base/progress-bar/progress-circle' +import { useMemo } from 'react' +import cn from '@/utils/classnames' + +const InstallInfo = () => { + const [open, setOpen] = useState(false) + const status = 'error' + const statusError = useMemo(() => status === 'error', [status]) + + return ( +
+ + setOpen(v => !v)}> + +
+ +
+ {/* */} + +
+
+
+
+ +
+
3 plugins failed to install
+
+
+ +
+
+ DuckDuckGo Search +
+ +
+
+
+
+
+ ) +} + +export default InstallInfo diff --git a/web/app/components/plugins/plugin-page/install-plugin-dropdown.tsx b/web/app/components/plugins/plugin-page/install-plugin-dropdown.tsx index 605a9f36f0..5b8d4caa2e 100644 --- a/web/app/components/plugins/plugin-page/install-plugin-dropdown.tsx +++ b/web/app/components/plugins/plugin-page/install-plugin-dropdown.tsx @@ -119,7 +119,7 @@ const InstallPluginDropdown = ({ && ( setSelectedAction(null)} - onSuccess={() => { }} + onSuccess={() => {}} /> ) } diff --git a/web/app/components/plugins/plugin-page/store.tsx b/web/app/components/plugins/plugin-page/store.tsx new file mode 100644 index 0000000000..25074b973f --- /dev/null +++ b/web/app/components/plugins/plugin-page/store.tsx @@ -0,0 +1,40 @@ +import { create } from 'zustand' +import type { PluginTask } from '../types' +import { fetchPluginTasks } from '@/service/plugins' + +type PluginTasksStore = { + pluginTasks: PluginTask[] + setPluginTasks: (tasks: PluginTask[]) => void + setPluginTasksWithPolling: () => void +} + +let pluginTasksTimer: NodeJS.Timeout | null = null + +export const usePluginTasksStore = create(set => ({ + pluginTasks: [], + setPluginTasks: (tasks: PluginTask[]) => set({ pluginTasks: tasks }), + setPluginTasksWithPolling: async () => { + if (pluginTasksTimer) { + clearTimeout(pluginTasksTimer) + pluginTasksTimer = null + } + const handleUpdatePluginTasks = async () => { + const { tasks } = await fetchPluginTasks() + set({ pluginTasks: tasks }) + + if (tasks.length && !tasks.every(task => task.status === 'success')) { + pluginTasksTimer = setTimeout(() => { + handleUpdatePluginTasks() + }, 5000) + } + else { + if (pluginTasksTimer) { + clearTimeout(pluginTasksTimer) + pluginTasksTimer = null + } + } + } + + handleUpdatePluginTasks() + }, +}))