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