|
|
|
@@ -1,14 +1,10 @@ |
|
|
|
import { |
|
|
|
useEffect, |
|
|
|
useRef, |
|
|
|
} from 'react' |
|
|
|
import { useTheme } from 'next-themes' |
|
|
|
import { |
|
|
|
RiArrowRightUpLine, |
|
|
|
RiArrowUpDoubleLine, |
|
|
|
} from '@remixicon/react' |
|
|
|
import { useTranslation } from 'react-i18next' |
|
|
|
import { useMarketplace } from './hooks' |
|
|
|
import type { useMarketplace } from './hooks' |
|
|
|
import List from '@/app/components/plugins/marketplace/list' |
|
|
|
import Loading from '@/app/components/base/loading' |
|
|
|
import { getLocaleOnClient } from '@/i18n' |
|
|
|
@@ -17,12 +13,16 @@ import { getMarketplaceUrl } from '@/utils/var' |
|
|
|
type MarketplaceProps = { |
|
|
|
searchPluginText: string |
|
|
|
filterPluginTags: string[] |
|
|
|
onMarketplaceScroll: () => void |
|
|
|
isMarketplaceArrowVisible: boolean |
|
|
|
showMarketplacePanel: () => void |
|
|
|
marketplaceContext: ReturnType<typeof useMarketplace> |
|
|
|
} |
|
|
|
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<HTMLDivElement>(null) |
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
const container = containerRef.current |
|
|
|
if (container) |
|
|
|
container.addEventListener('scroll', handleScroll) |
|
|
|
|
|
|
|
return () => { |
|
|
|
if (container) |
|
|
|
container.removeEventListener('scroll', handleScroll) |
|
|
|
} |
|
|
|
}, [handleScroll]) |
|
|
|
} = marketplaceContext |
|
|
|
|
|
|
|
return ( |
|
|
|
<div |
|
|
|
ref={containerRef} |
|
|
|
className='sticky bottom-[-442px] flex h-[530px] shrink-0 grow flex-col overflow-y-auto bg-background-default-subtle px-12 py-2 pt-0' |
|
|
|
> |
|
|
|
<RiArrowUpDoubleLine |
|
|
|
className='absolute left-1/2 top-2 h-4 w-4 -translate-x-1/2 cursor-pointer text-text-quaternary' |
|
|
|
onClick={() => onMarketplaceScroll()} |
|
|
|
/> |
|
|
|
<div className='sticky top-0 z-10 bg-background-default-subtle pb-3 pt-5'> |
|
|
|
<div className='title-2xl-semi-bold bg-gradient-to-r from-[rgba(11,165,236,0.95)] to-[rgba(21,90,239,0.95)] bg-clip-text text-transparent'> |
|
|
|
{t('plugin.marketplace.moreFrom')} |
|
|
|
</div> |
|
|
|
<div className='body-md-regular flex items-center text-center text-text-tertiary'> |
|
|
|
{t('plugin.marketplace.discover')} |
|
|
|
<span className="body-md-medium relative ml-1 text-text-secondary after:absolute after:bottom-[1.5px] after:left-0 after:h-2 after:w-full after:bg-text-text-selected after:content-['']"> |
|
|
|
{t('plugin.category.models')} |
|
|
|
</span> |
|
|
|
, |
|
|
|
<span className="body-md-medium relative ml-1 text-text-secondary after:absolute after:bottom-[1.5px] after:left-0 after:h-2 after:w-full after:bg-text-text-selected after:content-['']"> |
|
|
|
{t('plugin.category.tools')} |
|
|
|
</span> |
|
|
|
, |
|
|
|
<span className="body-md-medium relative ml-1 text-text-secondary after:absolute after:bottom-[1.5px] after:left-0 after:h-2 after:w-full after:bg-text-text-selected after:content-['']"> |
|
|
|
{t('plugin.category.agents')} |
|
|
|
</span> |
|
|
|
, |
|
|
|
<span className="body-md-medium relative ml-1 mr-1 text-text-secondary after:absolute after:bottom-[1.5px] after:left-0 after:h-2 after:w-full after:bg-text-text-selected after:content-['']"> |
|
|
|
{t('plugin.category.extensions')} |
|
|
|
</span> |
|
|
|
{t('plugin.marketplace.and')} |
|
|
|
<span className="body-md-medium relative ml-1 mr-1 text-text-secondary after:absolute after:bottom-[1.5px] after:left-0 after:h-2 after:w-full after:bg-text-text-selected after:content-['']"> |
|
|
|
{t('plugin.category.bundles')} |
|
|
|
</span> |
|
|
|
{t('common.operation.in')} |
|
|
|
<a |
|
|
|
href={getMarketplaceUrl('', { language: locale, q: searchPluginText, tags: filterPluginTags.join(','), theme })} |
|
|
|
className='system-sm-medium ml-1 flex items-center text-text-accent' |
|
|
|
target='_blank' |
|
|
|
> |
|
|
|
{t('plugin.marketplace.difyMarketplace')} |
|
|
|
<RiArrowRightUpLine className='h-4 w-4' /> |
|
|
|
</a> |
|
|
|
<> |
|
|
|
<div className='sticky bottom-0 flex shrink-0 flex-col bg-background-default-subtle px-12 pb-[14px] pt-2'> |
|
|
|
{isMarketplaceArrowVisible && ( |
|
|
|
<RiArrowUpDoubleLine |
|
|
|
className='absolute left-1/2 top-2 z-10 h-4 w-4 -translate-x-1/2 cursor-pointer text-text-quaternary' |
|
|
|
onClick={showMarketplacePanel} |
|
|
|
/> |
|
|
|
)} |
|
|
|
<div className='pb-3 pt-4'> |
|
|
|
<div className='title-2xl-semi-bold bg-gradient-to-r from-[rgba(11,165,236,0.95)] to-[rgba(21,90,239,0.95)] bg-clip-text text-transparent'> |
|
|
|
{t('plugin.marketplace.moreFrom')} |
|
|
|
</div> |
|
|
|
<div className='body-md-regular flex items-center text-center text-text-tertiary'> |
|
|
|
{t('plugin.marketplace.discover')} |
|
|
|
<span className="body-md-medium relative ml-1 text-text-secondary after:absolute after:bottom-[1.5px] after:left-0 after:h-2 after:w-full after:bg-text-text-selected after:content-['']"> |
|
|
|
{t('plugin.category.models')} |
|
|
|
</span> |
|
|
|
, |
|
|
|
<span className="body-md-medium relative ml-1 text-text-secondary after:absolute after:bottom-[1.5px] after:left-0 after:h-2 after:w-full after:bg-text-text-selected after:content-['']"> |
|
|
|
{t('plugin.category.tools')} |
|
|
|
</span> |
|
|
|
, |
|
|
|
<span className="body-md-medium relative ml-1 text-text-secondary after:absolute after:bottom-[1.5px] after:left-0 after:h-2 after:w-full after:bg-text-text-selected after:content-['']"> |
|
|
|
{t('plugin.category.agents')} |
|
|
|
</span> |
|
|
|
, |
|
|
|
<span className="body-md-medium relative ml-1 mr-1 text-text-secondary after:absolute after:bottom-[1.5px] after:left-0 after:h-2 after:w-full after:bg-text-text-selected after:content-['']"> |
|
|
|
{t('plugin.category.extensions')} |
|
|
|
</span> |
|
|
|
{t('plugin.marketplace.and')} |
|
|
|
<span className="body-md-medium relative ml-1 mr-1 text-text-secondary after:absolute after:bottom-[1.5px] after:left-0 after:h-2 after:w-full after:bg-text-text-selected after:content-['']"> |
|
|
|
{t('plugin.category.bundles')} |
|
|
|
</span> |
|
|
|
{t('common.operation.in')} |
|
|
|
<a |
|
|
|
href={getMarketplaceUrl('', { language: locale, q: searchPluginText, tags: filterPluginTags.join(','), theme })} |
|
|
|
className='system-sm-medium ml-1 flex items-center text-text-accent' |
|
|
|
target='_blank' |
|
|
|
> |
|
|
|
{t('plugin.marketplace.difyMarketplace')} |
|
|
|
<RiArrowRightUpLine className='h-4 w-4' /> |
|
|
|
</a> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
{ |
|
|
|
isLoading && page === 1 && ( |
|
|
|
<div className='absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2'> |
|
|
|
<Loading /> |
|
|
|
</div> |
|
|
|
) |
|
|
|
} |
|
|
|
{ |
|
|
|
(!isLoading || page > 1) && ( |
|
|
|
<List |
|
|
|
marketplaceCollections={marketplaceCollections || []} |
|
|
|
marketplaceCollectionPluginsMap={marketplaceCollectionPluginsMap || {}} |
|
|
|
plugins={plugins} |
|
|
|
showInstallButton |
|
|
|
locale={locale} |
|
|
|
/> |
|
|
|
) |
|
|
|
} |
|
|
|
</div> |
|
|
|
<div className='mt-[-14px] shrink-0 grow bg-background-default-subtle px-12 pb-2'> |
|
|
|
{ |
|
|
|
isLoading && page === 1 && ( |
|
|
|
<div className='absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2'> |
|
|
|
<Loading /> |
|
|
|
</div> |
|
|
|
) |
|
|
|
} |
|
|
|
{ |
|
|
|
(!isLoading || page > 1) && ( |
|
|
|
<List |
|
|
|
marketplaceCollections={marketplaceCollections || []} |
|
|
|
marketplaceCollectionPluginsMap={marketplaceCollectionPluginsMap || {}} |
|
|
|
plugins={plugins} |
|
|
|
showInstallButton |
|
|
|
locale={locale} |
|
|
|
/> |
|
|
|
) |
|
|
|
} |
|
|
|
</div> |
|
|
|
</> |
|
|
|
) |
|
|
|
} |
|
|
|
|