diff --git a/src/lib/statsig/gates.ts b/src/lib/statsig/gates.ts
index ef6dc1d4df..7fe8320109 100644
--- a/src/lib/statsig/gates.ts
+++ b/src/lib/statsig/gates.ts
@@ -7,6 +7,7 @@ export type Gate =
| 'explore_show_suggested_feeds'
| 'old_postonboarding'
| 'onboarding_add_video_feed'
+ | 'onboarding_suggested_accounts'
| 'post_follow_profile_suggested_accounts'
| 'post_threads_v2_unspecced'
| 'remove_show_latest_button'
diff --git a/src/screens/Onboarding/Layout.tsx b/src/screens/Onboarding/Layout.tsx
index 16c37358ff..15c300fed8 100644
--- a/src/screens/Onboarding/Layout.tsx
+++ b/src/screens/Onboarding/Layout.tsx
@@ -11,7 +11,7 @@ import {
atoms as a,
flatten,
native,
- TextStyleProp,
+ type TextStyleProp,
useBreakpoints,
useTheme,
web,
diff --git a/src/screens/Onboarding/StepSuggestedAccounts/index.tsx b/src/screens/Onboarding/StepSuggestedAccounts/index.tsx
new file mode 100644
index 0000000000..bf7b71c5b3
--- /dev/null
+++ b/src/screens/Onboarding/StepSuggestedAccounts/index.tsx
@@ -0,0 +1,146 @@
+import {useCallback, useContext, useState} from 'react'
+import {View} from 'react-native'
+import {msg, Trans} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+
+import {logger} from '#/logger'
+import {useOnboardingDispatch} from '#/state/shell'
+import {
+ DescriptionText,
+ OnboardingControls,
+ TitleText,
+} from '#/screens/Onboarding/Layout'
+import {Context} from '#/screens/Onboarding/state'
+import {atoms as a, useBreakpoints, useTheme} from '#/alf'
+import {Button, ButtonIcon, ButtonText} from '#/components/Button'
+import {IconCircle} from '#/components/IconCircle'
+import {ArrowRotateCounterClockwise_Stroke2_Corner0_Rounded as ArrowRotateCounterClockwise} from '#/components/icons/ArrowRotateCounterClockwise'
+import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '#/components/icons/Chevron'
+import {EmojiSad_Stroke2_Corner0_Rounded as EmojiSad} from '#/components/icons/Emoji'
+import {Hashtag_Stroke2_Corner0_Rounded as Hashtag} from '#/components/icons/Hashtag'
+import {Loader} from '#/components/Loader'
+
+export function StepSuggestedAccounts() {
+ const {_} = useLingui()
+ const t = useTheme()
+ const {gtMobile} = useBreakpoints()
+
+ const {dispatch} = useContext(Context)
+ const [saving, setSaving] = useState(false)
+ const onboardDispatch = useOnboardingDispatch()
+
+ const saveInterests = useCallback(async () => {
+ setSaving(true)
+
+ try {
+ setSaving(false)
+ dispatch({type: 'next'})
+ } catch (e: any) {
+ logger.info(`onboading: error saving interests`)
+ logger.error(e)
+ }
+ }, [setSaving, dispatch])
+
+ const skipOnboarding = useCallback(() => {
+ onboardDispatch({type: 'finish'})
+ dispatch({type: 'finish'})
+ }, [onboardDispatch, dispatch])
+
+ const isError = false
+
+ const title = isError ? (
+ Oh no! Something went wrong.
+ ) : (
+ Suggested Accounts
+ )
+ const description = isError ? (
+
+ We weren't able to connect. Please try again to continue setting up your
+ account. If it continues to fail, you can skip this flow.
+
+ ) : (
+ We'll use this to help customize your experience.
+ )
+
+ return (
+
+
+
+ {title}
+ {description}
+
+
+
+
+ {isError ? (
+
+
+
+
+ ) : (
+
+
+
+
+ )}
+
+
+ )
+}
diff --git a/src/screens/Onboarding/index.tsx b/src/screens/Onboarding/index.tsx
index a5c423ca19..b878438f17 100644
--- a/src/screens/Onboarding/index.tsx
+++ b/src/screens/Onboarding/index.tsx
@@ -1,21 +1,29 @@
-import React from 'react'
+import {useMemo, useReducer} from 'react'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
+import {useGate} from '#/lib/statsig/statsig'
import {Layout, OnboardingControls} from '#/screens/Onboarding/Layout'
import {Context, initialState, reducer} from '#/screens/Onboarding/state'
import {StepFinished} from '#/screens/Onboarding/StepFinished'
import {StepInterests} from '#/screens/Onboarding/StepInterests'
import {StepProfile} from '#/screens/Onboarding/StepProfile'
import {Portal} from '#/components/Portal'
+import {StepSuggestedAccounts} from './StepSuggestedAccounts'
export function Onboarding() {
const {_} = useLingui()
- const [state, dispatch] = React.useReducer(reducer, {
+ const gate = useGate()
+ const showSuggestedAccounts = gate('onboarding_suggested_accounts')
+ const [state, dispatch] = useReducer(reducer, {
...initialState,
+ totalSteps: showSuggestedAccounts ? 4 : 3,
+ experiments: {
+ onboarding_suggested_accounts: showSuggestedAccounts,
+ },
})
- const interestsDisplayNames = React.useMemo(() => {
+ const interestsDisplayNames = useMemo(() => {
return {
news: _(msg`News`),
journalism: _(msg`Journalism`),
@@ -46,13 +54,16 @@ export function Onboarding() {
({state, dispatch, interestsDisplayNames}),
[state, dispatch, interestsDisplayNames],
)}>
{state.activeStep === 'profile' && }
{state.activeStep === 'interests' && }
+ {state.activeStep === 'suggested-accounts' && (
+
+ )}
{state.activeStep === 'finished' && }
diff --git a/src/screens/Onboarding/state.ts b/src/screens/Onboarding/state.ts
index cbb466245a..42732b8725 100644
--- a/src/screens/Onboarding/state.ts
+++ b/src/screens/Onboarding/state.ts
@@ -11,7 +11,7 @@ import {
export type OnboardingState = {
hasPrev: boolean
totalSteps: number
- activeStep: 'profile' | 'interests' | 'finished'
+ activeStep: 'profile' | 'interests' | 'suggested-accounts' | 'finished'
activeStepIndex: number
interestsStepResults: {
@@ -34,6 +34,10 @@ export type OnboardingState = {
backgroundColor: AvatarColor
}
}
+
+ experiments?: {
+ onboarding_suggested_accounts?: boolean
+ }
}
export type OnboardingAction =
@@ -160,22 +164,49 @@ export function reducer(
switch (a.type) {
case 'next': {
- if (s.activeStep === 'profile') {
- next.activeStep = 'interests'
- next.activeStepIndex = 2
- } else if (s.activeStep === 'interests') {
- next.activeStep = 'finished'
- next.activeStepIndex = 3
+ if (s.experiments?.onboarding_suggested_accounts) {
+ if (s.activeStep === 'profile') {
+ next.activeStep = 'interests'
+ next.activeStepIndex = 2
+ } else if (s.activeStep === 'interests') {
+ next.activeStep = 'suggested-accounts'
+ next.activeStepIndex = 3
+ }
+ if (s.activeStep === 'suggested-accounts') {
+ next.activeStep = 'finished'
+ next.activeStepIndex = 4
+ }
+ } else {
+ if (s.activeStep === 'profile') {
+ next.activeStep = 'interests'
+ next.activeStepIndex = 2
+ } else if (s.activeStep === 'interests') {
+ next.activeStep = 'finished'
+ next.activeStepIndex = 3
+ }
}
break
}
case 'prev': {
- if (s.activeStep === 'interests') {
- next.activeStep = 'profile'
- next.activeStepIndex = 1
- } else if (s.activeStep === 'finished') {
- next.activeStep = 'interests'
- next.activeStepIndex = 2
+ if (s.experiments?.onboarding_suggested_accounts) {
+ if (s.activeStep === 'interests') {
+ next.activeStep = 'profile'
+ next.activeStepIndex = 1
+ } else if (s.activeStep === 'suggested-accounts') {
+ next.activeStep = 'interests'
+ next.activeStepIndex = 2
+ } else if (s.activeStep === 'finished') {
+ next.activeStep = 'suggested-accounts'
+ next.activeStepIndex = 3
+ }
+ } else {
+ if (s.activeStep === 'interests') {
+ next.activeStep = 'profile'
+ next.activeStepIndex = 1
+ } else if (s.activeStep === 'finished') {
+ next.activeStep = 'interests'
+ next.activeStepIndex = 2
+ }
}
break
}