From d7a228e96fa358703e6081af0d9c1220306fd7cf Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Fri, 5 Dec 2025 17:15:22 +0200 Subject: [PATCH] integrate existing flow into onboarding --- src/components/contacts/FindContactsFlow.tsx | 15 +++- .../contacts/screens/PhoneInput.tsx | 10 ++- .../contacts/screens/VerifyNumber.tsx | 6 +- .../contacts/screens/ViewMatches.tsx | 46 +++++++++-- src/components/contacts/state.ts | 17 +++- .../Onboarding/StepFindContacts/index.tsx | 42 ++++++++++ src/screens/Onboarding/index.tsx | 82 +++++++------------ 7 files changed, 149 insertions(+), 69 deletions(-) create mode 100644 src/screens/Onboarding/StepFindContacts/index.tsx diff --git a/src/components/contacts/FindContactsFlow.tsx b/src/components/contacts/FindContactsFlow.tsx index ecacf3f3f1..68f969f975 100644 --- a/src/components/contacts/FindContactsFlow.tsx +++ b/src/components/contacts/FindContactsFlow.tsx @@ -2,21 +2,23 @@ import {GetContacts} from './screens/GetContacts' import {PhoneInput} from './screens/PhoneInput' import {VerifyNumber} from './screens/VerifyNumber' import {ViewMatches} from './screens/ViewMatches' -import {type Action, type State} from './state' +import {type Action, FindContactsGoBackContext, type State} from './state' export function FindContactsFlow({ state, dispatch, + onBack, onCancel, context = 'Standalone', }: { state: State dispatch: React.Dispatch + onBack?: () => void onCancel: () => void context: 'Onboarding' | 'Standalone' }) { return ( - <> + {state.step === '1: phone input' && ( )} {state.step === '4: view matches' && ( - + )} - + ) } diff --git a/src/components/contacts/screens/PhoneInput.tsx b/src/components/contacts/screens/PhoneInput.tsx index b9124ac58e..55fd94adaa 100644 --- a/src/components/contacts/screens/PhoneInput.tsx +++ b/src/components/contacts/screens/PhoneInput.tsx @@ -26,7 +26,7 @@ import { getCountryCodeFromPastedNumber, processPhoneNumber, } from '../phone-number' -import {type Action, type State} from '../state' +import {type Action, type State, useOnPressBackButton} from '../state' export function PhoneInput({ state, @@ -103,10 +103,12 @@ export function PhoneInput({ const paddingBottom = Math.max(insets.bottom, tokens.space.xl) + const onPressBack = useOnPressBackButton() + return ( - + {showSkipButton ? ( diff --git a/src/components/contacts/screens/VerifyNumber.tsx b/src/components/contacts/screens/VerifyNumber.tsx index e765585f65..ed746ece97 100644 --- a/src/components/contacts/screens/VerifyNumber.tsx +++ b/src/components/contacts/screens/VerifyNumber.tsx @@ -19,7 +19,7 @@ import {Loader} from '#/components/Loader' import * as Toast from '#/components/Toast' import {Text} from '#/components/Typography' import {OTPInput} from '../components/OTPInput' -import {type Action, type State} from '../state' +import {type Action, type State, useOnPressBackButton} from '../state' export function VerifyNumber({ state, dispatch, @@ -121,10 +121,12 @@ export function VerifyNumber({ [state.phoneCountryCode], ) + const onPressBack = useOnPressBackButton() + return ( - + {showSkipButton ? ( + + )} ) } diff --git a/src/components/contacts/state.ts b/src/components/contacts/state.ts index 8e134db40a..3949f901e3 100644 --- a/src/components/contacts/state.ts +++ b/src/components/contacts/state.ts @@ -1,4 +1,5 @@ -import {useReducer} from 'react' +import {createContext, useContext, useReducer} from 'react' +import {type GestureResponderEvent} from 'react-native' import {type ExistingContact} from 'expo-contacts' import {type CountryCode} from '#/lib/international-telephone-codes' @@ -176,3 +177,17 @@ export function useFindContactsFlowState( ) { return useReducer(reducer, initialState) } + +export const FindContactsGoBackContext = createContext< + (() => void) | undefined +>(undefined) +export function useOnPressBackButton() { + const goBack = useContext(FindContactsGoBackContext) + if (!goBack) { + return undefined + } + return (evt: GestureResponderEvent) => { + evt.preventDefault() + goBack() + } +} diff --git a/src/screens/Onboarding/StepFindContacts/index.tsx b/src/screens/Onboarding/StepFindContacts/index.tsx new file mode 100644 index 0000000000..001fd6010b --- /dev/null +++ b/src/screens/Onboarding/StepFindContacts/index.tsx @@ -0,0 +1,42 @@ +import {useCallback} from 'react' +import {LayoutAnimationConfig} from 'react-native-reanimated' +import {SafeAreaView} from 'react-native-safe-area-context' + +import {FindContactsFlow} from '#/components/contacts/FindContactsFlow' +import {useFindContactsFlowState} from '#/components/contacts/state' +import {ScreenTransition} from '#/components/ScreenTransition' +import {useOnboardingInternalState} from '../state' + +export function StepFindContacts() { + const [fcfState, fcfDispatch] = useFindContactsFlowState() + const {dispatch} = useOnboardingInternalState() + + const onSkip = useCallback(() => { + dispatch({type: 'next'}) + }, [dispatch]) + + const canGoBack = fcfState.step === '2: verify number' + const onBack = useCallback(() => { + if (canGoBack) { + fcfDispatch({type: 'BACK'}) + } else { + dispatch({type: 'prev'}) + } + }, [dispatch, fcfDispatch, canGoBack]) + + return ( + + + + + + + + ) +} diff --git a/src/screens/Onboarding/index.tsx b/src/screens/Onboarding/index.tsx index 2e91ac2ad0..9513a18043 100644 --- a/src/screens/Onboarding/index.tsx +++ b/src/screens/Onboarding/index.tsx @@ -1,8 +1,8 @@ import {useMemo, useReducer} from 'react' -import {msg} from '@lingui/macro' -import {useLingui} from '@lingui/react' +import {View} from 'react-native' import * as bcp47Match from 'bcp-47-match' +import {useEnableKeyboardControllerScreen} from '#/lib/hooks/useEnableKeyboardController' import {useGate} from '#/lib/statsig/statsig' import {isNative} from '#/platform/detection' import {useLanguagePrefs} from '#/state/preferences' @@ -19,15 +19,17 @@ import { import {StepFinished} from '#/screens/Onboarding/StepFinished' import {StepInterests} from '#/screens/Onboarding/StepInterests' import {StepProfile} from '#/screens/Onboarding/StepProfile' +import {atoms as a, useTheme} from '#/alf' import {Portal} from '#/components/Portal' import {ScreenTransition} from '#/components/ScreenTransition' import {ENV} from '#/env' +import {StepFindContacts} from './StepFindContacts' import {StepSuggestedAccounts} from './StepSuggestedAccounts' import {StepSuggestedStarterpacks} from './StepSuggestedStarterpacks' export function Onboarding() { - const {_} = useLingui() const gate = useGate() + const t = useTheme() const {contentLanguages} = useLanguagePrefs() const probablySpeaksEnglish = useMemo(() => { @@ -52,61 +54,39 @@ export function Onboarding() { createInitialOnboardingState, ) - const interestsDisplayNames = useMemo(() => { - return { - news: _(msg`News`), - journalism: _(msg`Journalism`), - nature: _(msg`Nature`), - art: _(msg`Art`), - comics: _(msg`Comics`), - writers: _(msg`Writers`), - culture: _(msg`Culture`), - sports: _(msg`Sports`), - pets: _(msg`Pets`), - animals: _(msg`Animals`), - books: _(msg`Books`), - education: _(msg`Education`), - climate: _(msg`Climate`), - science: _(msg`Science`), - politics: _(msg`Politics`), - fitness: _(msg`Fitness`), - tech: _(msg`Tech`), - dev: _(msg`Software Dev`), - comedy: _(msg`Comedy`), - gaming: _(msg`Video Games`), - food: _(msg`Food`), - cooking: _(msg`Cooking`), - } - }, [_]) + useEnableKeyboardControllerScreen(true) return ( - - - ({state, dispatch, interestsDisplayNames}), - [state, dispatch, interestsDisplayNames], - )}> - + + + + ({state, dispatch}), [state, dispatch])}> - {state.activeStep === 'profile' && } - {state.activeStep === 'interests' && } - {state.activeStep === 'suggested-accounts' && ( - + direction={state.stepTransitionDirection} + style={a.flex_1}> + {state.activeStep === 'find-contacts' ? ( + + ) : ( + + {state.activeStep === 'profile' && } + {state.activeStep === 'interests' && } + {state.activeStep === 'suggested-accounts' && ( + + )} + {state.activeStep === 'suggested-starterpacks' && ( + + )} + {state.activeStep === 'finished' && } + )} - {state.activeStep === 'suggested-starterpacks' && ( - - )} - {state.activeStep === 'find-contacts' && null} - {state.activeStep === 'finished' && } - - - - + + + + ) }