diff --git a/web/app/components/plugins/marketplace/list/index.tsx b/web/app/components/plugins/marketplace/list/index.tsx index 5651512f8..2072e3fee 100644 --- a/web/app/components/plugins/marketplace/list/index.tsx +++ b/web/app/components/plugins/marketplace/list/index.tsx @@ -56,7 +56,7 @@ const List = ({ return ( void + isMarketplaceArrowVisible: boolean + showMarketplacePanel: () => void + marketplaceContext: ReturnType } const Marketplace = ({ searchPluginText, filterPluginTags, - onMarketplaceScroll, + isMarketplaceArrowVisible, + showMarketplacePanel, + marketplaceContext, }: MarketplaceProps) => { const locale = getLocaleOnClient() const { t } = useTranslation() @@ -32,86 +32,76 @@ const Marketplace = ({ marketplaceCollections, marketplaceCollectionPluginsMap, plugins, - handleScroll, page, - } = useMarketplace(searchPluginText, filterPluginTags) - const containerRef = useRef(null) - - useEffect(() => { - const container = containerRef.current - if (container) - container.addEventListener('scroll', handleScroll) - - return () => { - if (container) - container.removeEventListener('scroll', handleScroll) - } - }, [handleScroll]) + } = marketplaceContext return ( -
- onMarketplaceScroll()} - /> -
-
- {t('plugin.marketplace.moreFrom')} -
-
- {t('plugin.marketplace.discover')} - - {t('plugin.category.models')} - - , - - {t('plugin.category.tools')} - - , - - {t('plugin.category.agents')} - - , - - {t('plugin.category.extensions')} - - {t('plugin.marketplace.and')} - - {t('plugin.category.bundles')} - - {t('common.operation.in')} - - {t('plugin.marketplace.difyMarketplace')} - - + <> +
+ {isMarketplaceArrowVisible && ( + + )} +
+
+ {t('plugin.marketplace.moreFrom')} +
+
+ {t('plugin.marketplace.discover')} + + {t('plugin.category.models')} + + , + + {t('plugin.category.tools')} + + , + + {t('plugin.category.agents')} + + , + + {t('plugin.category.extensions')} + + {t('plugin.marketplace.and')} + + {t('plugin.category.bundles')} + + {t('common.operation.in')} + + {t('plugin.marketplace.difyMarketplace')} + + +
- { - isLoading && page === 1 && ( -
- -
- ) - } - { - (!isLoading || page > 1) && ( - - ) - } -
+
+ { + isLoading && page === 1 && ( +
+ +
+ ) + } + { + (!isLoading || page > 1) && ( + + ) + } +
+ ) } diff --git a/web/app/components/tools/provider-list.tsx b/web/app/components/tools/provider-list.tsx index ecfa5f6ea..d267b49c7 100644 --- a/web/app/components/tools/provider-list.tsx +++ b/web/app/components/tools/provider-list.tsx @@ -1,5 +1,5 @@ 'use client' -import { useMemo, useRef, useState } from 'react' +import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import type { Collection } from './types' import Marketplace from './marketplace' @@ -20,6 +20,7 @@ import { useAllToolProviders } from '@/service/use-tools' import { useInstalledPluginList, useInvalidateInstalledPluginList } from '@/service/use-plugins' import { useGlobalPublicStore } from '@/context/global-public-context' import { ToolTypeEnum } from '../workflow/block-selector/types' +import { useMarketplace } from './marketplace/hooks' const getToolType = (type: string) => { switch (type) { @@ -37,7 +38,7 @@ const getToolType = (type: string) => { } const ProviderList = () => { // const searchParams = useSearchParams() - // searchParams.get('category') === 'workflow' + // searchParams.get('category') === 'workflow' const { t } = useTranslation() const { enable_marketplace } = useGlobalPublicStore(s => s.systemFeatures) const containerRef = useRef(null) @@ -83,6 +84,41 @@ const ProviderList = () => { return detail }, [currentProvider?.plugin_id, pluginList?.plugins]) + const toolListTailRef = useRef(null) + const showMarketplacePanel = useCallback(() => { + containerRef.current?.scrollTo({ + top: toolListTailRef.current + ? toolListTailRef.current?.offsetTop - 80 + : 0, + behavior: 'smooth', + }) + }, [toolListTailRef]) + + const marketplaceContext = useMarketplace(keywords, tagFilterValue) + const { + handleScroll, + } = marketplaceContext + + const [isMarketplaceArrowVisible, setIsMarketplaceArrowVisible] = useState(true) + const onContainerScroll = useMemo(() => { + return (e: Event) => { + handleScroll(e) + if (containerRef.current && toolListTailRef.current) + setIsMarketplaceArrowVisible(containerRef.current.scrollTop < (toolListTailRef.current?.offsetTop - 80)) + } + }, [handleScroll, containerRef, toolListTailRef, setIsMarketplaceArrowVisible]) + + useEffect(() => { + const container = containerRef.current + if (container) + container.addEventListener('scroll', onContainerScroll) + + return () => { + if (container) + container.removeEventListener('scroll', onContainerScroll) + } + }, [onContainerScroll]) + return ( <>
@@ -152,15 +188,16 @@ const ProviderList = () => {
)} {!filteredCollectionList.length && activeTab === 'builtin' && ( - + )} +
{enable_marketplace && activeTab === 'builtin' && ( { - containerRef.current?.scrollTo({ top: containerRef.current.scrollHeight, behavior: 'smooth' }) - }} searchPluginText={keywords} filterPluginTags={tagFilterValue} + isMarketplaceArrowVisible={isMarketplaceArrowVisible} + showMarketplacePanel={showMarketplacePanel} + marketplaceContext={marketplaceContext} /> )} {activeTab === 'mcp' && (