diff options
Diffstat (limited to 'src/screens/Signup/StepHandle.tsx')
-rw-r--r-- | src/screens/Signup/StepHandle.tsx | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/screens/Signup/StepHandle.tsx b/src/screens/Signup/StepHandle.tsx new file mode 100644 index 000000000..e0a79e8fb --- /dev/null +++ b/src/screens/Signup/StepHandle.tsx @@ -0,0 +1,134 @@ +import React from 'react' +import {View} from 'react-native' +import {useFocusEffect} from '@react-navigation/native' +import {useLingui} from '@lingui/react' +import {msg, Trans} from '@lingui/macro' +import {TimesLarge_Stroke2_Corner0_Rounded as Times} from '#/components/icons/Times' +import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check' +import {At_Stroke2_Corner0_Rounded as At} from '#/components/icons/At' +import * as TextField from '#/components/forms/TextField' +import {useSignupContext} from '#/screens/Signup/state' +import {Text} from '#/components/Typography' +import {atoms as a, useTheme} from '#/alf' +import { + createFullHandle, + IsValidHandle, + validateHandle, +} from 'lib/strings/handles' +import {ScreenTransition} from '#/screens/Login/ScreenTransition' + +export function StepHandle() { + const {_} = useLingui() + const t = useTheme() + const {state, dispatch} = useSignupContext() + + const [validCheck, setValidCheck] = React.useState<IsValidHandle>({ + handleChars: false, + hyphenStartOrEnd: false, + frontLength: false, + totalLength: true, + overall: false, + }) + + useFocusEffect( + React.useCallback(() => { + console.log('run') + setValidCheck(validateHandle(state.handle, state.userDomain)) + }, [state.handle, state.userDomain]), + ) + + const onHandleChange = React.useCallback( + (value: string) => { + if (state.error) { + dispatch({type: 'setError', value: ''}) + } + + dispatch({ + type: 'setHandle', + value, + }) + }, + [dispatch, state.error], + ) + + return ( + <ScreenTransition> + <View style={[a.gap_lg]}> + <View> + <TextField.Root> + <TextField.Icon icon={At} /> + <TextField.Input + onChangeText={onHandleChange} + label={_(msg`Input your user handle`)} + defaultValue={state.handle} + autoCapitalize="none" + autoCorrect={false} + autoFocus + autoComplete="off" + /> + </TextField.Root> + </View> + <Text style={[a.text_md]}> + <Trans>Your full handle will be</Trans>{' '} + <Text style={[a.text_md, a.font_bold]}> + @{createFullHandle(state.handle, state.userDomain)} + </Text> + </Text> + + <View + style={[ + a.w_full, + a.rounded_sm, + a.border, + a.p_md, + a.gap_sm, + t.atoms.border_contrast_low, + ]}> + {state.error ? ( + <View style={[a.w_full, a.flex_row, a.align_center, a.gap_sm]}> + <IsValidIcon valid={false} /> + <Text style={[a.text_md, a.flex_1]}>{state.error}</Text> + </View> + ) : undefined} + {validCheck.hyphenStartOrEnd ? ( + <View style={[a.w_full, a.flex_row, a.align_center, a.gap_sm]}> + <IsValidIcon valid={validCheck.handleChars} /> + <Text style={[a.text_md, a.flex_1]}> + <Trans>Only contains letters, numbers, and hyphens</Trans> + </Text> + </View> + ) : ( + <View style={[a.w_full, a.flex_row, a.align_center, a.gap_sm]}> + <IsValidIcon valid={validCheck.hyphenStartOrEnd} /> + <Text style={[a.text_md, a.flex_1]}> + <Trans>Doesn't begin or end with a hyphen</Trans> + </Text> + </View> + )} + <View style={[a.w_full, a.flex_row, a.align_center, a.gap_sm]}> + <IsValidIcon + valid={validCheck.frontLength && validCheck.totalLength} + /> + {!validCheck.totalLength ? ( + <Text style={[a.text_md, a.flex_1]}> + <Trans>No longer than 253 characters</Trans> + </Text> + ) : ( + <Text style={[a.text_md, a.flex_1]}> + <Trans>At least 3 characters</Trans> + </Text> + )} + </View> + </View> + </View> + </ScreenTransition> + ) +} + +function IsValidIcon({valid}: {valid: boolean}) { + const t = useTheme() + if (!valid) { + return <Times size="md" style={{color: t.palette.negative_500}} /> + } + return <Check size="md" style={{color: t.palette.positive_700}} /> +} |