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,37 +1,74 @@
import React from 'react'
import {Platform, StyleSheet, View} from 'react-native'
import {StyleSheet, View} from 'react-native'
import {Text} from './text/Text'
import {ago} from 'lib/strings/time'
import {usePalette} from 'lib/hooks/usePalette'
import {useStores} from 'state/index'
import {observer} from 'mobx-react-lite'
import FollowButton from '../profile/FollowButton'
interface PostMetaOpts {
authorHandle: string
authorDisplayName: string | undefined
timestamp: string
did: string
declarationCid: string
showFollowBtn?: boolean
}
export function PostMeta(opts: PostMetaOpts) {
export const PostMeta = observer(function (opts: PostMetaOpts) {
const pal = usePalette('default')
let displayName = opts.authorDisplayName || opts.authorHandle
let handle = opts.authorHandle
const store = useStores()
const isMe = opts.did === store.me.did
// HACK
// Android simply cannot handle the truncation case we need
// so we have to do it manually here
// -prf
if (Platform.OS === 'android') {
if (displayName.length + handle.length > 26) {
if (displayName.length > 26) {
displayName = displayName.slice(0, 23) + '...'
} else {
handle = handle.slice(0, 23 - displayName.length) + '...'
if (handle.endsWith('....')) {
handle = handle.slice(0, -4) + '...'
}
}
}
// NOTE we capture `isFollowing` via a memo so that follows
// don't change this UI immediately, but rather upon future
// renders
const isFollowing = React.useMemo(
() => store.me.follows.isFollowing(opts.did),
[opts.did, store.me.follows],
)
if (opts.showFollowBtn && !isMe && !isFollowing) {
// two-liner with follow button
return (
<View style={[styles.metaTwoLine]}>
<View>
<Text
type="lg-bold"
style={[pal.text]}
numberOfLines={1}
lineHeight={1.2}>
{displayName}{' '}
<Text
type="md"
style={[styles.metaItem, pal.textLight]}
lineHeight={1.2}>
&middot; {ago(opts.timestamp)}
</Text>
</Text>
<Text
type="md"
style={[styles.metaItem, pal.textLight]}
lineHeight={1.2}>
{handle ? (
<Text type="md" style={[pal.textLight]}>
@{handle}
</Text>
) : undefined}
</Text>
</View>
<View>
<FollowButton did={opts.did} declarationCid={opts.declarationCid} />
</View>
</View>
)
}
// one-liner
return (
<View style={styles.meta}>
<View style={[styles.metaItem, styles.maxWidth]}>
@ -53,13 +90,18 @@ export function PostMeta(opts: PostMetaOpts) {
</Text>
</View>
)
}
})
const styles = StyleSheet.create({
meta: {
flexDirection: 'row',
alignItems: 'baseline',
paddingTop: 0,
paddingBottom: 2,
},
metaTwoLine: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingBottom: 2,
},
metaItem: {

View file

@ -0,0 +1,33 @@
import React from 'react'
import {StyleSheet, View} from 'react-native'
import {usePalette} from 'lib/hooks/usePalette'
import {Text} from './text/Text'
import {s} from 'lib/styles'
export function WelcomeBanner() {
const pal = usePalette('default')
return (
<View
testID="welcomeBanner"
style={[pal.view, styles.container, pal.border]}>
<Text
type="title-lg"
style={[pal.text, s.textCenter, s.bold, s.pb5]}
lineHeight={1.1}>
Welcome to the private beta!
</Text>
<Text type="lg" style={[pal.text, s.textCenter]}>
Here are some recent posts. Follow their creators to build your feed.
</Text>
</View>
)
}
const styles = StyleSheet.create({
container: {
paddingTop: 30,
paddingBottom: 26,
paddingHorizontal: 20,
borderTopWidth: 1,
},
})