feat: add search params to url (#17684)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -35,9 +35,10 @@ import {
|
||||
import {
|
||||
getMarketplaceListCondition,
|
||||
getMarketplaceListFilterType,
|
||||
updateSearchParams,
|
||||
} from './utils'
|
||||
import { useInstalledPluginList } from '@/service/use-plugins'
|
||||
import { noop } from 'lodash-es'
|
||||
import { debounce, noop } from 'lodash-es'
|
||||
|
||||
export type MarketplaceContextValue = {
|
||||
intersected: boolean
|
||||
@@ -96,6 +97,7 @@ type MarketplaceContextProviderProps = {
|
||||
searchParams?: SearchParams
|
||||
shouldExclude?: boolean
|
||||
scrollContainerId?: string
|
||||
showSearchParams?: boolean
|
||||
}
|
||||
|
||||
export function useMarketplaceContext(selector: (value: MarketplaceContextValue) => any) {
|
||||
@@ -107,6 +109,7 @@ export const MarketplaceContextProvider = ({
|
||||
searchParams,
|
||||
shouldExclude,
|
||||
scrollContainerId,
|
||||
showSearchParams,
|
||||
}: MarketplaceContextProviderProps) => {
|
||||
const { data, isSuccess } = useInstalledPluginList(!shouldExclude)
|
||||
const exclude = useMemo(() => {
|
||||
@@ -159,7 +162,10 @@ export const MarketplaceContextProvider = ({
|
||||
type: getMarketplaceListFilterType(activePluginTypeRef.current),
|
||||
page: pageRef.current,
|
||||
})
|
||||
history.pushState({}, '', `/${searchParams?.language ? `?language=${searchParams?.language}` : ''}`)
|
||||
const url = new URL(window.location.href)
|
||||
if (searchParams?.language)
|
||||
url.searchParams.set('language', searchParams?.language)
|
||||
history.replaceState({}, '', url)
|
||||
}
|
||||
else {
|
||||
if (shouldExclude && isSuccess) {
|
||||
@@ -182,7 +188,31 @@ export const MarketplaceContextProvider = ({
|
||||
resetPlugins()
|
||||
}, [exclude, queryMarketplaceCollectionsAndPlugins, resetPlugins])
|
||||
|
||||
const debouncedUpdateSearchParams = useMemo(() => debounce(() => {
|
||||
updateSearchParams({
|
||||
query: searchPluginTextRef.current,
|
||||
category: activePluginTypeRef.current,
|
||||
tags: filterPluginTagsRef.current,
|
||||
})
|
||||
}, 500), [])
|
||||
|
||||
const handleUpdateSearchParams = useCallback((debounced?: boolean) => {
|
||||
if (!showSearchParams)
|
||||
return
|
||||
if (debounced) {
|
||||
debouncedUpdateSearchParams()
|
||||
}
|
||||
else {
|
||||
updateSearchParams({
|
||||
query: searchPluginTextRef.current,
|
||||
category: activePluginTypeRef.current,
|
||||
tags: filterPluginTagsRef.current,
|
||||
})
|
||||
}
|
||||
}, [debouncedUpdateSearchParams, showSearchParams])
|
||||
|
||||
const handleQueryPlugins = useCallback((debounced?: boolean) => {
|
||||
handleUpdateSearchParams(debounced)
|
||||
if (debounced) {
|
||||
queryPluginsWithDebounced({
|
||||
query: searchPluginTextRef.current,
|
||||
@@ -207,17 +237,18 @@ export const MarketplaceContextProvider = ({
|
||||
page: pageRef.current,
|
||||
})
|
||||
}
|
||||
}, [exclude, queryPluginsWithDebounced, queryPlugins])
|
||||
}, [exclude, queryPluginsWithDebounced, queryPlugins, handleUpdateSearchParams])
|
||||
|
||||
const handleQuery = useCallback((debounced?: boolean) => {
|
||||
if (!searchPluginTextRef.current && !filterPluginTagsRef.current.length) {
|
||||
handleUpdateSearchParams(debounced)
|
||||
cancelQueryPluginsWithDebounced()
|
||||
handleQueryMarketplaceCollectionsAndPlugins()
|
||||
return
|
||||
}
|
||||
|
||||
handleQueryPlugins(debounced)
|
||||
}, [handleQueryMarketplaceCollectionsAndPlugins, handleQueryPlugins, cancelQueryPluginsWithDebounced])
|
||||
}, [handleQueryMarketplaceCollectionsAndPlugins, handleQueryPlugins, cancelQueryPluginsWithDebounced, handleUpdateSearchParams])
|
||||
|
||||
const handleSearchPluginTextChange = useCallback((text: string) => {
|
||||
setSearchPluginText(text)
|
||||
@@ -242,11 +273,9 @@ export const MarketplaceContextProvider = ({
|
||||
activePluginTypeRef.current = type
|
||||
setPage(1)
|
||||
pageRef.current = 1
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
handleQuery()
|
||||
}, [activePluginType, handleQuery])
|
||||
}, [handleQuery])
|
||||
|
||||
const handleSortChange = useCallback((sort: PluginsSort) => {
|
||||
setSort(sort)
|
||||
|
@@ -17,6 +17,7 @@ type MarketplaceProps = {
|
||||
pluginTypeSwitchClassName?: string
|
||||
intersectionContainerId?: string
|
||||
scrollContainerId?: string
|
||||
showSearchParams?: boolean
|
||||
}
|
||||
const Marketplace = async ({
|
||||
locale,
|
||||
@@ -27,6 +28,7 @@ const Marketplace = async ({
|
||||
pluginTypeSwitchClassName,
|
||||
intersectionContainerId,
|
||||
scrollContainerId,
|
||||
showSearchParams = true,
|
||||
}: MarketplaceProps) => {
|
||||
let marketplaceCollections: any = []
|
||||
let marketplaceCollectionPluginsMap = {}
|
||||
@@ -42,6 +44,7 @@ const Marketplace = async ({
|
||||
searchParams={searchParams}
|
||||
shouldExclude={shouldExclude}
|
||||
scrollContainerId={scrollContainerId}
|
||||
showSearchParams={showSearchParams}
|
||||
>
|
||||
<Description locale={locale} />
|
||||
<IntersectionLine intersectionContainerId={intersectionContainerId} />
|
||||
@@ -53,6 +56,7 @@ const Marketplace = async ({
|
||||
locale={locale}
|
||||
className={pluginTypeSwitchClassName}
|
||||
searchBoxAutoAnimate={searchBoxAutoAnimate}
|
||||
showSearchParams={showSearchParams}
|
||||
/>
|
||||
<ListWrapper
|
||||
locale={locale}
|
||||
|
@@ -13,6 +13,7 @@ import {
|
||||
useSearchBoxAutoAnimate,
|
||||
} from './hooks'
|
||||
import cn from '@/utils/classnames'
|
||||
import { useCallback, useEffect } from 'react'
|
||||
|
||||
export const PLUGIN_TYPE_SEARCH_MAP = {
|
||||
all: 'all',
|
||||
@@ -26,11 +27,13 @@ type PluginTypeSwitchProps = {
|
||||
locale?: string
|
||||
className?: string
|
||||
searchBoxAutoAnimate?: boolean
|
||||
showSearchParams?: boolean
|
||||
}
|
||||
const PluginTypeSwitch = ({
|
||||
locale,
|
||||
className,
|
||||
searchBoxAutoAnimate,
|
||||
showSearchParams,
|
||||
}: PluginTypeSwitchProps) => {
|
||||
const { t } = useMixedTranslation(locale)
|
||||
const activePluginType = useMarketplaceContext(s => s.activePluginType)
|
||||
@@ -70,6 +73,23 @@ const PluginTypeSwitch = ({
|
||||
},
|
||||
]
|
||||
|
||||
const handlePopState = useCallback(() => {
|
||||
if (!showSearchParams)
|
||||
return
|
||||
const url = new URL(window.location.href)
|
||||
const category = url.searchParams.get('category') || PLUGIN_TYPE_SEARCH_MAP.all
|
||||
handleActivePluginTypeChange(category)
|
||||
}, [showSearchParams, handleActivePluginTypeChange])
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('popstate', () => {
|
||||
handlePopState()
|
||||
})
|
||||
return () => {
|
||||
window.removeEventListener('popstate', handlePopState)
|
||||
}
|
||||
}, [handlePopState])
|
||||
|
||||
return (
|
||||
<div className={cn(
|
||||
'flex shrink-0 items-center justify-center space-x-2 bg-background-body py-3',
|
||||
|
@@ -4,6 +4,7 @@ import { PluginType } from '@/app/components/plugins/types'
|
||||
import type {
|
||||
CollectionsAndPluginsSearchParams,
|
||||
MarketplaceCollection,
|
||||
PluginsSearchParams,
|
||||
} from '@/app/components/plugins/marketplace/types'
|
||||
import {
|
||||
MARKETPLACE_API_PREFIX,
|
||||
@@ -125,3 +126,22 @@ export const getMarketplaceListFilterType = (category: string) => {
|
||||
|
||||
return 'plugin'
|
||||
}
|
||||
|
||||
export const updateSearchParams = (pluginsSearchParams: PluginsSearchParams) => {
|
||||
const { query, category, tags } = pluginsSearchParams
|
||||
const url = new URL(window.location.href)
|
||||
const categoryChanged = url.searchParams.get('category') !== category
|
||||
if (query)
|
||||
url.searchParams.set('q', query)
|
||||
else
|
||||
url.searchParams.delete('q')
|
||||
if (category)
|
||||
url.searchParams.set('category', category)
|
||||
else
|
||||
url.searchParams.delete('category')
|
||||
if (tags && tags.length)
|
||||
url.searchParams.set('tags', tags.join(','))
|
||||
else
|
||||
url.searchParams.delete('tags')
|
||||
history[`${categoryChanged ? 'pushState' : 'replaceState'}`]({}, '', url)
|
||||
}
|
||||
|
Reference in New Issue
Block a user