fix: model provider page marketplace

This commit is contained in:
StyleZhang 2024-11-28 11:26:24 +08:00
parent 99942b26e6
commit 37eee7be24
4 changed files with 125 additions and 49 deletions

View File

@ -11,6 +11,7 @@ import type {
DefaultModel,
DefaultModelResponse,
Model,
ModelProvider,
ModelTypeEnum,
} from './declarations'
import {
@ -26,6 +27,12 @@ import {
getPayUrl,
} from '@/service/common'
import { useProviderContext } from '@/context/provider-context'
import {
useMarketplaceCollectionsAndPlugins,
useMarketplacePlugins,
} from '@/app/components/plugins/marketplace/hooks'
import { PluginType } from '@/app/components/plugins/types'
import { getMarketplaceListCondition } from '@/app/components/plugins/marketplace/utils'
type UseDefaultModelAndModelList = (
defaultModel: DefaultModelResponse | undefined,
@ -233,3 +240,46 @@ export const useUpdateModelProviders = () => {
return updateModelProviders
}
export const useMarketplace = (providers: ModelProvider[], searchText: string) => {
const exclude = useMemo(() => {
return providers.map(provider => provider.provider.replace(/(.+)\/([^/]+)$/, '$1'))
}, [providers])
const {
isLoading,
marketplaceCollections,
marketplaceCollectionPluginsMap,
queryMarketplaceCollectionsAndPlugins,
} = useMarketplaceCollectionsAndPlugins()
const {
plugins,
resetPlugins,
queryPluginsWithDebounced,
isLoading: isPluginsLoading,
} = useMarketplacePlugins()
useEffect(() => {
if (searchText) {
queryPluginsWithDebounced({
query: searchText,
category: PluginType.model,
exclude,
})
}
else {
queryMarketplaceCollectionsAndPlugins({
category: PluginType.model,
condition: getMarketplaceListCondition(PluginType.model),
exclude,
})
resetPlugins()
}
}, [searchText, queryMarketplaceCollectionsAndPlugins, queryPluginsWithDebounced, resetPlugins, exclude])
return {
isLoading: isLoading || isPluginsLoading,
marketplaceCollections,
marketplaceCollectionPluginsMap,
plugins: plugins?.filter(plugin => plugin.type !== 'bundle'),
}
}

View File

@ -1,4 +1,4 @@
import { useEffect, useMemo, useState } from 'react'
import { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Link from 'next/link'
import { useDebounce } from 'ahooks'
@ -21,21 +21,21 @@ import {
} from './declarations'
import {
useDefaultModel,
useMarketplace,
useUpdateModelList,
useUpdateModelProviders,
} from './hooks'
import Divider from '@/app/components/base/divider'
import Loading from '@/app/components/base/loading'
import ProviderCard from '@/app/components/plugins/provider-card'
import List from '@/app/components/plugins/marketplace/list'
import { useProviderContext } from '@/context/provider-context'
import { useModalContextSelector } from '@/context/modal-context'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import {
useMarketplacePlugins,
} from '@/app/components/plugins/marketplace/hooks'
import { PluginType } from '@/app/components/plugins/types'
import type { Plugin } from '@/app/components/plugins/types'
import { MARKETPLACE_URL_PREFIX } from '@/config'
import cn from '@/utils/classnames'
import { getLocaleOnClient } from '@/i18n'
type Props = {
searchText: string
@ -121,28 +121,20 @@ const ModelProviderPage = ({ searchText }: Props) => {
}
const [collapse, setCollapse] = useState(false)
const locale = getLocaleOnClient()
const {
plugins = [],
queryPlugins,
queryPluginsWithDebounced,
plugins,
marketplaceCollections,
marketplaceCollectionPluginsMap,
isLoading: isPluginsLoading,
} = useMarketplacePlugins()
} = useMarketplace(providers, searchText)
useEffect(() => {
if (searchText) {
queryPluginsWithDebounced({
query: searchText,
category: PluginType.model,
})
}
else {
queryPlugins({
query: searchText,
category: PluginType.model,
})
}
}, [queryPlugins, queryPluginsWithDebounced, searchText])
const cardRender = useCallback((plugin: Plugin) => {
if (plugin.type === 'bundle')
return null
return <ProviderCard key={plugin.plugin_id} payload={plugin} />
}, [])
return (
<div className='relative pt-1 -mt-2'>
@ -219,14 +211,20 @@ const ModelProviderPage = ({ searchText }: Props) => {
</Link>
</div>
</div>
{!collapse && !isPluginsLoading && (
<div className='grid grid-cols-2 gap-2'>
{plugins.map(plugin => (
<ProviderCard key={plugin.plugin_id} payload={plugin} />
))}
</div>
)}
{!collapse && isPluginsLoading && <Loading type='area' />}
{
!isPluginsLoading && (
<List
marketplaceCollections={marketplaceCollections || []}
marketplaceCollectionPluginsMap={marketplaceCollectionPluginsMap || {}}
plugins={plugins}
showInstallButton
locale={locale}
cardContainerClassName='grid grid-cols-2 gap-2'
cardRender={cardRender}
/>
)
}
</div>
</div>
)

View File

@ -4,6 +4,7 @@ import type { MarketplaceCollection } from '../types'
import ListWithCollection from './list-with-collection'
import CardWrapper from './card-wrapper'
import Empty from '../empty'
import cn from '@/utils/classnames'
type ListProps = {
marketplaceCollections: MarketplaceCollection[]
@ -11,6 +12,8 @@ type ListProps = {
plugins?: Plugin[]
showInstallButton?: boolean
locale: string
cardContainerClassName?: string
cardRender?: (plugin: Plugin) => JSX.Element | null
}
const List = ({
marketplaceCollections,
@ -18,6 +21,8 @@ const List = ({
plugins,
showInstallButton,
locale,
cardContainerClassName,
cardRender,
}: ListProps) => {
return (
<>
@ -28,21 +33,31 @@ const List = ({
marketplaceCollectionPluginsMap={marketplaceCollectionPluginsMap}
showInstallButton={showInstallButton}
locale={locale}
cardContainerClassName={cardContainerClassName}
cardRender={cardRender}
/>
)
}
{
plugins && !!plugins.length && (
<div className='grid grid-cols-4 gap-3'>
<div className={cn(
'grid grid-cols-4 gap-3',
cardContainerClassName,
)}>
{
plugins.map(plugin => (
<CardWrapper
key={plugin.name}
plugin={plugin}
showInstallButton={showInstallButton}
locale={locale}
/>
))
plugins.map((plugin) => {
if (cardRender)
return cardRender(plugin)
return (
<CardWrapper
key={plugin.name}
plugin={plugin}
showInstallButton={showInstallButton}
locale={locale}
/>
)
})
}
</div>
)

View File

@ -3,18 +3,23 @@ import type { MarketplaceCollection } from '../types'
import CardWrapper from './card-wrapper'
import type { Plugin } from '@/app/components/plugins/types'
import { getLanguage } from '@/i18n/language'
import cn from '@/utils/classnames'
type ListWithCollectionProps = {
marketplaceCollections: MarketplaceCollection[]
marketplaceCollectionPluginsMap: Record<string, Plugin[]>
showInstallButton?: boolean
locale: string
cardContainerClassName?: string
cardRender?: (plugin: Plugin) => JSX.Element | null
}
const ListWithCollection = ({
marketplaceCollections,
marketplaceCollectionPluginsMap,
showInstallButton,
locale,
cardContainerClassName,
cardRender,
}: ListWithCollectionProps) => {
return (
<>
@ -26,16 +31,24 @@ const ListWithCollection = ({
>
<div className='title-xl-semi-bold text-text-primary'>{collection.label[getLanguage(locale)]}</div>
<div className='system-xs-regular text-text-tertiary'>{collection.description[getLanguage(locale)]}</div>
<div className='grid grid-cols-4 gap-3 mt-2'>
<div className={cn(
'grid grid-cols-4 gap-3 mt-2',
cardContainerClassName,
)}>
{
marketplaceCollectionPluginsMap[collection.name].map(plugin => (
<CardWrapper
key={plugin.name}
plugin={plugin}
showInstallButton={showInstallButton}
locale={locale}
/>
))
marketplaceCollectionPluginsMap[collection.name].map((plugin) => {
if (cardRender)
return cardRender(plugin)
return (
<CardWrapper
key={plugin.name}
plugin={plugin}
showInstallButton={showInstallButton}
locale={locale}
/>
)
})
}
</div>
</div>