From 6f46927c28a5a18a08760a55b4c08415bc9579d6 Mon Sep 17 00:00:00 2001
From: DS Boyce <260543580+ds-boyce@users.noreply.github.com>
Date: Mon, 24 Aug 2026 11:39:46 -0700
Subject: [PATCH] Overfetch trending topics before filtering (#11477)
---
src/components/interstitials/Trending.tsx | 154 ------------------
.../Search/modules/ExploreTrendingTopics.tsx | 6 +-
.../queries/trending/useGetTrendsQuery.ts | 15 +-
src/view/com/posts/PostFeed.tsx | 7 -
.../shell/desktop/SidebarTrendingTopics.tsx | 1 -
5 files changed, 14 insertions(+), 169 deletions(-)
delete mode 100644 src/components/interstitials/Trending.tsx
diff --git a/src/components/interstitials/Trending.tsx b/src/components/interstitials/Trending.tsx
deleted file mode 100644
index 0b94064dac..0000000000
--- a/src/components/interstitials/Trending.tsx
+++ /dev/null
@@ -1,154 +0,0 @@
-import {useCallback} from 'react'
-import {ScrollView, View} from 'react-native'
-import {useLingui} from '@lingui/react/macro'
-
-import {
- useTrendingSettings,
- useTrendingSettingsApi,
-} from '#/state/preferences/trending'
-import {useGetTrendsQuery} from '#/state/queries/trending/useGetTrendsQuery'
-import {useTrendingConfig} from '#/state/service-config'
-import {LoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
-import {BlockDrawerGesture} from '#/view/shell/BlockDrawerGesture'
-import {atoms as a, useGutters, useTheme} from '#/alf'
-import {Button, ButtonIcon} from '#/components/Button'
-import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times'
-import {Trending2_Stroke2_Corner2_Rounded as Graph} from '#/components/icons/Trending'
-import * as Prompt from '#/components/Prompt'
-import {TrendingTopicLink} from '#/components/TrendingTopics'
-import {Text} from '#/components/Typography'
-import {useAnalytics} from '#/analytics'
-
-const TRENDING_LIMIT = 14
-
-export function TrendingInterstitial() {
- const {enabled} = useTrendingConfig()
- const {trendingDisabled} = useTrendingSettings()
- return enabled && !trendingDisabled ? : null
-}
-
-export function Inner() {
- const t = useTheme()
- const {t: l} = useLingui()
- const ax = useAnalytics()
- const gutters = useGutters([0, 'base', 0, 'base'])
- const trendingPrompt = Prompt.usePromptControl()
- const {setTrendingDisabled} = useTrendingSettingsApi()
- const {
- data: trending,
- error,
- isLoading,
- } = useGetTrendsQuery({
- limit: TRENDING_LIMIT,
- refetchOnWindowFocus: true,
- })
- const noTopics = !isLoading && !error && !trending?.trends?.length
-
- const onConfirmHide = useCallback(() => {
- ax.metric('trendingTopics:hide', {context: 'interstitial'})
- setTrendingDisabled(true)
- }, [ax, setTrendingDisabled])
-
- return error || noTopics ? null : (
-
-
-
-
-
-
-
- {isLoading ? (
-
-
-
-
-
-
-
- {' '}
-
-
- ) : !trending?.trends ? null : (
- <>
- {trending.trends.map((topic, index) => {
- const rank = index + 1
- return (
- {
- ax.metric('trendingTopic:click', {
- context: 'interstitial',
- rank,
- recId: trending.recId,
- })
- }}>
-
-
- {topic.topic}
-
-
-
- )
- })}
-
- >
- )}
-
-
-
-
-
-
- )
-}
diff --git a/src/screens/Search/modules/ExploreTrendingTopics.tsx b/src/screens/Search/modules/ExploreTrendingTopics.tsx
index e8bfeed54a..72ca638dab 100644
--- a/src/screens/Search/modules/ExploreTrendingTopics.tsx
+++ b/src/screens/Search/modules/ExploreTrendingTopics.tsx
@@ -11,6 +11,7 @@ import {
useTrendingSettingsApi,
} from '#/state/preferences/trending'
import {
+ DEFAULT_FETCH_LIMIT,
DEFAULT_LIMIT,
useGetTrendsQuery,
} from '#/state/queries/trending/useGetTrendsQuery'
@@ -57,7 +58,10 @@ function Inner() {
error,
isLoading,
isRefetching,
- } = useGetTrendsQuery({limit: topicCount})
+ } = useGetTrendsQuery({
+ fetchLimit: Math.min(topicCount * 2, DEFAULT_FETCH_LIMIT),
+ limit: topicCount,
+ })
const noTopics = !isLoading && !error && !trending?.trends?.length
const showLoading = isLoading || isRefetching
diff --git a/src/state/queries/trending/useGetTrendsQuery.ts b/src/state/queries/trending/useGetTrendsQuery.ts
index fabeccd478..9c8e851f43 100644
--- a/src/state/queries/trending/useGetTrendsQuery.ts
+++ b/src/state/queries/trending/useGetTrendsQuery.ts
@@ -14,8 +14,10 @@ import {useAppviewClient} from '#/state/session'
import {app} from '#/lexicons'
export const DEFAULT_LIMIT = 5
+export const DEFAULT_FETCH_LIMIT = 20
type QueryProps = {
+ fetchLimit?: number
limit?: number
refetchOnWindowFocus?: boolean
}
@@ -29,12 +31,13 @@ function dedupe(trends: T[]): T[] {
})
}
-export const createGetTrendsQueryKey = (limit?: number) =>
- limit === undefined ? ['trends'] : ['trends', {limit}]
+export const createGetTrendsQueryKey = (fetchLimit?: number) =>
+ fetchLimit === undefined ? ['trends'] : ['trends', {limit: fetchLimit}]
export function useGetTrendsQuery(props: QueryProps = {}) {
const client = useAppviewClient()
const {data: preferences} = usePreferencesQuery()
+ const fetchLimit = props.fetchLimit ?? DEFAULT_FETCH_LIMIT
const limit = props.limit ?? DEFAULT_LIMIT
const mutedWords = useMemo(() => {
return preferences?.moderationPrefs?.mutedWords || []
@@ -44,13 +47,13 @@ export function useGetTrendsQuery(props: QueryProps = {}) {
enabled: !!preferences,
refetchOnWindowFocus: props.refetchOnWindowFocus,
staleTime: STALE.MINUTES.THREE,
- queryKey: createGetTrendsQueryKey(limit),
+ queryKey: createGetTrendsQueryKey(fetchLimit),
queryFn: async () => {
const contentLangs = getContentLanguages().join(',')
const data = await client.call(
app.bsky.unspecced.getTrends,
{
- limit,
+ limit: fetchLimit,
},
{
headers: {
@@ -75,10 +78,10 @@ export function useGetTrendsQuery(props: QueryProps = {}) {
text: `${t.topic} ${t.displayName} ${t.category}`,
})
}),
- ),
+ ).slice(0, limit),
}
},
- [mutedWords],
+ [limit, mutedWords],
),
})
}
diff --git a/src/view/com/posts/PostFeed.tsx b/src/view/com/posts/PostFeed.tsx
index 62bf3209c9..38fce08344 100644
--- a/src/view/com/posts/PostFeed.tsx
+++ b/src/view/com/posts/PostFeed.tsx
@@ -62,7 +62,6 @@ import {
PostFeedVideoGridRowPlaceholder,
} from '#/components/feeds/PostFeedVideoGridRow'
import {FeedTrendingTopicsInterstitial} from '#/components/interstitials/FeedTrendingTopics'
-import {TrendingInterstitial} from '#/components/interstitials/Trending'
import {TrendingVideos as TrendingVideosInterstitial} from '#/components/interstitials/TrendingVideos'
import {isStandardSiteEmbed} from '#/components/Post/Embed/StandardSiteEmbed/utils'
import {RichText} from '#/components/RichText'
@@ -146,10 +145,6 @@ type FeedRow =
type: 'interstitialProgressGuide'
key: string
}
- | {
- type: 'interstitialTrending'
- key: string
- }
| {
type: 'interstitialFeedTrendingTopics'
key: string
@@ -853,8 +848,6 @@ let PostFeed = ({
return
} else if (row.type === 'ageAssuranceBanner') {
return
- } else if (row.type === 'interstitialTrending') {
- return
} else if (row.type === 'interstitialFeedTrendingTopics') {
return (
diff --git a/src/view/shell/desktop/SidebarTrendingTopics.tsx b/src/view/shell/desktop/SidebarTrendingTopics.tsx
index 25f2510798..cd07fa83ac 100644
--- a/src/view/shell/desktop/SidebarTrendingTopics.tsx
+++ b/src/view/shell/desktop/SidebarTrendingTopics.tsx
@@ -46,7 +46,6 @@ function Inner() {
error,
isLoading,
} = useGetTrendsQuery({
- limit: DEFAULT_LIMIT,
refetchOnWindowFocus: true,
})
const noTopics = !isLoading && !error && !trending?.trends?.length