fix: marketplace list

This commit is contained in:
StyleZhang 2024-10-31 18:31:17 +08:00
parent bf2b9bb898
commit a9e8eb1c7e
4 changed files with 116 additions and 86 deletions

View File

@ -12,20 +12,17 @@ import {
createContext, createContext,
useContextSelector, useContextSelector,
} from 'use-context-selector' } from 'use-context-selector'
import { useDebounceFn } from 'ahooks'
import { PLUGIN_TYPE_SEARCH_MAP } from './plugin-type-switch' import { PLUGIN_TYPE_SEARCH_MAP } from './plugin-type-switch'
import type { Plugin } from '../types' import type { Plugin } from '../types'
import type { import type {
CollectionsAndPluginsSearchParams,
MarketplaceCollection, MarketplaceCollection,
PluginsSearchParams,
PluginsSort, PluginsSort,
} from './types' } from './types'
import {
getMarketplaceCollectionsAndPlugins,
getMarketplacePlugins,
} from './utils'
import { DEFAULT_SORT } from './constants' import { DEFAULT_SORT } from './constants'
import {
useMarketplaceCollectionsAndPlugins,
useMarketplacePlugins,
} from './hooks'
export type MarketplaceContextValue = { export type MarketplaceContextValue = {
intersected: boolean intersected: boolean
@ -83,94 +80,82 @@ export const MarketplaceContextProvider = ({
const filterPluginTagsRef = useRef(filterPluginTags) const filterPluginTagsRef = useRef(filterPluginTags)
const [activePluginType, setActivePluginType] = useState(PLUGIN_TYPE_SEARCH_MAP.all) const [activePluginType, setActivePluginType] = useState(PLUGIN_TYPE_SEARCH_MAP.all)
const activePluginTypeRef = useRef(activePluginType) const activePluginTypeRef = useRef(activePluginType)
const [plugins, setPlugins] = useState<Plugin[]>()
const [sort, setSort] = useState(DEFAULT_SORT) const [sort, setSort] = useState(DEFAULT_SORT)
const sortRef = useRef(sort) const sortRef = useRef(sort)
const [marketplaceCollectionsFromClient, setMarketplaceCollectionsFromClient] = useState<MarketplaceCollection[] | undefined>(undefined)
const [marketplaceCollectionPluginsMapFromClient, setMarketplaceCollectionPluginsMapFromClient] = useState<Record<string, Plugin[]> | undefined>(undefined)
const handleUpdatePlugins = useCallback(async (query: PluginsSearchParams) => {
const { marketplacePlugins } = await getMarketplacePlugins(query)
setPlugins(marketplacePlugins)
setMarketplaceCollectionsFromClient(undefined)
setMarketplaceCollectionPluginsMapFromClient(undefined)
}, [])
const handleUpdateMarketplaceCollectionsAndPlugins = useCallback(async (query?: CollectionsAndPluginsSearchParams) => {
const { const {
marketplaceCollections, marketplaceCollections: marketplaceCollectionsFromClient,
marketplaceCollectionPluginsMap, setMarketplaceCollections: setMarketplaceCollectionsFromClient,
} = await getMarketplaceCollectionsAndPlugins(query) marketplaceCollectionPluginsMap: marketplaceCollectionPluginsMapFromClient,
setMarketplaceCollectionPluginsMap: setMarketplaceCollectionPluginsMapFromClient,
setMarketplaceCollectionsFromClient(marketplaceCollections) queryMarketplaceCollectionsAndPlugins,
setMarketplaceCollectionPluginsMapFromClient(marketplaceCollectionPluginsMap) } = useMarketplaceCollectionsAndPlugins()
setPlugins(undefined) const {
}, []) plugins,
setPlugins,
const { run: handleUpdatePluginsWithDebounced } = useDebounceFn(handleUpdatePlugins, { queryPlugins,
wait: 500, queryPluginsWithDebounced,
}) } = useMarketplacePlugins()
const handleSearchPluginTextChange = useCallback((text: string) => { const handleSearchPluginTextChange = useCallback((text: string) => {
setSearchPluginText(text) setSearchPluginText(text)
searchPluginTextRef.current = text searchPluginTextRef.current = text
handleUpdatePluginsWithDebounced({ queryPluginsWithDebounced({
query: text, query: text,
category: activePluginTypeRef.current === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : activePluginTypeRef.current, category: activePluginTypeRef.current === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : activePluginTypeRef.current,
tags: filterPluginTagsRef.current, tags: filterPluginTagsRef.current,
sortBy: sortRef.current.sortBy, sortBy: sortRef.current.sortBy,
sortOrder: sortRef.current.sortOrder, sortOrder: sortRef.current.sortOrder,
}) })
}, [handleUpdatePluginsWithDebounced]) }, [queryPluginsWithDebounced])
const handleFilterPluginTagsChange = useCallback((tags: string[]) => { const handleFilterPluginTagsChange = useCallback((tags: string[]) => {
setFilterPluginTags(tags) setFilterPluginTags(tags)
filterPluginTagsRef.current = tags filterPluginTagsRef.current = tags
handleUpdatePlugins({ queryPlugins({
query: searchPluginTextRef.current, query: searchPluginTextRef.current,
category: activePluginTypeRef.current === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : activePluginTypeRef.current, category: activePluginTypeRef.current === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : activePluginTypeRef.current,
tags, tags,
sortBy: sortRef.current.sortBy, sortBy: sortRef.current.sortBy,
sortOrder: sortRef.current.sortOrder, sortOrder: sortRef.current.sortOrder,
}) })
}, [handleUpdatePlugins]) }, [queryPlugins])
const handleActivePluginTypeChange = useCallback((type: string) => { const handleActivePluginTypeChange = useCallback((type: string) => {
setActivePluginType(type) setActivePluginType(type)
activePluginTypeRef.current = type activePluginTypeRef.current = type
if (!searchPluginTextRef.current && !filterPluginTagsRef.current.length) { if (!searchPluginTextRef.current && !filterPluginTagsRef.current.length) {
handleUpdateMarketplaceCollectionsAndPlugins({ queryMarketplaceCollectionsAndPlugins({
category: type === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : type, category: type === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : type,
}) })
setPlugins(undefined)
return return
} }
handleUpdatePlugins({ queryPlugins({
query: searchPluginTextRef.current, query: searchPluginTextRef.current,
category: type === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : type, category: type === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : type,
tags: filterPluginTagsRef.current, tags: filterPluginTagsRef.current,
sortBy: sortRef.current.sortBy, sortBy: sortRef.current.sortBy,
sortOrder: sortRef.current.sortOrder, sortOrder: sortRef.current.sortOrder,
}) })
}, [handleUpdatePlugins, handleUpdateMarketplaceCollectionsAndPlugins]) }, [queryPlugins, setPlugins, queryMarketplaceCollectionsAndPlugins])
const handleSortChange = useCallback((sort: PluginsSort) => { const handleSortChange = useCallback((sort: PluginsSort) => {
setSort(sort) setSort(sort)
sortRef.current = sort sortRef.current = sort
handleUpdatePlugins({ queryPlugins({
query: searchPluginTextRef.current, query: searchPluginTextRef.current,
category: activePluginTypeRef.current === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : activePluginTypeRef.current, category: activePluginTypeRef.current === PLUGIN_TYPE_SEARCH_MAP.all ? undefined : activePluginTypeRef.current,
tags: filterPluginTagsRef.current, tags: filterPluginTagsRef.current,
sortBy: sortRef.current.sortBy, sortBy: sortRef.current.sortBy,
sortOrder: sortRef.current.sortOrder, sortOrder: sortRef.current.sortOrder,
}) })
}, [handleUpdatePlugins]) }, [queryPlugins])
return ( return (
<MarketplaceContext.Provider <MarketplaceContext.Provider

View File

@ -0,0 +1,65 @@
import {
useCallback,
useState,
} from 'react'
import { useDebounceFn } from 'ahooks'
import type { Plugin } from '../types'
import type {
CollectionsAndPluginsSearchParams,
MarketplaceCollection,
PluginsSearchParams,
} from './types'
import {
getMarketplaceCollectionsAndPlugins,
getMarketplacePlugins,
} from './utils'
export const useMarketplaceCollectionsAndPlugins = () => {
const [isLoading, setIsLoading] = useState(false)
const [marketplaceCollections, setMarketplaceCollections] = useState<MarketplaceCollection[]>()
const [marketplaceCollectionPluginsMap, setMarketplaceCollectionPluginsMap] = useState<Record<string, Plugin[]>>()
const queryMarketplaceCollectionsAndPlugins = useCallback(async (query?: CollectionsAndPluginsSearchParams) => {
setIsLoading(true)
const { marketplaceCollections, marketplaceCollectionPluginsMap } = await getMarketplaceCollectionsAndPlugins(query)
setIsLoading(false)
setMarketplaceCollections(marketplaceCollections)
setMarketplaceCollectionPluginsMap(marketplaceCollectionPluginsMap)
}, [])
return {
marketplaceCollections,
setMarketplaceCollections,
marketplaceCollectionPluginsMap,
setMarketplaceCollectionPluginsMap,
queryMarketplaceCollectionsAndPlugins,
isLoading,
}
}
export const useMarketplacePlugins = () => {
const [isLoading, setIsLoading] = useState(false)
const [plugins, setPlugins] = useState<Plugin[]>()
const queryPlugins = useCallback(async (query: PluginsSearchParams) => {
setIsLoading(true)
const { marketplacePlugins } = await getMarketplacePlugins(query)
setIsLoading(false)
setPlugins(marketplacePlugins)
}, [])
const { run: queryPluginsWithDebounced } = useDebounceFn(queryPlugins, {
wait: 500,
})
return {
plugins,
setPlugins,
queryPlugins,
queryPluginsWithDebounced,
isLoading,
setIsLoading,
}
}

View File

@ -1,68 +1,48 @@
import { import {
useCallback,
useEffect, useEffect,
useState,
} from 'react' } from 'react'
import { useDebounceFn } from 'ahooks'
import type { Plugin } from '@/app/components/plugins/types'
import type {
MarketplaceCollection,
PluginsSearchParams,
} from '@/app/components/plugins/marketplace/types'
import { import {
getMarketplaceCollectionsAndPlugins, useMarketplaceCollectionsAndPlugins,
getMarketplacePlugins, useMarketplacePlugins,
} from '@/app/components/plugins/marketplace/utils' } from '@/app/components/plugins/marketplace/hooks'
export const useMarketplace = (searchPluginText: string, filterPluginTags: string[]) => { export const useMarketplace = (searchPluginText: string, filterPluginTags: string[]) => {
const [marketplaceCollections, setMarketplaceCollections] = useState<MarketplaceCollection[]>([]) const {
const [marketplaceCollectionPluginsMap, setMarketplaceCollectionPluginsMap] = useState<Record<string, Plugin[]>>({}) isLoading,
const [isLoading, setIsLoading] = useState(true) marketplaceCollections,
const [plugins, setPlugins] = useState<Plugin[]>() marketplaceCollectionPluginsMap,
queryMarketplaceCollectionsAndPlugins,
const handleUpldateMarketplaceCollections = useCallback(async () => { } = useMarketplaceCollectionsAndPlugins()
setIsLoading(true) const {
const { marketplaceCollections, marketplaceCollectionPluginsMap } = await getMarketplaceCollectionsAndPlugins() plugins,
setIsLoading(false) setPlugins,
queryPlugins,
setMarketplaceCollections(marketplaceCollections) queryPluginsWithDebounced,
setMarketplaceCollectionPluginsMap(marketplaceCollectionPluginsMap) isLoading: isPluginsLoading,
setPlugins(undefined) } = useMarketplacePlugins()
}, [])
const handleUpdatePlugins = async (query: PluginsSearchParams) => {
setIsLoading(true)
const { marketplacePlugins } = await getMarketplacePlugins(query)
setIsLoading(false)
setPlugins(marketplacePlugins)
}
const { run: handleUpdatePluginsWithDebounced } = useDebounceFn(handleUpdatePlugins, {
wait: 500,
})
useEffect(() => { useEffect(() => {
if (searchPluginText || filterPluginTags.length) { if (searchPluginText || filterPluginTags.length) {
if (searchPluginText) { if (searchPluginText) {
handleUpdatePluginsWithDebounced({ queryPluginsWithDebounced({
query: searchPluginText, query: searchPluginText,
tags: filterPluginTags, tags: filterPluginTags,
}) })
return return
} }
handleUpdatePlugins({ queryPlugins({
query: searchPluginText, query: searchPluginText,
tags: filterPluginTags, tags: filterPluginTags,
}) })
} }
else { else {
handleUpldateMarketplaceCollections() queryMarketplaceCollectionsAndPlugins()
setPlugins(undefined)
} }
}, [searchPluginText, filterPluginTags, handleUpdatePluginsWithDebounced, handleUpldateMarketplaceCollections]) }, [searchPluginText, filterPluginTags, queryPlugins, queryMarketplaceCollectionsAndPlugins, queryPluginsWithDebounced, setPlugins])
return { return {
isLoading, isLoading: isLoading || isPluginsLoading,
marketplaceCollections, marketplaceCollections,
marketplaceCollectionPluginsMap, marketplaceCollectionPluginsMap,
plugins, plugins,

View File

@ -58,8 +58,8 @@ const Marketplace = ({
{ {
!isLoading && ( !isLoading && (
<List <List
marketplaceCollections={marketplaceCollections} marketplaceCollections={marketplaceCollections || []}
marketplaceCollectionPluginsMap={marketplaceCollectionPluginsMap} marketplaceCollectionPluginsMap={marketplaceCollectionPluginsMap || {}}
plugins={plugins} plugins={plugins}
showInstallButton showInstallButton
/> />