83 lines
2.3 KiB
TypeScript
83 lines
2.3 KiB
TypeScript
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<T extends {link: string}>(trends: T[]): T[] {
|
|
const seen = new Set<string>()
|
|
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],
|
|
),
|
|
})
|
|
}
|