add intro step
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import {View} from 'react-native'
|
||||
import * as Contacts from 'expo-contacts'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useQuery} from '@tanstack/react-query'
|
||||
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Admonition} from '#/components/Admonition'
|
||||
import {Button, ButtonText} from '#/components/Button'
|
||||
import {ContactsHeroImage} from '#/components/contacts/components/HeroImage'
|
||||
import {InlineLinkText} from '#/components/Link'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {OnboardingControls} from '../Layout'
|
||||
import {useOnboardingInternalState} from '../state'
|
||||
|
||||
export function StepFindContactsIntro() {
|
||||
const {_} = useLingui()
|
||||
const t = useTheme()
|
||||
const {dispatch} = useOnboardingInternalState()
|
||||
|
||||
const {data: isAvailable, isSuccess} = useQuery({
|
||||
queryKey: ['contacts-available'],
|
||||
queryFn: async () => await Contacts.isAvailableAsync(),
|
||||
})
|
||||
|
||||
return (
|
||||
<View style={[a.w_full, a.gap_lg]}>
|
||||
<ContactsHeroImage />
|
||||
<Text style={[a.text_3xl, a.leading_snug, a.font_bold]}>
|
||||
<Trans>Bluesky is more fun with Friends</Trans>
|
||||
</Text>
|
||||
<Text style={[a.text_md, a.leading_snug, t.atoms.text_contrast_medium]}>
|
||||
<Trans>
|
||||
Find your friends on Bluesky by verifying your phone number and
|
||||
matching with your contacts. We protect your information and you
|
||||
control what happens next.{' '}
|
||||
<InlineLinkText
|
||||
to="#"
|
||||
label={_(msg`Learn more`)}
|
||||
style={[a.text_md, a.leading_snug]}>
|
||||
TODO: Learn more
|
||||
</InlineLinkText>
|
||||
</Trans>
|
||||
</Text>
|
||||
{!isAvailable && isSuccess && (
|
||||
<Admonition type="error">
|
||||
<Trans>
|
||||
Contact sync is not available on this device, as the app is unable
|
||||
to access your contacts.
|
||||
</Trans>
|
||||
</Admonition>
|
||||
)}
|
||||
|
||||
<OnboardingControls.Portal>
|
||||
<View style={[a.gap_md]}>
|
||||
<Button
|
||||
onPress={() => dispatch({type: 'next'})}
|
||||
label={_(msg`Upload contacts`)}
|
||||
size="large"
|
||||
color="primary">
|
||||
<ButtonText>
|
||||
<Trans>Upload contacts</Trans>
|
||||
</ButtonText>
|
||||
</Button>
|
||||
<Button
|
||||
onPress={() => dispatch({type: 'skip-contacts'})}
|
||||
label={_(msg`Skip`)}
|
||||
size="large"
|
||||
color="secondary">
|
||||
<ButtonText>
|
||||
<Trans>Skip</Trans>
|
||||
</ButtonText>
|
||||
</Button>
|
||||
</View>
|
||||
</OnboardingControls.Portal>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import {Portal} from '#/components/Portal'
|
||||
import {ScreenTransition} from '#/components/ScreenTransition'
|
||||
import {ENV} from '#/env'
|
||||
import {StepFindContacts} from './StepFindContacts'
|
||||
import {StepFindContactsIntro} from './StepFindContactsIntro'
|
||||
import {StepSuggestedAccounts} from './StepSuggestedAccounts'
|
||||
import {StepSuggestedStarterpacks} from './StepSuggestedStarterpacks'
|
||||
|
||||
@@ -67,6 +68,7 @@ export function Onboarding() {
|
||||
key={state.activeStep}
|
||||
direction={state.stepTransitionDirection}
|
||||
style={a.flex_1}>
|
||||
{/* FindContactsFlow cannot be nested in Layout */}
|
||||
{state.activeStep === 'find-contacts' ? (
|
||||
<StepFindContacts />
|
||||
) : (
|
||||
@@ -79,6 +81,9 @@ export function Onboarding() {
|
||||
{state.activeStep === 'suggested-starterpacks' && (
|
||||
<StepSuggestedStarterpacks />
|
||||
)}
|
||||
{state.activeStep === 'find-contacts-intro' && (
|
||||
<StepFindContactsIntro />
|
||||
)}
|
||||
{state.activeStep === 'finished' && <StepFinished />}
|
||||
</Layout>
|
||||
)}
|
||||
|
||||
@@ -11,6 +11,7 @@ type OnboardingScreen =
|
||||
| 'interests'
|
||||
| 'suggested-accounts'
|
||||
| 'suggested-starterpacks'
|
||||
| 'find-contacts-intro'
|
||||
| 'find-contacts'
|
||||
| 'finished'
|
||||
|
||||
@@ -47,6 +48,9 @@ export type OnboardingAction =
|
||||
| {
|
||||
type: 'prev'
|
||||
}
|
||||
| {
|
||||
type: 'skip-contacts'
|
||||
}
|
||||
| {
|
||||
type: 'finish'
|
||||
}
|
||||
@@ -82,6 +86,7 @@ export function createInitialOnboardingState(
|
||||
interests: true,
|
||||
'suggested-accounts': true,
|
||||
'suggested-starterpacks': starterPacksStepEnabled,
|
||||
'find-contacts-intro': findContactsStepEnabled,
|
||||
'find-contacts': findContactsStepEnabled,
|
||||
finished: true,
|
||||
}
|
||||
@@ -130,11 +135,24 @@ export function reducer(
|
||||
const prevIndex = stepOrder.indexOf(next.activeStep) - 1
|
||||
const prevStep = stepOrder[prevIndex]
|
||||
if (prevStep) {
|
||||
next.activeStep = prevStep
|
||||
// override back behaviour for the find contacts screen
|
||||
// so returning to the flow takes you to the intro screen
|
||||
if (prevStep === 'find-contacts') {
|
||||
next.activeStep = 'find-contacts-intro'
|
||||
} else {
|
||||
next.activeStep = prevStep
|
||||
}
|
||||
}
|
||||
next.stepTransitionDirection = 'Backward'
|
||||
break
|
||||
}
|
||||
case 'skip-contacts': {
|
||||
const nextIndex = stepOrder.indexOf('find-contacts') + 1
|
||||
const nextStep = stepOrder[nextIndex] ?? 'finished'
|
||||
next.activeStep = nextStep
|
||||
next.stepTransitionDirection = 'Forward'
|
||||
break
|
||||
}
|
||||
case 'finish': {
|
||||
next = createInitialOnboardingState({
|
||||
starterPacksStepEnabled: s.screens['suggested-starterpacks'],
|
||||
@@ -187,6 +205,7 @@ function getStepOrder(s: OnboardingState): OnboardingScreen[] {
|
||||
s.screens.interests && ('interests' as const),
|
||||
s.screens['suggested-accounts'] && ('suggested-accounts' as const),
|
||||
s.screens['suggested-starterpacks'] && ('suggested-starterpacks' as const),
|
||||
s.screens['find-contacts-intro'] && ('find-contacts-intro' as const),
|
||||
s.screens['find-contacts'] && ('find-contacts' as const),
|
||||
s.screens.finished && ('finished' as const),
|
||||
].filter(x => !!x)
|
||||
|
||||
Reference in New Issue
Block a user