deer social fork for personal usage. but you might see a use idk. github mirror

Include follow-based suggestions in interstitial (#4889)

authored by danabra.mov and committed by GitHub 2174feed f1031d10

Changed files
+40 -2
src
+12 -2
src/components/FeedInterstitials.tsx
··· 133 133 const {currentAccount} = useSession() 134 134 const userActionSnapshot = userActionHistory.useActionHistorySnapshot() 135 135 const dids = React.useMemo(() => { 136 - const {likes, follows, seen} = userActionSnapshot 136 + const {likes, follows, followSuggestions, seen} = userActionSnapshot 137 137 const likeDids = likes 138 138 .map(l => new AtUri(l)) 139 139 .map(uri => uri.host) 140 140 .filter(did => !follows.includes(did)) 141 + let suggestedDids: string[] = [] 142 + if (followSuggestions.length > 0) { 143 + suggestedDids = [ 144 + // It's ok if these will pick the same item (weighed by its frequency) 145 + followSuggestions[Math.floor(Math.random() * followSuggestions.length)], 146 + followSuggestions[Math.floor(Math.random() * followSuggestions.length)], 147 + followSuggestions[Math.floor(Math.random() * followSuggestions.length)], 148 + followSuggestions[Math.floor(Math.random() * followSuggestions.length)], 149 + ] 150 + } 141 151 const seenDids = seen 142 152 .sort(sortSeenPosts) 143 153 .map(l => new AtUri(l.uri)) 144 154 .map(uri => uri.host) 145 - return [...new Set([...likeDids, ...seenDids])].filter( 155 + return [...new Set([...suggestedDids, ...likeDids, ...seenDids])].filter( 146 156 did => did !== currentAccount?.did, 147 157 ) 148 158 }, [userActionSnapshot, currentAccount])
+15
src/state/queries/profile.ts
··· 222 222 logContext: LogEvents['profile:follow']['logContext'] & 223 223 LogEvents['profile:unfollow']['logContext'], 224 224 ) { 225 + const agent = useAgent() 225 226 const queryClient = useQueryClient() 226 227 const did = profile.did 227 228 const initialFollowingUri = profile.viewer?.following ··· 253 254 updateProfileShadow(queryClient, did, { 254 255 followingUri: finalFollowingUri, 255 256 }) 257 + 258 + if (finalFollowingUri) { 259 + agent.app.bsky.graph 260 + .getSuggestedFollowsByActor({ 261 + actor: did, 262 + }) 263 + .then(res => { 264 + const dids = res.data.suggestions 265 + .filter(a => !a.viewer?.following) 266 + .map(a => a.did) 267 + .slice(0, 8) 268 + userActionHistory.followSuggestion(dids) 269 + }) 270 + } 256 271 }, 257 272 }) 258 273
+13
src/state/userActionHistory.ts
··· 2 2 3 3 const LIKE_WINDOW = 100 4 4 const FOLLOW_WINDOW = 100 5 + const FOLLOW_SUGGESTION_WINDOW = 100 5 6 const SEEN_WINDOW = 100 6 7 7 8 export type SeenPost = { ··· 22 23 * The last 100 DIDs the user has followed 23 24 */ 24 25 follows: string[] 26 + /* 27 + * The last 100 DIDs of suggested follows based on last follows 28 + */ 29 + followSuggestions: string[] 25 30 /** 26 31 * The last 100 post URIs the user has seen from the Discover feed only 27 32 */ ··· 31 36 const userActionHistory: UserActionHistory = { 32 37 likes: [], 33 38 follows: [], 39 + followSuggestions: [], 34 40 seen: [], 35 41 } 36 42 ··· 58 64 .concat(dids) 59 65 .slice(-FOLLOW_WINDOW) 60 66 } 67 + 68 + export function followSuggestion(dids: string[]) { 69 + userActionHistory.followSuggestions = userActionHistory.followSuggestions 70 + .concat(dids) 71 + .slice(-FOLLOW_SUGGESTION_WINDOW) 72 + } 73 + 61 74 export function unfollow(dids: string[]) { 62 75 userActionHistory.follows = userActionHistory.follows.filter( 63 76 uri => !dids.includes(uri),