diff options
Diffstat (limited to 'src/view')
-rw-r--r-- | src/view/com/auth/create/Step1.tsx | 4 | ||||
-rw-r--r-- | src/view/com/auth/create/Step2.tsx | 9 | ||||
-rw-r--r-- | src/view/com/auth/create/Step3.tsx | 3 | ||||
-rw-r--r-- | src/view/com/auth/onboarding/Onboarding.tsx | 66 | ||||
-rw-r--r-- | src/view/com/auth/onboarding/Welcome.tsx | 87 | ||||
-rw-r--r-- | src/view/com/modals/Modal.tsx | 4 | ||||
-rw-r--r-- | src/view/com/modals/Modal.web.tsx | 3 | ||||
-rw-r--r-- | src/view/com/modals/OnboardingModal.tsx | 8 |
8 files changed, 184 insertions, 0 deletions
diff --git a/src/view/com/auth/create/Step1.tsx b/src/view/com/auth/create/Step1.tsx index 57747f070..5038c8819 100644 --- a/src/view/com/auth/create/Step1.tsx +++ b/src/view/com/auth/create/Step1.tsx @@ -16,6 +16,10 @@ import {ErrorMessage} from 'view/com/util/error/ErrorMessage' import {LOCAL_DEV_SERVICE, STAGING_SERVICE, PROD_SERVICE} from 'state/index' import {LOGIN_INCLUDE_DEV_SERVERS} from 'lib/build-flags' +/** STEP 1: Your hosting provider + * @field Bluesky (default) + * @field Other (staging, local dev, your own PDS, etc.) + */ export const Step1 = observer(({model}: {model: CreateAccountModel}) => { const pal = usePalette('default') const [isDefaultSelected, setIsDefaultSelected] = React.useState(true) diff --git a/src/view/com/auth/create/Step2.tsx b/src/view/com/auth/create/Step2.tsx index 2865191c4..52a06f031 100644 --- a/src/view/com/auth/create/Step2.tsx +++ b/src/view/com/auth/create/Step2.tsx @@ -12,6 +12,15 @@ import {Policies} from './Policies' import {ErrorMessage} from 'view/com/util/error/ErrorMessage' import {useStores} from 'state/index' +/** STEP 2: Your account + * @field Invite code or waitlist + * @field Email address + * @field Email address + * @field Email address + * @field Password + * @field Birth date + * @readonly Terms of service & privacy policy + */ export const Step2 = observer(({model}: {model: CreateAccountModel}) => { const pal = usePalette('default') const store = useStores() diff --git a/src/view/com/auth/create/Step3.tsx b/src/view/com/auth/create/Step3.tsx index bf26231a0..f35777d27 100644 --- a/src/view/com/auth/create/Step3.tsx +++ b/src/view/com/auth/create/Step3.tsx @@ -10,6 +10,9 @@ import {createFullHandle} from 'lib/strings/handles' import {usePalette} from 'lib/hooks/usePalette' import {ErrorMessage} from 'view/com/util/error/ErrorMessage' +/** STEP 3: Your user handle + * @field User handle + */ export const Step3 = observer(({model}: {model: CreateAccountModel}) => { const pal = usePalette('default') return ( diff --git a/src/view/com/auth/onboarding/Onboarding.tsx b/src/view/com/auth/onboarding/Onboarding.tsx new file mode 100644 index 000000000..28e4419d7 --- /dev/null +++ b/src/view/com/auth/onboarding/Onboarding.tsx @@ -0,0 +1,66 @@ +import React from 'react' +import {StyleSheet, View} from 'react-native' +import {usePalette} from 'lib/hooks/usePalette' +import {Welcome} from './Welcome' +import {useStores} from 'state/index' +import {track} from 'lib/analytics/analytics' + +enum OnboardingStep { + WELCOME = 'WELCOME', + // SELECT_INTERESTS = 'SELECT_INTERESTS', + COMPLETE = 'COMPLETE', +} +type OnboardingState = { + currentStep: OnboardingStep +} +type Action = {type: 'NEXT_STEP'} +const initialState: OnboardingState = { + currentStep: OnboardingStep.WELCOME, +} +const reducer = (state: OnboardingState, action: Action): OnboardingState => { + switch (action.type) { + case 'NEXT_STEP': + switch (state.currentStep) { + case OnboardingStep.WELCOME: + track('Onboarding:Begin') + return {...state, currentStep: OnboardingStep.COMPLETE} + case OnboardingStep.COMPLETE: + track('Onboarding:Complete') + return state + default: + return state + } + default: + return state + } +} + +export const Onboarding = () => { + const pal = usePalette('default') + const rootStore = useStores() + const [state, dispatch] = React.useReducer(reducer, initialState) + const next = React.useCallback( + () => dispatch({type: 'NEXT_STEP'}), + [dispatch], + ) + + React.useEffect(() => { + if (state.currentStep === OnboardingStep.COMPLETE) { + // navigate to home + rootStore.shell.closeModal() + } + }, [state.currentStep, rootStore.shell]) + + return ( + <View style={[pal.view, styles.container]}> + {state.currentStep === OnboardingStep.WELCOME && <Welcome next={next} />} + </View> + ) +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + paddingHorizontal: 20, + }, +}) diff --git a/src/view/com/auth/onboarding/Welcome.tsx b/src/view/com/auth/onboarding/Welcome.tsx new file mode 100644 index 000000000..e7c068ea0 --- /dev/null +++ b/src/view/com/auth/onboarding/Welcome.tsx @@ -0,0 +1,87 @@ +import React from 'react' +import {StyleSheet, View} from 'react-native' +import {Text} from 'view/com/util/text/Text' +import {s} from 'lib/styles' +import {usePalette} from 'lib/hooks/usePalette' +import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' +import {Button} from 'view/com/util/forms/Button' + +export const Welcome = ({next}: {next: () => void}) => { + const pal = usePalette('default') + return ( + <View style={[styles.container]}> + <View> + <Text style={[pal.text, styles.title]}>Welcome to </Text> + <Text style={[pal.text, pal.link, styles.title]}>Bluesky</Text> + + <View style={styles.spacer} /> + + <View style={[styles.row]}> + <FontAwesomeIcon icon={'globe'} size={36} color={pal.colors.link} /> + <View style={[styles.rowText]}> + <Text type="lg-bold" style={[pal.text]}> + Bluesky is public. + </Text> + <Text type="lg-thin" style={[pal.text, s.pt2]}> + Your posts, likes, and blocks are public. Mutes are private. + </Text> + </View> + </View> + <View style={[styles.row]}> + <FontAwesomeIcon icon={'at'} size={36} color={pal.colors.link} /> + <View style={[styles.rowText]}> + <Text type="lg-bold" style={[pal.text]}> + Bluesky is open. + </Text> + <Text type="lg-thin" style={[pal.text, s.pt2]}> + Never lose access to your followers and data. + </Text> + </View> + </View> + <View style={[styles.row]}> + <FontAwesomeIcon icon={'gear'} size={36} color={pal.colors.link} /> + <View style={[styles.rowText]}> + <Text type="lg-bold" style={[pal.text]}> + Bluesky is flexible. + </Text> + <Text type="lg-thin" style={[pal.text, s.pt2]}> + Choose the algorithms that power your experience with custom + feeds. + </Text> + </View> + </View> + </View> + + <Button onPress={next} label="Continue" labelStyle={styles.buttonText} /> + </View> + ) +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + marginVertical: 60, + justifyContent: 'space-between', + }, + title: { + fontSize: 48, + fontWeight: '800', + }, + row: { + flexDirection: 'row', + columnGap: 20, + alignItems: 'center', + marginVertical: 20, + }, + rowText: { + flex: 1, + }, + spacer: { + height: 20, + }, + buttonText: { + textAlign: 'center', + fontSize: 18, + marginVertical: 4, + }, +}) diff --git a/src/view/com/modals/Modal.tsx b/src/view/com/modals/Modal.tsx index ad8794e89..525df7ba1 100644 --- a/src/view/com/modals/Modal.tsx +++ b/src/view/com/modals/Modal.tsx @@ -27,6 +27,7 @@ import * as ContentFilteringSettingsModal from './ContentFilteringSettings' import * as ContentLanguagesSettingsModal from './lang-settings/ContentLanguagesSettings' import * as PostLanguagesSettingsModal from './lang-settings/PostLanguagesSettings' import * as PreferencesHomeFeed from './PreferencesHomeFeed' +import * as OnboardingModal from './OnboardingModal' const DEFAULT_SNAPPOINTS = ['90%'] @@ -117,6 +118,9 @@ export const ModalsContainer = observer(function ModalsContainer() { } else if (activeModal?.name === 'preferences-home-feed') { snapPoints = PreferencesHomeFeed.snapPoints element = <PreferencesHomeFeed.Component /> + } else if (activeModal?.name === 'onboarding') { + snapPoints = OnboardingModal.snapPoints + element = <OnboardingModal.Component /> } else { return null } diff --git a/src/view/com/modals/Modal.web.tsx b/src/view/com/modals/Modal.web.tsx index 20312fe6b..39cdbd868 100644 --- a/src/view/com/modals/Modal.web.tsx +++ b/src/view/com/modals/Modal.web.tsx @@ -26,6 +26,7 @@ import * as AddAppPassword from './AddAppPasswords' import * as ContentFilteringSettingsModal from './ContentFilteringSettings' import * as ContentLanguagesSettingsModal from './lang-settings/ContentLanguagesSettings' import * as PostLanguagesSettingsModal from './lang-settings/PostLanguagesSettings' +import * as OnboardingModal from './OnboardingModal' import * as PreferencesHomeFeed from './PreferencesHomeFeed' @@ -107,6 +108,8 @@ function Modal({modal}: {modal: ModalIface}) { element = <EditImageModal.Component {...modal} /> } else if (modal.name === 'preferences-home-feed') { element = <PreferencesHomeFeed.Component /> + } else if (modal.name === 'onboarding') { + element = <OnboardingModal.Component /> } else { return null } diff --git a/src/view/com/modals/OnboardingModal.tsx b/src/view/com/modals/OnboardingModal.tsx new file mode 100644 index 000000000..c70f4fd62 --- /dev/null +++ b/src/view/com/modals/OnboardingModal.tsx @@ -0,0 +1,8 @@ +import React from 'react' +import {Onboarding} from '../auth/onboarding/Onboarding' + +export const snapPoints = ['90%'] + +export function Component() { + return <Onboarding /> +} |