mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at tooltip 180 lines 4.9 kB view raw
1import { 2 AppBskyActorDefs, 3 AppBskyActorGetSuggestions, 4 AppBskyGraphGetSuggestedFollowsByActor, 5 moderateProfile, 6} from '@atproto/api' 7import { 8 InfiniteData, 9 QueryClient, 10 QueryKey, 11 useInfiniteQuery, 12 useQuery, 13} from '@tanstack/react-query' 14 15import { 16 aggregateUserInterests, 17 createBskyTopicsHeader, 18} from '#/lib/api/feed/utils' 19import {getContentLanguages} from '#/state/preferences/languages' 20import {STALE} from '#/state/queries' 21import {usePreferencesQuery} from '#/state/queries/preferences' 22import {useAgent, useSession} from '#/state/session' 23import {useModerationOpts} from '../preferences/moderation-opts' 24 25const suggestedFollowsQueryKeyRoot = 'suggested-follows' 26const suggestedFollowsQueryKey = (options?: SuggestedFollowsOptions) => [ 27 suggestedFollowsQueryKeyRoot, 28 options, 29] 30 31const suggestedFollowsByActorQueryKeyRoot = 'suggested-follows-by-actor' 32const suggestedFollowsByActorQueryKey = (did: string) => [ 33 suggestedFollowsByActorQueryKeyRoot, 34 did, 35] 36 37type SuggestedFollowsOptions = {limit?: number; subsequentPageLimit?: number} 38 39export function useSuggestedFollowsQuery(options?: SuggestedFollowsOptions) { 40 const {currentAccount} = useSession() 41 const agent = useAgent() 42 const moderationOpts = useModerationOpts() 43 const {data: preferences} = usePreferencesQuery() 44 const limit = options?.limit || 25 45 46 return useInfiniteQuery< 47 AppBskyActorGetSuggestions.OutputSchema, 48 Error, 49 InfiniteData<AppBskyActorGetSuggestions.OutputSchema>, 50 QueryKey, 51 string | undefined 52 >({ 53 enabled: !!moderationOpts && !!preferences, 54 staleTime: STALE.HOURS.ONE, 55 queryKey: suggestedFollowsQueryKey(options), 56 queryFn: async ({pageParam}) => { 57 const contentLangs = getContentLanguages().join(',') 58 const maybeDifferentLimit = 59 options?.subsequentPageLimit && pageParam 60 ? options.subsequentPageLimit 61 : limit 62 const res = await agent.app.bsky.actor.getSuggestions( 63 { 64 limit: maybeDifferentLimit, 65 cursor: pageParam, 66 }, 67 { 68 headers: { 69 ...createBskyTopicsHeader(aggregateUserInterests(preferences)), 70 'Accept-Language': contentLangs, 71 }, 72 }, 73 ) 74 75 res.data.actors = res.data.actors 76 .filter( 77 actor => 78 !moderateProfile(actor, moderationOpts!).ui('profileList').filter, 79 ) 80 .filter(actor => { 81 const viewer = actor.viewer 82 if (viewer) { 83 if ( 84 viewer.following || 85 viewer.muted || 86 viewer.mutedByList || 87 viewer.blockedBy || 88 viewer.blocking 89 ) { 90 return false 91 } 92 } 93 if (actor.did === currentAccount?.did) { 94 return false 95 } 96 return true 97 }) 98 99 return res.data 100 }, 101 initialPageParam: undefined, 102 getNextPageParam: lastPage => lastPage.cursor, 103 }) 104} 105 106export function useSuggestedFollowsByActorQuery({ 107 did, 108 enabled, 109}: { 110 did: string 111 enabled?: boolean 112}) { 113 const agent = useAgent() 114 return useQuery({ 115 queryKey: suggestedFollowsByActorQueryKey(did), 116 queryFn: async () => { 117 const res = await agent.app.bsky.graph.getSuggestedFollowsByActor({ 118 actor: did, 119 }) 120 const suggestions = res.data.isFallback 121 ? [] 122 : res.data.suggestions.filter(profile => !profile.viewer?.following) 123 return {suggestions, recId: res.data.recId} 124 }, 125 enabled, 126 }) 127} 128 129export function* findAllProfilesInQueryData( 130 queryClient: QueryClient, 131 did: string, 132): Generator<AppBskyActorDefs.ProfileView, void> { 133 yield* findAllProfilesInSuggestedFollowsQueryData(queryClient, did) 134 yield* findAllProfilesInSuggestedFollowsByActorQueryData(queryClient, did) 135} 136 137function* findAllProfilesInSuggestedFollowsQueryData( 138 queryClient: QueryClient, 139 did: string, 140) { 141 const queryDatas = queryClient.getQueriesData< 142 InfiniteData<AppBskyActorGetSuggestions.OutputSchema> 143 >({ 144 queryKey: [suggestedFollowsQueryKeyRoot], 145 }) 146 for (const [_queryKey, queryData] of queryDatas) { 147 if (!queryData?.pages) { 148 continue 149 } 150 for (const page of queryData?.pages) { 151 for (const actor of page.actors) { 152 if (actor.did === did) { 153 yield actor 154 } 155 } 156 } 157 } 158} 159 160function* findAllProfilesInSuggestedFollowsByActorQueryData( 161 queryClient: QueryClient, 162 did: string, 163) { 164 const queryDatas = 165 queryClient.getQueriesData<AppBskyGraphGetSuggestedFollowsByActor.OutputSchema>( 166 { 167 queryKey: [suggestedFollowsByActorQueryKeyRoot], 168 }, 169 ) 170 for (const [_queryKey, queryData] of queryDatas) { 171 if (!queryData) { 172 continue 173 } 174 for (const suggestion of queryData.suggestions) { 175 if (suggestion.did === did) { 176 yield suggestion 177 } 178 } 179 } 180}