add screen to onboarding flow

This commit is contained in:
Hailey
2024-02-13 09:31:26 -08:00
parent 36e1da1006
commit 579a07db9e
3 changed files with 169 additions and 2 deletions
@@ -0,0 +1,158 @@
import React from 'react'
import {View} from 'react-native'
import {useLingui} from '@lingui/react'
import {msg, Trans} from '@lingui/macro'
import {logger} from '#/logger'
import {atoms as a, useTheme} from '#/alf'
import {Button, ButtonText, ButtonIcon} from '#/components/Button'
import {News2_Stroke2_Corner0_Rounded as News} from '#/components/icons/News2'
import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check'
import {Growth_Stroke2_Corner0_Rounded as Growth} from '#/components/icons/Growth'
import {Trending2_Stroke2_Corner2_Rounded as Trending} from '#/components/icons/Trending2'
import {Text} from '#/components/Typography'
import {useOnboardingDispatch} from '#/state/shell'
import {Loader} from '#/components/Loader'
import {useSetSaveFeedsMutation} from '#/state/queries/preferences'
import {getAgent} from '#/state/session'
import {useAnalytics} from '#/lib/analytics/analytics'
import {Context} from '#/screens/Onboarding/state'
import {
Title,
Description,
OnboardingControls,
} from '#/screens/Onboarding/Layout'
import {IconCircle} from '#/screens/Onboarding/IconCircle'
import {
bulkWriteFollows,
sortPrimaryAlgorithmFeeds,
} from '#/screens/Onboarding/util'
export function StepProfile() {
const {_} = useLingui()
const t = useTheme()
const {track} = useAnalytics()
const {state, dispatch} = React.useContext(Context)
const onboardDispatch = useOnboardingDispatch()
const [saving, setSaving] = React.useState(false)
const {mutateAsync: saveFeeds} = useSetSaveFeedsMutation()
const finishOnboarding = React.useCallback(async () => {
setSaving(true)
const {
interestsStepResults,
suggestedAccountsStepResults,
algoFeedsStepResults,
topicalFeedsStepResults,
} = state
const {selectedInterests} = interestsStepResults
const selectedFeeds = [
...sortPrimaryAlgorithmFeeds(algoFeedsStepResults.feedUris),
...topicalFeedsStepResults.feedUris,
]
try {
await Promise.all([
bulkWriteFollows(suggestedAccountsStepResults.accountDids),
// these must be serial
(async () => {
await getAgent().setInterestsPref({tags: selectedInterests})
await saveFeeds({
saved: selectedFeeds,
pinned: selectedFeeds,
})
})(),
])
} catch (e: any) {
logger.info(`onboarding: bulk save failed`)
logger.error(e)
// don't alert the user, just let them into their account
}
setSaving(false)
dispatch({type: 'finish'})
onboardDispatch({type: 'finish'})
track('OnboardingV2:StepFinished:End')
track('OnboardingV2:Complete')
}, [state, dispatch, onboardDispatch, setSaving, saveFeeds, track])
React.useEffect(() => {
track('OnboardingV2:StepFinished:Start')
}, [track])
return (
<View style={[a.align_start]}>
<IconCircle icon={Check} style={[a.mb_2xl]} />
<Title>
<Trans>You're ready to go!</Trans>
</Title>
<Description>
<Trans>We hope you have a wonderful time. Remember, Bluesky is:</Trans>
</Description>
<View style={[a.pt_5xl, a.gap_3xl]}>
<View style={[a.flex_row, a.align_center, a.w_full, a.gap_lg]}>
<IconCircle icon={Growth} size="lg" style={{width: 48, height: 48}} />
<View style={[a.flex_1, a.gap_xs]}>
<Text style={[a.font_bold, a.text_lg]}>
<Trans>Public</Trans>
</Text>
<Text
style={[t.atoms.text_contrast_medium, a.text_md, a.leading_snug]}>
<Trans>
Your posts, likes, and blocks are public. Mutes are private.
</Trans>
</Text>
</View>
</View>
<View style={[a.flex_row, a.align_center, a.w_full, a.gap_lg]}>
<IconCircle icon={News} size="lg" style={{width: 48, height: 48}} />
<View style={[a.flex_1, a.gap_xs]}>
<Text style={[a.font_bold, a.text_lg]}>
<Trans>Open</Trans>
</Text>
<Text
style={[t.atoms.text_contrast_medium, a.text_md, a.leading_snug]}>
<Trans>Never lose access to your followers or data.</Trans>
</Text>
</View>
</View>
<View style={[a.flex_row, a.align_center, a.w_full, a.gap_lg]}>
<IconCircle
icon={Trending}
size="lg"
style={{width: 48, height: 48}}
/>
<View style={[a.flex_1, a.gap_xs]}>
<Text style={[a.font_bold, a.text_lg]}>
<Trans>Flexible</Trans>
</Text>
<Text
style={[t.atoms.text_contrast_medium, a.text_md, a.leading_snug]}>
<Trans>Choose the algorithms that power your custom feeds.</Trans>
</Text>
</View>
</View>
</View>
<OnboardingControls.Portal>
<Button
disabled={saving}
key={state.activeStep} // remove focus state on nav
variant="gradient"
color="gradient_sky"
size="large"
label={_(msg`Complete onboarding and start using your account`)}
onPress={finishOnboarding}>
<ButtonText>
{saving ? <Trans>Finalizing</Trans> : <Trans>Let's go!</Trans>}
</ButtonText>
{saving && <ButtonIcon icon={Loader} position="right" />}
</Button>
</OnboardingControls.Portal>
</View>
)
}
+2
View File
@@ -13,6 +13,7 @@ import {StepAlgoFeeds} from '#/screens/Onboarding/StepAlgoFeeds'
import {StepTopicalFeeds} from '#/screens/Onboarding/StepTopicalFeeds'
import {StepFinished} from '#/screens/Onboarding/StepFinished'
import {StepModeration} from '#/screens/Onboarding/StepModeration'
import {StepProfile} from '#/screens/Onboarding/StepProfile'
export function Onboarding() {
const {_} = useLingui()
@@ -62,6 +63,7 @@ export function Onboarding() {
{state.activeStep === 'algoFeeds' && <StepAlgoFeeds />}
{state.activeStep === 'topicalFeeds' && <StepTopicalFeeds />}
{state.activeStep === 'moderation' && <StepModeration />}
{state.activeStep === 'profile' && <StepProfile />}
{state.activeStep === 'finished' && <StepFinished />}
</Layout>
</Context.Provider>
+9 -2
View File
@@ -12,6 +12,7 @@ export type OnboardingState = {
| 'algoFeeds'
| 'topicalFeeds'
| 'moderation'
| 'profile'
| 'finished'
activeStepIndex: number
@@ -154,8 +155,11 @@ export function reducer(
next.activeStep = 'moderation'
next.activeStepIndex = 6
} else if (s.activeStep === 'moderation') {
next.activeStep = 'finished'
next.activeStep = 'profile'
next.activeStepIndex = 7
} else if (s.activeStep === 'profile') {
next.activeStep = 'finished'
next.activeStepIndex = 8
}
break
}
@@ -175,9 +179,12 @@ export function reducer(
} else if (s.activeStep === 'moderation') {
next.activeStep = 'topicalFeeds'
next.activeStepIndex = 5
} else if (s.activeStep === 'finished') {
} else if (s.activeStep === 'profile') {
next.activeStep = 'moderation'
next.activeStepIndex = 6
} else if (s.activeStep === 'finished') {
next.activeStep = 'profile'
next.activeStepIndex = 7
}
break
}