diff --git a/web/app/components/plugins/install-plugin/hooks/use-fold-anim-into.ts b/web/app/components/plugins/install-plugin/hooks/use-fold-anim-into.ts index f1c2a612d6..5bf17bb917 100644 --- a/web/app/components/plugins/install-plugin/hooks/use-fold-anim-into.ts +++ b/web/app/components/plugins/install-plugin/hooks/use-fold-anim-into.ts @@ -1,7 +1,8 @@ import { sleep } from '@/utils' -// modalElem fold into plugin install task btn const animTime = 2000 +const modalClassName = 'install-modal' +const COUNT_DOWN_TIME = 15000 // 15s function getElemCenter(elem: HTMLElement) { const rect = elem.getBoundingClientRect() @@ -12,7 +13,13 @@ function getElemCenter(elem: HTMLElement) { } const useFoldAnimInto = (onClose: () => void) => { - return async function foldIntoAnim(modalClassName: string) { + let countDownRunId: number + const clearCountDown = () => { + clearTimeout(countDownRunId) + } + // modalElem fold into plugin install task btn + const foldIntoAnim = async () => { + clearCountDown() const modalElem = document.querySelector(`.${modalClassName}`) as HTMLElement const pluginTaskTriggerElem = document.getElementById('plugin-task-trigger') @@ -32,6 +39,19 @@ const useFoldAnimInto = (onClose: () => void) => { await sleep(animTime) onClose() } + + const countDownFoldIntoAnim = async () => { + countDownRunId = window.setTimeout(() => { + foldIntoAnim() + }, COUNT_DOWN_TIME) + } + + return { + modalClassName, + foldIntoAnim, + clearCountDown, + countDownFoldIntoAnim, + } } export default useFoldAnimInto diff --git a/web/app/components/plugins/install-plugin/install-from-marketplace/index.tsx b/web/app/components/plugins/install-plugin/install-from-marketplace/index.tsx index 67ed8ee547..84660ad6ea 100644 --- a/web/app/components/plugins/install-plugin/install-from-marketplace/index.tsx +++ b/web/app/components/plugins/install-plugin/install-from-marketplace/index.tsx @@ -1,6 +1,6 @@ 'use client' -import React, { useCallback, useRef, useState } from 'react' +import React, { useCallback, useState } from 'react' import Modal from '@/app/components/base/modal' import type { Dependency, Plugin, PluginManifestInMarket } from '../../types' import { InstallStep } from '../../types' @@ -37,8 +37,27 @@ const InstallFromMarketplace: React.FC = ({ const [errorMsg, setErrorMsg] = useState(null) const { refreshPluginList } = useRefreshPluginList() - const modalRef = useRef(null) - const foldAnimInto = useFoldAnimInto(onClose) + const { + modalClassName, + foldIntoAnim: doFoldAnimInto, + clearCountDown, + countDownFoldIntoAnim, + } = useFoldAnimInto(onClose) + + const [isInstalling, setIsInstalling] = useState(false) + + const foldAnimInto = useCallback(() => { + if (isInstalling) { + doFoldAnimInto() + return + } + onClose() + }, [doFoldAnimInto, isInstalling, onClose]) + + const handleStartToInstall = useCallback(() => { + setIsInstalling(true) + countDownFoldIntoAnim() + }, [countDownFoldIntoAnim]) const getTitle = useCallback(() => { if (isBundle && step === InstallStep.installed) @@ -61,12 +80,10 @@ const InstallFromMarketplace: React.FC = ({ setErrorMsg(errorMsg) }, []) - const modalClassName = 'install-modal' - return ( step === InstallStep.readyToInstall ? foldAnimInto(modalClassName) : onClose()} + onClose={foldAnimInto} wrapperClassName='z-[9999]' className={cn(modalClassName, 'flex min-w-[560px] p-0 flex-col items-start rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadows-shadow-xl')} closable @@ -94,6 +111,8 @@ const InstallFromMarketplace: React.FC = ({ onCancel={onClose} onInstalled={handleInstalled} onFailed={handleFailed} + onStartToInstall={handleStartToInstall} + clearCountDown={clearCountDown} /> )} { diff --git a/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx b/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx index 01c4d44bad..be847c6756 100644 --- a/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx +++ b/web/app/components/plugins/install-plugin/install-from-marketplace/steps/install.tsx @@ -22,6 +22,7 @@ type Props = { onCancel: () => void onStartToInstall?: () => void onInstalled: () => void + clearCountDown: () => void onFailed: (message?: string) => void } @@ -31,6 +32,7 @@ const Installed: FC = ({ onCancel, onStartToInstall, onInstalled, + clearCountDown, onFailed, }) => { const { t } = useTranslation() @@ -56,6 +58,7 @@ const Installed: FC = ({ useEffect(() => { if (hasInstalled && uniqueIdentifier === installedInfoPayload.uniqueIdentifier) onInstalled() + // eslint-disable-next-line react-hooks/exhaustive-deps }, [hasInstalled]) const handleCancel = () => { @@ -67,7 +70,6 @@ const Installed: FC = ({ if (isInstalling) return onStartToInstall?.() setIsInstalling(true) - try { let taskId let isInstalled @@ -91,6 +93,8 @@ const Installed: FC = ({ isInstalled = all_installed } + clearCountDown() + if (isInstalled) { onInstalled() return