diff options
author | Ansh <anshnanda10@gmail.com> | 2023-03-02 10:21:33 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-02 12:21:33 -0600 |
commit | bd9386d81c258d3d3f43666d3e25328f68428689 (patch) | |
tree | 8008c5dcfc41f85aac24abac0f6fec08dea6296f /src/lib/api | |
parent | 9b46b2e6a9a8e4e9254fa9031b2eb44a672e287f (diff) | |
download | voidsky-bd9386d81c258d3d3f43666d3e25328f68428689.tar.zst |
New onboarding (#241)
* delete old onboarding files and code * add custom FollowButton component to Post, FeedItem, & ProfileCard * move building suggested feed into helper lib * show suggested posts/feed if follower list is empty * Update tsconfig.json * add pagination to getting new onboarding * remove unnecessary console log * fix naming, add better null check for combinedCursor * In locally-combined feeds, correctly produce an undefined cursor when out of data * Minor refactors of the suggested posts lib functions * Show 'follow button' style of post meta in certain conditions only * Only show follow btn in posts on the main feed and the discovery feed * Add a welcome notice to the home feed * Tune the timing of when the welcome banner shows or hides * Make the follow button an observer (closes #244) * Update postmeta to keep the follow btn after press until next render * A couple of fixes that ensure consistent welcome screen * Fix lint * Rework the welcome banner * Fix cache invalidation of follows model on user switch * Show welcome banner while loading * Update the home onboarding feed to get top posts from hardcode recommends * Drop unused helper function * Update happy path tests --------- Co-authored-by: Paul Frazee <pfrazee@gmail.com>
Diffstat (limited to 'src/lib/api')
-rw-r--r-- | src/lib/api/build-suggested-posts.ts | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/src/lib/api/build-suggested-posts.ts b/src/lib/api/build-suggested-posts.ts new file mode 100644 index 000000000..6250f4a9c --- /dev/null +++ b/src/lib/api/build-suggested-posts.ts @@ -0,0 +1,120 @@ +import {RootStoreModel} from 'state/index' +import { + AppBskyFeedFeedViewPost, + AppBskyFeedGetAuthorFeed as GetAuthorFeed, +} from '@atproto/api' +type ReasonRepost = AppBskyFeedFeedViewPost.ReasonRepost + +async function getMultipleAuthorsPosts( + rootStore: RootStoreModel, + authors: string[], + cursor: string | undefined = undefined, + limit: number = 10, +) { + const responses = await Promise.all( + authors.map((author, index) => + rootStore.api.app.bsky.feed + .getAuthorFeed({ + author, + limit, + before: cursor ? cursor.split(',')[index] : undefined, + }) + .catch(_err => ({success: false, headers: {}, data: {feed: []}})), + ), + ) + return responses +} + +function mergePosts( + responses: GetAuthorFeed.Response[], + {repostsOnly, bestOfOnly}: {repostsOnly?: boolean; bestOfOnly?: boolean}, +) { + let posts: AppBskyFeedFeedViewPost.Main[] = [] + + if (bestOfOnly) { + for (const res of responses) { + if (res.success) { + // filter the feed down to the post with the most upvotes + res.data.feed = res.data.feed.reduce( + (acc: AppBskyFeedFeedViewPost.Main[], v) => { + if (!acc?.[0] && !v.reason) { + return [v] + } + if ( + acc && + !v.reason && + v.post.upvoteCount > acc[0].post.upvoteCount + ) { + return [v] + } + return acc + }, + [], + ) + } + } + } + + // merge into one array + for (const res of responses) { + if (res.success) { + posts = posts.concat(res.data.feed) + } + } + + // filter down to reposts of other users + const uris = new Set() + posts = posts.filter(p => { + if (repostsOnly && !isARepostOfSomeoneElse(p)) { + return false + } + if (uris.has(p.post.uri)) { + return false + } + uris.add(p.post.uri) + return true + }) + + // sort by index time + posts.sort((a, b) => { + return ( + Number(new Date(b.post.indexedAt)) - Number(new Date(a.post.indexedAt)) + ) + }) + + return posts +} + +function isARepostOfSomeoneElse(post: AppBskyFeedFeedViewPost.Main): boolean { + return ( + post.reason?.$type === 'app.bsky.feed.feedViewPost#reasonRepost' && + post.post.author.did !== (post.reason as ReasonRepost).by.did + ) +} + +function getCombinedCursors(responses: GetAuthorFeed.Response[]) { + let hasCursor = false + const cursors = responses.map(r => { + if (r.data.cursor) { + hasCursor = true + return r.data.cursor + } + return '' + }) + if (!hasCursor) { + return undefined + } + const combinedCursors = cursors.join(',') + return combinedCursors +} + +function isCombinedCursor(cursor: string) { + return cursor.includes(',') +} + +export { + getMultipleAuthorsPosts, + mergePosts, + getCombinedCursors, + isCombinedCursor, +} |