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>
This commit is contained in:
Ansh 2023-03-02 10:21:33 -08:00 committed by GitHub
parent 9b46b2e6a9
commit bd9386d81c
31 changed files with 426 additions and 866 deletions

View file

@ -1,21 +1,12 @@
import {makeAutoObservable, runInAction} from 'mobx'
import {
AppBskyFeedFeedViewPost,
AppBskyFeedGetAuthorFeed as GetAuthorFeed,
} from '@atproto/api'
type ReasonRepost = AppBskyFeedFeedViewPost.ReasonRepost
import {RootStoreModel} from './root-store'
import {FeedItemModel} from './feed-view'
import {cleanError} from 'lib/strings/errors'
const TEAM_HANDLES = [
'jay.bsky.social',
'paul.bsky.social',
'dan.bsky.social',
'divy.bsky.social',
'why.bsky.social',
'iamrosewang.bsky.social',
]
import {TEAM_HANDLES} from 'lib/constants'
import {
getMultipleAuthorsPosts,
mergePosts,
} from 'lib/api/build-suggested-posts'
export class SuggestedPostsView {
// state
@ -54,15 +45,18 @@ export class SuggestedPostsView {
async setup() {
this._xLoading()
try {
const responses = await Promise.all(
TEAM_HANDLES.map(handle =>
this.rootStore.api.app.bsky.feed
.getAuthorFeed({author: handle, limit: 10})
.catch(_err => ({success: false, headers: {}, data: {feed: []}})),
),
const responses = await getMultipleAuthorsPosts(
this.rootStore,
TEAM_HANDLES(String(this.rootStore.agent.service)),
)
runInAction(() => {
this.posts = mergeAndFilterResponses(this.rootStore, responses)
const finalPosts = mergePosts(responses, {repostsOnly: true})
// hydrate into models
this.posts = finalPosts.map((post, i) => {
// strip the reasons to hide that these are reposts
delete post.reason
return new FeedItemModel(this.rootStore, `post-${i}`, post)
})
})
this._xIdle()
} catch (e: any) {
@ -90,59 +84,3 @@ export class SuggestedPostsView {
}
}
}
function mergeAndFilterResponses(
store: RootStoreModel,
responses: GetAuthorFeed.Response[],
): FeedItemModel[] {
let posts: AppBskyFeedFeedViewPost.Main[] = []
// 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 now = Date.now()
const uris = new Set()
posts = posts.filter(p => {
if (isARepostOfSomeoneElse(p) && isRecentEnough(now, p)) {
if (uris.has(p.post.uri)) {
return false
}
uris.add(p.post.uri)
return true
}
return false
})
// sort by index time
posts.sort((a, b) => {
return (
Number(new Date(b.post.indexedAt)) - Number(new Date(a.post.indexedAt))
)
})
// hydrate into models and strip the reasons to hide that these are reposts
return posts.map((post, i) => {
delete post.reason
return new FeedItemModel(store, `post-${i}`, post)
})
}
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
)
}
const THREE_DAYS = 3 * 24 * 60 * 60 * 1000
function isRecentEnough(
now: number,
post: AppBskyFeedFeedViewPost.Main,
): boolean {
return now - Number(new Date(post.post.indexedAt)) < THREE_DAYS
}