New user progress guides (#4716)
* Add the animated checkmark svg * Add progress guide list and task components * Add ProgressGuide Toast component * Implement progress-guide controller * Add 7 follows to the progress guide * Wire up action captures * Wire up progress-guide persistence * Trigger progress guide on account creation * Clear the progress guide from storage on complete * Add progress guide interstitial, put behind gate * Fix: read progress guide state from prefs * Some defensive type checks * Create separate toast for completion * List tweaks * Only show on Discover * Spacing and progress tweaks * Completely hide when complete * Capture the progress guide in local state, and only render toasts while guide is active * Fix: ensure persisted hydrates into local state * Gate --------- Co-authored-by: Eric Bailey <git@esb.lol> Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
This commit is contained in:
parent
aa7117edb6
commit
0ed99b840d
19 changed files with 721 additions and 22 deletions
|
@ -34,7 +34,11 @@ import {useSession} from '#/state/session'
|
|||
import {useAnalytics} from 'lib/analytics/analytics'
|
||||
import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender'
|
||||
import {useTheme} from 'lib/ThemeContext'
|
||||
import {SuggestedFeeds, SuggestedFollows} from '#/components/FeedInterstitials'
|
||||
import {
|
||||
ProgressGuide,
|
||||
SuggestedFeeds,
|
||||
SuggestedFollows,
|
||||
} from '#/components/FeedInterstitials'
|
||||
import {List, ListRef} from '../util/List'
|
||||
import {PostFeedLoadingPlaceholder} from '../util/LoadingPlaceholder'
|
||||
import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
|
||||
|
@ -85,12 +89,26 @@ type FeedItem =
|
|||
}
|
||||
slot: number
|
||||
}
|
||||
| {
|
||||
type: 'interstitialProgressGuide'
|
||||
key: string
|
||||
params: {
|
||||
variant: 'default' | string
|
||||
}
|
||||
slot: number
|
||||
}
|
||||
|
||||
const feedInterstitialType = 'interstitialFeeds'
|
||||
const followInterstitialType = 'interstitialFollows'
|
||||
const progressGuideInterstitialType = 'interstitialProgressGuide'
|
||||
const interstials: Record<
|
||||
'following' | 'discover',
|
||||
(FeedItem & {type: 'interstitialFeeds' | 'interstitialFollows'})[]
|
||||
(FeedItem & {
|
||||
type:
|
||||
| 'interstitialFeeds'
|
||||
| 'interstitialFollows'
|
||||
| 'interstitialProgressGuide'
|
||||
})[]
|
||||
> = {
|
||||
following: [
|
||||
{
|
||||
|
@ -111,6 +129,14 @@ const interstials: Record<
|
|||
},
|
||||
],
|
||||
discover: [
|
||||
{
|
||||
type: progressGuideInterstitialType,
|
||||
params: {
|
||||
variant: 'default',
|
||||
},
|
||||
key: progressGuideInterstitialType,
|
||||
slot: 0,
|
||||
},
|
||||
{
|
||||
type: feedInterstitialType,
|
||||
params: {
|
||||
|
@ -336,14 +362,14 @@ let Feed = ({
|
|||
|
||||
if (feedType) {
|
||||
for (const interstitial of interstials[feedType]) {
|
||||
const feedInterstitialEnabled =
|
||||
interstitial.type === feedInterstitialType &&
|
||||
gate('suggested_feeds_interstitial')
|
||||
const followInterstitialEnabled =
|
||||
interstitial.type === followInterstitialType &&
|
||||
gate('suggested_follows_interstitial')
|
||||
const shouldShow =
|
||||
(interstitial.type === feedInterstitialType &&
|
||||
gate('suggested_feeds_interstitial')) ||
|
||||
(interstitial.type === followInterstitialType &&
|
||||
gate('suggested_follows_interstitial')) ||
|
||||
interstitial.type === progressGuideInterstitialType
|
||||
|
||||
if (feedInterstitialEnabled || followInterstitialEnabled) {
|
||||
if (shouldShow) {
|
||||
const variant = 'default' // replace with experiment variant
|
||||
const int = {
|
||||
...interstitial,
|
||||
|
@ -460,6 +486,8 @@ let Feed = ({
|
|||
return <SuggestedFeeds />
|
||||
} else if (item.type === followInterstitialType) {
|
||||
return <SuggestedFollows />
|
||||
} else if (item.type === progressGuideInterstitialType) {
|
||||
return <ProgressGuide />
|
||||
} else if (item.type === 'slice') {
|
||||
if (item.slice.rootUri === FALLBACK_MARKER_POST.post.uri) {
|
||||
// HACK
|
||||
|
|
|
@ -31,6 +31,10 @@ import {
|
|||
} from '#/state/queries/post'
|
||||
import {useRequireAuth, useSession} from '#/state/session'
|
||||
import {useComposerControls} from '#/state/shell/composer'
|
||||
import {
|
||||
ProgressGuideAction,
|
||||
useProgressGuideControls,
|
||||
} from '#/state/shell/progress-guide'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {useDialogControl} from '#/components/Dialog'
|
||||
import {ArrowOutOfBox_Stroke2_Corner0_Rounded as ArrowOutOfBox} from '#/components/icons/ArrowOutOfBox'
|
||||
|
@ -77,6 +81,7 @@ let PostCtrls = ({
|
|||
const requireAuth = useRequireAuth()
|
||||
const loggedOutWarningPromptControl = useDialogControl()
|
||||
const {sendInteraction} = useFeedFeedbackContext()
|
||||
const {captureAction} = useProgressGuideControls()
|
||||
const playHaptic = useHaptics()
|
||||
const gate = useGate()
|
||||
|
||||
|
@ -103,6 +108,7 @@ let PostCtrls = ({
|
|||
event: 'app.bsky.feed.defs#interactionLike',
|
||||
feedContext,
|
||||
})
|
||||
captureAction(ProgressGuideAction.Like)
|
||||
await queueLike()
|
||||
} else {
|
||||
await queueUnlike()
|
||||
|
@ -119,6 +125,7 @@ let PostCtrls = ({
|
|||
queueLike,
|
||||
queueUnlike,
|
||||
sendInteraction,
|
||||
captureAction,
|
||||
feedContext,
|
||||
])
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import {Text} from 'view/com/util/text/Text'
|
|||
import {DesktopFeeds} from './Feeds'
|
||||
import {DesktopSearch} from './Search'
|
||||
import hairlineWidth = StyleSheet.hairlineWidth
|
||||
import {ProgressGuideList} from '#/components/ProgressGuide/List'
|
||||
|
||||
export function DesktopRightNav({routeName}: {routeName: string}) {
|
||||
const pal = usePalette('default')
|
||||
|
@ -39,9 +40,12 @@ export function DesktopRightNav({routeName}: {routeName: string}) {
|
|||
<DesktopSearch />
|
||||
|
||||
{hasSession && (
|
||||
<View style={[pal.border, styles.desktopFeedsContainer]}>
|
||||
<DesktopFeeds />
|
||||
</View>
|
||||
<>
|
||||
<ProgressGuideList style={[{marginTop: 22, marginBottom: 8}]} />
|
||||
<View style={[pal.border, styles.desktopFeedsContainer]}>
|
||||
<DesktopFeeds />
|
||||
</View>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue