forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {useCallback, useMemo} from 'react'
2import {type AppBskyUnspeccedDefs, hasMutedWord} from '@atproto/api'
3import {useQuery} from '@tanstack/react-query'
4
5import {STALE} from '#/state/queries'
6import {usePreferencesQuery} from '#/state/queries/preferences'
7import {useAgent} from '#/state/session'
8
9export type TrendingTopic = AppBskyUnspeccedDefs.TrendingTopic
10
11type Response = {
12 topics: TrendingTopic[]
13 suggested: TrendingTopic[]
14}
15
16export const DEFAULT_LIMIT = 14
17
18function dedup(topics: TrendingTopic[]): TrendingTopic[] {
19 const seen = new Set<string>()
20 return topics.filter(t => {
21 if (seen.has(t.link)) return false
22 seen.add(t.link)
23 return true
24 })
25}
26
27export const trendingTopicsQueryKey = ['trending-topics']
28
29export function useTrendingTopics() {
30 const agent = useAgent()
31 const {data: preferences} = usePreferencesQuery()
32 const mutedWords = useMemo(
33 () => preferences?.moderationPrefs?.mutedWords ?? [],
34 [preferences?.moderationPrefs?.mutedWords],
35 )
36
37 return useQuery<Response>({
38 refetchOnWindowFocus: true,
39 staleTime: STALE.MINUTES.THREE,
40 queryKey: trendingTopicsQueryKey,
41 async queryFn() {
42 const {data} = await agent.app.bsky.unspecced.getTrendingTopics({
43 limit: DEFAULT_LIMIT,
44 })
45 return {
46 topics: data.topics ?? [],
47 suggested: data.suggested ?? [],
48 }
49 },
50 select: useCallback(
51 (data: Response) => {
52 return {
53 topics: dedup(
54 data.topics.filter(t => {
55 return !hasMutedWord({
56 mutedWords,
57 text: `${t.topic} ${t.displayName ?? ''} ${t.description ?? ''}`,
58 })
59 }),
60 ),
61 suggested: dedup(
62 data.suggested.filter(t => {
63 return !hasMutedWord({
64 mutedWords,
65 text: `${t.topic} ${t.displayName ?? ''} ${t.description ?? ''}`,
66 })
67 }),
68 ),
69 }
70 },
71 [mutedWords],
72 ),
73 })
74}