+12
-2
src/components/FeedInterstitials.tsx
+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
+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
+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),