import {useCallback, useMemo} from 'react' import {type AppBskyUnspeccedGetTrends, hasMutedWord} from '@atproto/api' import {useQuery} from '@tanstack/react-query' import { aggregateUserInterests, createBskyTopicsHeader, } from '#/lib/api/feed/utils' import {logger} from '#/logger' import {getContentLanguages} from '#/state/preferences/languages' import {STALE} from '#/state/queries' import {usePreferencesQuery} from '#/state/queries/preferences' import {useAgent} from '#/state/session' export const DEFAULT_LIMIT = 5 type QueryProps = { limit?: number refetchOnWindowFocus?: boolean } function dedupe(trends: T[]): T[] { const seen = new Set() return trends.filter(trend => { if (seen.has(trend.link)) return false seen.add(trend.link) return true }) } export const createGetTrendsQueryKey = (limit?: number) => limit === undefined ? ['trends'] : ['trends', {limit}] export function useGetTrendsQuery(props: QueryProps = {}) { const agent = useAgent() const {data: preferences} = usePreferencesQuery() const limit = props.limit ?? DEFAULT_LIMIT const mutedWords = useMemo(() => { return preferences?.moderationPrefs?.mutedWords || [] }, [preferences?.moderationPrefs]) return useQuery({ enabled: !!preferences, refetchOnWindowFocus: props.refetchOnWindowFocus, staleTime: STALE.MINUTES.THREE, queryKey: createGetTrendsQueryKey(limit), queryFn: async () => { const contentLangs = getContentLanguages().join(',') const {data} = await agent.app.bsky.unspecced.getTrends( { limit, }, { headers: { ...createBskyTopicsHeader(aggregateUserInterests(preferences)), 'Accept-Language': contentLangs, }, }, ) if (!data.recIdStr) { logger.debug('useGetTrendsQuery response missing recIdStr') } return data }, select: useCallback( (data: AppBskyUnspeccedGetTrends.OutputSchema) => { return { recId: data.recIdStr, trends: dedupe( (data.trends ?? []).filter(t => { return !hasMutedWord({ mutedWords, text: `${t.topic} ${t.displayName} ${t.category}`, }) }), ), } }, [mutedWords], ), }) }