dify/web/app/components/plugins/marketplace/embedded.tsx
CodingOnStar a4a57ec662 fix(web): address marketplace review follow-ups on assets, locale and a11y
- resample the 3MB trending background to a 97KB webp and serve a frozen
  recommend banner from the E2E stub so the benchmark covers the carousel
- show the on-page filtered count in template search and redirect
  out-of-range pages to the last available page
- localize the carousel controls across all 24 locales and replace the
  i18n type casts with typed selectors
- surface Marketplace API failures with a retry action instead of
  rendering them as empty results
- use iconify marks for the hero decorations, share the carousel
  page-size hook to avoid a hydration mismatch, move banner types into
  @dify/contracts, scope the Cmd+K shortcut to the standalone platform,
  point the embedded logo at /marketplace, pass resolvedTheme to the
  detail dialogs, and reveal the detail iframe after a loading timeout

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-16 13:48:34 +08:00

47 lines
1.7 KiB
TypeScript

'use client'
import type { PluginBanner } from '@dify/contracts/marketplace'
import type { MarketplaceViewProps } from './view'
import { queryOptions, useQuery } from '@tanstack/react-query'
import { useLocale } from '@/context/i18n'
import { useResetMarketplaceSearchModeOnMount } from './atoms'
import { fetchPluginBanners } from './home/banners'
import { MarketplaceView } from './view'
const BANNER_STALE_TIME = 1000 * 60 * 5
export type EmbeddedMarketplaceProps = Omit<MarketplaceViewProps, 'banners'> & {
initialBanners?: PluginBanner[]
/**
* Locale used to fetch `initialBanners` during server rendering. `initialBanners`
* is only applied while the client locale still matches it, so a client-side
* language change refetches banners instead of seeding the new locale's cache
* with banners from the previous language.
*/
initialLocale?: string
}
export function EmbeddedMarketplace({
initialBanners,
initialLocale,
variant = 'default',
...props
}: EmbeddedMarketplaceProps) {
useResetMarketplaceSearchModeOnMount()
const locale = useLocale()
const { data: banners = [] } = useQuery(
queryOptions({
// fetchPluginBanners returns normalized PluginBanner[] rather than the
// raw contract response, so it uses its own cache key instead of
// impersonating the generated banners.list contract query.
queryKey: ['marketplace-banners', locale],
queryFn: () => fetchPluginBanners(locale),
enabled: variant === 'home',
initialData: locale === initialLocale ? initialBanners : undefined,
staleTime: BANNER_STALE_TIME,
}),
)
return <MarketplaceView {...props} banners={banners} variant={variant} />
}