Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 4 additions & 23 deletions web/app/components/plugins/marketplace/atoms.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { ActivePluginType } from './constants'
import type { PluginsSort, SearchParamsFromCollection } from './types'
import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai'
import { useQueryState } from 'nuqs'
Expand All @@ -17,32 +16,14 @@ export function useSetMarketplaceSort() {
return useSetAtom(marketplaceSortAtom)
}

/**
* Preserve the state for marketplace
*/
export const preserveSearchStateInQueryAtom = atom<boolean>(false)

const searchPluginTextAtom = atom<string>('')
const activePluginTypeAtom = atom<ActivePluginType>('all')
const filterPluginTagsAtom = atom<string[]>([])

export function useSearchPluginText() {
const preserveSearchStateInQuery = useAtomValue(preserveSearchStateInQueryAtom)
const queryState = useQueryState('q', marketplaceSearchParamsParsers.q)
const atomState = useAtom(searchPluginTextAtom)
return preserveSearchStateInQuery ? queryState : atomState
return useQueryState('q', marketplaceSearchParamsParsers.q)
}
export function useActivePluginType() {
const preserveSearchStateInQuery = useAtomValue(preserveSearchStateInQueryAtom)
const queryState = useQueryState('category', marketplaceSearchParamsParsers.category)
const atomState = useAtom(activePluginTypeAtom)
return preserveSearchStateInQuery ? queryState : atomState
return useQueryState('tab', marketplaceSearchParamsParsers.category)
}
Comment on lines 22 to 24
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Find and examine search-params.ts
fd -n "search-params" -t f | head -20

Repository: qodo-benchmark/dify-combined-coderabbit

Length of output: 313


🏁 Script executed:

# Look at the atoms.ts file around line 23
cat -n web/app/components/plugins/marketplace/atoms.ts | sed -n '15,30p'

Repository: qodo-benchmark/dify-combined-coderabbit

Length of output: 666


🏁 Script executed:

# Search for marketplaceSearchParamsParsers definition and usage
rg -n "marketplaceSearchParamsParsers" -A 5 -B 2 | head -50

Repository: qodo-benchmark/dify-combined-coderabbit

Length of output: 4484


🏁 Script executed:

# Search for query parameter key definitions - look for 'tab' and 'category'
rg -n "useQueryState\(" --type=ts --type=tsx -g "*marketplace*" -A 1 | head -40

Repository: qodo-benchmark/dify-combined-coderabbit

Length of output: 110


🏁 Script executed:

# Search for 'tab' parameter usage in the marketplace
rg -n "tab" web/app/components/plugins/marketplace/ --type ts | grep -i "query\|param\|url\|state"

Repository: qodo-benchmark/dify-combined-coderabbit

Length of output: 204


🏁 Script executed:

# Look for useActivePluginType usage to see how the hook is called
rg -n "useActivePluginType" --type ts --type js

Repository: qodo-benchmark/dify-combined-coderabbit

Length of output: 839


🏁 Script executed:

# Search for URL parameters or links that might use 'tab'
rg -n "\btab\b" web/app/components/plugins/marketplace/ --type ts | head -30

Repository: qodo-benchmark/dify-combined-coderabbit

Length of output: 204


🏁 Script executed:

# Check if there are any URL building or navigation that references the params
rg -n "searchParams\|query\|params" web/app/components/plugins/marketplace/atoms.ts -A 2 -B 2

Repository: qodo-benchmark/dify-combined-coderabbit

Length of output: 65


Query parameter key mismatch: 'tab' should be 'category'.

useActivePluginType uses 'tab' as the query parameter key, but marketplaceSearchParamsParsers.category is defined with key 'category' in search-params.ts. This mismatch means the URL will contain ?tab=... while the parser configuration and server-side code expect ?category=.... The parser options (default value, history behavior) are defined for the 'category' key and won't apply correctly to the 'tab' key.

🐛 Proposed fix
 export function useActivePluginType() {
-  return useQueryState('tab', marketplaceSearchParamsParsers.category)
+  return useQueryState('category', marketplaceSearchParamsParsers.category)
 }
🤖 Prompt for AI Agents
In `@web/app/components/plugins/marketplace/atoms.ts` around lines 22 - 24, The
hook useActivePluginType currently reads the wrong query key ('tab'), causing a
mismatch with the parser configuration; change the query key passed to
useQueryState from 'tab' to 'category' so it aligns with
marketplaceSearchParamsParsers.category and the search-params.ts configuration
(update the call in useActivePluginType to use 'category' instead of 'tab').

export function useFilterPluginTags() {
const preserveSearchStateInQuery = useAtomValue(preserveSearchStateInQueryAtom)
const queryState = useQueryState('tags', marketplaceSearchParamsParsers.tags)
const atomState = useAtom(filterPluginTagsAtom)
return preserveSearchStateInQuery ? queryState : atomState
return useQueryState('tags', marketplaceSearchParamsParsers.tags)
}

/**
Expand All @@ -59,7 +40,7 @@ export function useMarketplaceSearchMode() {
const searchMode = useAtomValue(searchModeAtom)
const isSearchMode = !!searchPluginText
|| filterPluginTags.length > 0
|| (searchMode ?? (!PLUGIN_CATEGORY_WITH_COLLECTIONS.has(activePluginType)))
|| (searchMode ?? (PLUGIN_CATEGORY_WITH_COLLECTIONS.has(activePluginType)))
return isSearchMode
}

Expand Down
15 changes: 0 additions & 15 deletions web/app/components/plugins/marketplace/hydration-client.tsx

This file was deleted.

20 changes: 8 additions & 12 deletions web/app/components/plugins/marketplace/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { SearchParams } from 'nuqs'
import { TanstackQueryInitializer } from '@/context/query-client'
import Description from './description'
import { HydrateMarketplaceAtoms } from './hydration-client'
import { HydrateQueryClient } from './hydration-server'
import ListWrapper from './list/list-wrapper'
import StickySearchAndSwitchWrapper from './sticky-search-and-switch-wrapper'
Expand All @@ -10,8 +9,7 @@ type MarketplaceProps = {
showInstallButton?: boolean
pluginTypeSwitchClassName?: string
/**
* Pass the search params from the request to prefetch data on the server
* and preserve the search params in the URL.
* Pass the search params from the request to prefetch data on the server.
*/
searchParams?: Promise<SearchParams>
}
Expand All @@ -24,15 +22,13 @@ const Marketplace = async ({
return (
<TanstackQueryInitializer>
<HydrateQueryClient searchParams={searchParams}>
<HydrateMarketplaceAtoms preserveSearchStateInQuery={!!searchParams}>
<Description />
<StickySearchAndSwitchWrapper
pluginTypeSwitchClassName={pluginTypeSwitchClassName}
/>
<ListWrapper
showInstallButton={showInstallButton}
/>
</HydrateMarketplaceAtoms>
<Description />
<StickySearchAndSwitchWrapper
pluginTypeSwitchClassName={pluginTypeSwitchClassName}
/>
<ListWrapper
showInstallButton={showInstallButton}
/>
</HydrateQueryClient>
</TanstackQueryInitializer>
)
Expand Down
2 changes: 1 addition & 1 deletion web/app/components/plugins/plugin-page/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ type PluginPageContextProviderProps = {
children: ReactNode
}

export function usePluginPageContext(selector: (value: PluginPageContextValue) => any) {
export function usePluginPageContext(selector: any) {
return useContextSelector(PluginPageContext, selector)
}

Expand Down