From 63e8e9b7ec76083661ec64c81643df7e4ecee617 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sat, 7 Mar 2026 14:15:40 -0600 Subject: [PATCH] Add #m tag filter for webxdc on logged-out homepage Kind 1063 is generic file metadata, so webxdc events require filtering by #m=application/x-webxdc. Add extraFilters support to useInfiniteHotFeed and pass webxdc as a separate filter object with the MIME constraint. --- src/components/Feed.tsx | 9 ++++++--- src/hooks/useTrending.ts | 32 ++++++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/components/Feed.tsx b/src/components/Feed.tsx index a22793e8..885e00b4 100644 --- a/src/components/Feed.tsx +++ b/src/components/Feed.tsx @@ -32,12 +32,14 @@ const LANDING_KINDS = [ 36767, // Themes 37381, // Magic Decks 3367, // Color Moments - 1063, // Webxdc 37516, // Treasures (Geocaches) 7516, // Treasures (Found Logs) 30030, // Emoji Packs ]; +/** Webxdc needs a MIME-type tag filter, so it gets its own filter object. */ +const LANDING_WEBXDC_FILTER = { kinds: [1063], '#m': ['application/x-webxdc'] }; + interface FeedProps { /** Override the kinds list instead of using feed settings. */ kinds?: number[]; @@ -111,8 +113,9 @@ export function Feed({ kinds, tagFilters, header, hideCompose, emptyMessage }: F ); // "Hot" sorted feed query (used when logged out on the home page) - // Shows curated "otherstuff" kinds (photos, videos, articles, themes, etc.) instead of kind 1. - const topQuery = useInfiniteHotFeed(LANDING_KINDS, useTopFeedForLoggedOut); + // Shows curated "otherstuff" kinds instead of kind 1. Webxdc needs a + // separate filter with a MIME-type tag constraint. + const topQuery = useInfiniteHotFeed(LANDING_KINDS, useTopFeedForLoggedOut, undefined, [LANDING_WEBXDC_FILTER]); // Unify the two query shapes behind a single interface const activeQuery = useTopFeedForLoggedOut ? topQuery : feedQuery; diff --git a/src/hooks/useTrending.ts b/src/hooks/useTrending.ts index 83055505..b557d146 100644 --- a/src/hooks/useTrending.ts +++ b/src/hooks/useTrending.ts @@ -188,22 +188,42 @@ export function useInfiniteSortedPosts(sort: SortMode, enabled = true) { /** * Fetches hot-sorted events for specific kinds with infinite scroll. * Uses NIP-50 search extension `sort:hot` against relay.ditto.pub. + * + * `extraFilters` allows appending additional filter objects to the REQ, + * useful when some kinds need tag constraints (e.g. webxdc needs `#m`). */ -export function useInfiniteHotFeed(kinds: number[], enabled = true, limit = SORTED_PAGE_SIZE) { +export function useInfiniteHotFeed( + kinds: number[], + enabled = true, + limit = SORTED_PAGE_SIZE, + extraFilters?: Record[], +) { const { nostr } = useNostr(); + const extraKey = extraFilters ? JSON.stringify(extraFilters) : ''; return useInfiniteQuery({ - queryKey: ['infinite-hot-feed', kinds.join(','), limit], + queryKey: ['infinite-hot-feed', kinds.join(','), limit, extraKey], queryFn: async ({ pageParam, signal }) => { const ditto = nostr.relay(DITTO_RELAY); - const filter: Record = { - kinds, + + const base: Record = { search: 'sort:hot protocol:nostr', limit, }; - if (pageParam) filter.until = pageParam; + if (pageParam) base.until = pageParam; + + // Primary filter for the main kinds list + const filters: Record[] = [{ ...base, kinds }]; + + // Append extra filters (each gets the same sort/pagination params) + if (extraFilters) { + for (const extra of extraFilters) { + filters.push({ ...base, ...extra }); + } + } + return ditto.query( - [filter as { kinds: number[]; search: string; limit: number; until?: number }], + filters as { kinds: number[]; search: string; limit: number; until?: number }[], { signal: AbortSignal.any([signal, AbortSignal.timeout(10000)]) }, ); },