Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

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

Use getSuggestions endpoint behind the gate (#3499)

* Move suggested follows out of the component

* Add new suggestions implementation

* Put new endpoint behind the gate

* Make bottom less weird

authored by

dan and committed by
GitHub
bedb0c3f e3e8f105

+66 -5
+1
src/lib/statsig/gates.ts
··· 7 7 | 'new_search' 8 8 | 'show_follow_back_label' 9 9 | 'start_session_with_following' 10 + | 'use_new_suggestions_endpoint'
+4 -1
src/lib/statsig/statsig.tsx
··· 82 82 // This should not happen because of waitForInitialization={true}. 83 83 console.error('Did not expected isLoading to ever be true.') 84 84 } 85 - return value 85 + // This shouldn't technically be necessary but let's get a strong 86 + // guarantee that a gate value can never change while mounted. 87 + const [initialValue] = React.useState(value) 88 + return initialValue 86 89 } 87 90 88 91 function toStatsigUser(did: string | undefined) {
+61 -4
src/view/screens/Search/Search.tsx
··· 32 32 import {useActorSearch} from '#/state/queries/actor-search' 33 33 import {useModerationOpts} from '#/state/queries/preferences' 34 34 import {useSearchPostsQuery} from '#/state/queries/search-posts' 35 - import {useGetSuggestedFollowersByActor} from '#/state/queries/suggested-follows' 35 + import { 36 + useGetSuggestedFollowersByActor, 37 + useSuggestedFollowsQuery, 38 + } from '#/state/queries/suggested-follows' 36 39 import {useSession} from '#/state/session' 37 40 import {useSetDrawerOpen} from '#/state/shell' 38 41 import {useSetDrawerSwipeDisabled, useSetMinimalShellMode} from '#/state/shell' ··· 118 121 ) 119 122 } 120 123 121 - function SearchScreenSuggestedFollows() { 122 - const pal = usePalette('default') 124 + function useSuggestedFollowsV1(): [ 125 + AppBskyActorDefs.ProfileViewBasic[], 126 + () => void, 127 + ] { 123 128 const {currentAccount} = useSession() 124 129 const [suggestions, setSuggestions] = React.useState< 125 130 AppBskyActorDefs.ProfileViewBasic[] ··· 162 167 } 163 168 }, [currentAccount, setSuggestions, getSuggestedFollowsByActor]) 164 169 170 + return [suggestions, () => {}] 171 + } 172 + 173 + function useSuggestedFollowsV2(): [ 174 + AppBskyActorDefs.ProfileViewBasic[], 175 + () => void, 176 + ] { 177 + const { 178 + data: suggestions, 179 + hasNextPage, 180 + isFetchingNextPage, 181 + isError, 182 + fetchNextPage, 183 + } = useSuggestedFollowsQuery() 184 + 185 + const onEndReached = React.useCallback(async () => { 186 + if (isFetchingNextPage || !hasNextPage || isError) return 187 + try { 188 + await fetchNextPage() 189 + } catch (err) { 190 + logger.error('Failed to load more suggested follows', {message: err}) 191 + } 192 + }, [isFetchingNextPage, hasNextPage, isError, fetchNextPage]) 193 + 194 + const items: AppBskyActorDefs.ProfileViewBasic[] = [] 195 + if (suggestions) { 196 + // Currently the responses contain duplicate items. 197 + // Needs to be fixed on backend, but let's dedupe to be safe. 198 + let seen = new Set() 199 + for (const page of suggestions.pages) { 200 + for (const actor of page.actors) { 201 + if (!seen.has(actor.did)) { 202 + seen.add(actor.did) 203 + items.push(actor) 204 + } 205 + } 206 + } 207 + } 208 + return [items, onEndReached] 209 + } 210 + 211 + function SearchScreenSuggestedFollows() { 212 + const pal = usePalette('default') 213 + const useSuggestedFollows = useGate('use_new_suggestions_endpoint') 214 + ? // Conditional hook call here is *only* OK because useGate() 215 + // result won't change until a remount. 216 + useSuggestedFollowsV2 217 + : useSuggestedFollowsV1 218 + const [suggestions, onEndReached] = useSuggestedFollows() 219 + 165 220 return suggestions.length ? ( 166 221 <List 167 222 data={suggestions} ··· 169 224 keyExtractor={item => item.did} 170 225 // @ts-ignore web only -prf 171 226 desktopFixedHeight 172 - contentContainerStyle={{paddingBottom: 1200}} 227 + contentContainerStyle={{paddingBottom: 200}} 173 228 keyboardShouldPersistTaps="handled" 174 229 keyboardDismissMode="on-drag" 230 + onEndReached={onEndReached} 231 + onEndReachedThreshold={2} 175 232 /> 176 233 ) : ( 177 234 <CenteredView sideBorders style={[pal.border, s.hContentRegion]}>