Fix lint, tsc; delete dead code

This commit is contained in:
Paul Frazee 2023-03-14 13:13:46 -05:00
parent c73d1e80b1
commit 1b7292e1db
3 changed files with 6 additions and 593 deletions

View file

@ -1,584 +0,0 @@
import React from 'react'
import {
ActivityIndicator,
Keyboard,
KeyboardAvoidingView,
ScrollView,
StyleSheet,
TextInput,
TouchableOpacity,
View,
} from 'react-native'
import {
FontAwesomeIcon,
FontAwesomeIconStyle,
} from '@fortawesome/react-native-fontawesome'
import {ComAtprotoAccountCreate} from '@atproto/api'
import * as EmailValidator from 'email-validator'
import {sha256} from 'js-sha256'
import {useAnalytics} from 'lib/analytics'
import {LogoTextHero} from '../Logo'
import {Picker} from '../../util/Picker'
import {TextLink} from '../../util/Link'
import {Text} from '../../util/text/Text'
import {s, colors} from 'lib/styles'
import {makeValidHandle, createFullHandle} from 'lib/strings/handles'
import {toNiceDomain} from 'lib/strings/url-helpers'
import {useStores, DEFAULT_SERVICE} from 'state/index'
import {ServiceDescription} from 'state/models/session'
import {usePalette} from 'lib/hooks/usePalette'
import {useTheme} from 'lib/ThemeContext'
import {cleanError} from 'lib/strings/errors'
export const CreateAccount = ({onPressBack}: {onPressBack: () => void}) => {
const {track, screen, identify} = useAnalytics()
const pal = usePalette('default')
const theme = useTheme()
const store = useStores()
const [isProcessing, setIsProcessing] = React.useState<boolean>(false)
const [serviceUrl, setServiceUrl] = React.useState<string>(DEFAULT_SERVICE)
const [error, setError] = React.useState<string>('')
const [retryDescribeTrigger, setRetryDescribeTrigger] = React.useState<any>(
{},
)
const [serviceDescription, setServiceDescription] = React.useState<
ServiceDescription | undefined
>(undefined)
const [userDomain, setUserDomain] = React.useState<string>('')
const [inviteCode, setInviteCode] = React.useState<string>('')
const [email, setEmail] = React.useState<string>('')
const [password, setPassword] = React.useState<string>('')
const [handle, setHandle] = React.useState<string>('')
const [is13, setIs13] = React.useState<boolean>(false)
React.useEffect(() => {
screen('CreateAccount')
}, [screen])
React.useEffect(() => {
let aborted = false
setError('')
setServiceDescription(undefined)
store.session.describeService(serviceUrl).then(
desc => {
if (aborted) {
return
}
setServiceDescription(desc)
setUserDomain(desc.availableUserDomains[0])
},
err => {
if (aborted) {
return
}
store.log.warn(
`Failed to fetch service description for ${serviceUrl}`,
err,
)
setError(
'Unable to contact your service. Please check your Internet connection.',
)
},
)
return () => {
aborted = true
}
}, [serviceUrl, store.session, store.log, retryDescribeTrigger])
const onPressRetryConnect = React.useCallback(
() => setRetryDescribeTrigger({}),
[setRetryDescribeTrigger],
)
const onPressSelectService = React.useCallback(() => {
store.shell.openModal({
name: 'server-input',
initialService: serviceUrl,
onSelect: setServiceUrl,
})
Keyboard.dismiss()
}, [store, serviceUrl])
const onBlurInviteCode = React.useCallback(() => {
setInviteCode(inviteCode.trim())
}, [setInviteCode, inviteCode])
const onPressNext = React.useCallback(async () => {
if (!email) {
return setError('Please enter your email.')
}
if (!EmailValidator.validate(email)) {
return setError('Your email appears to be invalid.')
}
if (!password) {
return setError('Please choose your password.')
}
if (!handle) {
return setError('Please choose your username.')
}
setError('')
setIsProcessing(true)
try {
await store.session.createAccount({
service: serviceUrl,
email,
handle: createFullHandle(handle, userDomain),
password,
inviteCode,
})
const email_hashed = sha256(email)
identify(email_hashed, {email_hashed})
track('Create Account')
} catch (e: any) {
let errMsg = e.toString()
if (e instanceof ComAtprotoAccountCreate.InvalidInviteCodeError) {
errMsg =
'Invite code not accepted. Check that you input it correctly and try again.'
}
store.log.error('Failed to create account', e)
setIsProcessing(false)
setError(cleanError(errMsg))
}
}, [
serviceUrl,
userDomain,
inviteCode,
email,
password,
handle,
setError,
setIsProcessing,
store,
track,
identify,
])
const isReady = !!email && !!password && !!handle && is13
return (
<ScrollView testID="createAccount" style={pal.view}>
<KeyboardAvoidingView behavior="padding">
<LogoTextHero />
{error ? (
<View style={[styles.error, styles.errorFloating]}>
<View style={[styles.errorIcon]}>
<FontAwesomeIcon icon="exclamation" style={s.white} size={10} />
</View>
<View style={s.flex1}>
<Text style={[s.white, s.bold]}>{error}</Text>
</View>
</View>
) : undefined}
<View style={styles.groupLabel}>
<Text type="sm-bold" style={pal.text}>
Service provider
</Text>
</View>
<View style={[pal.borderDark, styles.group]}>
<View
style={[pal.borderDark, styles.groupContent, styles.noTopBorder]}>
<FontAwesomeIcon
icon="globe"
style={[pal.textLight, styles.groupContentIcon]}
/>
<TouchableOpacity
testID="registerSelectServiceButton"
style={styles.textBtn}
onPress={onPressSelectService}>
<Text type="xl" style={[pal.text, styles.textBtnLabel]}>
{toNiceDomain(serviceUrl)}
</Text>
<View style={[pal.btn, styles.textBtnFakeInnerBtn]}>
<FontAwesomeIcon
icon="pen"
size={12}
style={[pal.textLight, styles.textBtnFakeInnerBtnIcon]}
/>
<Text style={[pal.textLight]}>Change</Text>
</View>
</TouchableOpacity>
</View>
</View>
{serviceDescription ? (
<>
<View style={styles.groupLabel}>
<Text type="sm-bold" style={pal.text}>
Account details
</Text>
</View>
<View style={[pal.borderDark, styles.group]}>
{serviceDescription?.inviteCodeRequired ? (
<View
style={[pal.border, styles.groupContent, styles.noTopBorder]}>
<FontAwesomeIcon
icon="ticket"
style={[pal.textLight, styles.groupContentIcon]}
/>
<TextInput
style={[pal.text, styles.textInput]}
placeholder="Invite code"
placeholderTextColor={pal.colors.textLight}
autoCapitalize="none"
autoCorrect={false}
autoFocus
keyboardAppearance={theme.colorScheme}
value={inviteCode}
onChangeText={setInviteCode}
onBlur={onBlurInviteCode}
editable={!isProcessing}
/>
</View>
) : undefined}
<View style={[pal.border, styles.groupContent]}>
<FontAwesomeIcon
icon="envelope"
style={[pal.textLight, styles.groupContentIcon]}
/>
<TextInput
testID="registerEmailInput"
style={[pal.text, styles.textInput]}
placeholder="Email address"
placeholderTextColor={pal.colors.textLight}
autoCapitalize="none"
autoCorrect={false}
value={email}
onChangeText={setEmail}
editable={!isProcessing}
/>
</View>
<View style={[pal.border, styles.groupContent]}>
<FontAwesomeIcon
icon="lock"
style={[pal.textLight, styles.groupContentIcon]}
/>
<TextInput
testID="registerPasswordInput"
style={[pal.text, styles.textInput]}
placeholder="Choose your password"
placeholderTextColor={pal.colors.textLight}
autoCapitalize="none"
autoCorrect={false}
secureTextEntry
value={password}
onChangeText={setPassword}
editable={!isProcessing}
/>
</View>
</View>
</>
) : undefined}
{serviceDescription ? (
<>
<View style={styles.groupLabel}>
<Text type="sm-bold" style={pal.text}>
Choose your username
</Text>
</View>
<View style={[pal.border, styles.group]}>
<View
style={[pal.border, styles.groupContent, styles.noTopBorder]}>
<FontAwesomeIcon
icon="at"
style={[pal.textLight, styles.groupContentIcon]}
/>
<TextInput
testID="registerHandleInput"
style={[pal.text, styles.textInput]}
placeholder="eg alice"
placeholderTextColor={pal.colors.textLight}
autoCapitalize="none"
value={handle}
onChangeText={v => setHandle(makeValidHandle(v))}
editable={!isProcessing}
/>
</View>
{serviceDescription.availableUserDomains.length > 1 && (
<View style={[pal.border, styles.groupContent]}>
<FontAwesomeIcon
icon="globe"
style={styles.groupContentIcon}
/>
<Picker
style={[pal.text, styles.picker]}
labelStyle={styles.pickerLabel}
iconStyle={pal.textLight as FontAwesomeIconStyle}
value={userDomain}
items={serviceDescription.availableUserDomains.map(d => ({
label: `.${d}`,
value: d,
}))}
onChange={itemValue => setUserDomain(itemValue)}
enabled={!isProcessing}
/>
</View>
)}
<View style={[pal.border, styles.groupContent]}>
<Text style={[pal.textLight, s.p10]}>
Your full username will be{' '}
<Text type="md-bold" style={pal.textLight}>
@{createFullHandle(handle, userDomain)}
</Text>
</Text>
</View>
</View>
<View style={styles.groupLabel}>
<Text type="sm-bold" style={pal.text}>
Legal
</Text>
</View>
<View style={[pal.border, styles.group]}>
<View
style={[pal.border, styles.groupContent, styles.noTopBorder]}>
<TouchableOpacity
testID="registerIs13Input"
style={styles.textBtn}
onPress={() => setIs13(!is13)}>
<View
style={[
pal.border,
is13 ? styles.checkboxFilled : styles.checkbox,
]}>
{is13 && (
<FontAwesomeIcon icon="check" style={s.blue3} size={14} />
)}
</View>
<Text style={[pal.text, styles.textBtnLabel]}>
I am 13 years old or older
</Text>
</TouchableOpacity>
</View>
</View>
<Policies serviceDescription={serviceDescription} />
</>
) : undefined}
<View style={[s.flexRow, s.pl20, s.pr20]}>
<TouchableOpacity onPress={onPressBack}>
<Text type="xl" style={pal.link}>
Back
</Text>
</TouchableOpacity>
<View style={s.flex1} />
{isReady ? (
<TouchableOpacity
testID="createAccountButton"
onPress={onPressNext}>
{isProcessing ? (
<ActivityIndicator />
) : (
<Text type="xl-bold" style={[pal.link, s.pr5]}>
Next
</Text>
)}
</TouchableOpacity>
) : !serviceDescription && error ? (
<TouchableOpacity
testID="registerRetryButton"
onPress={onPressRetryConnect}>
<Text type="xl-bold" style={[pal.link, s.pr5]}>
Retry
</Text>
</TouchableOpacity>
) : !serviceDescription ? (
<>
<ActivityIndicator color="#fff" />
<Text type="xl-bold" style={[pal.link, s.pr5]}>
Connecting...
</Text>
</>
) : undefined}
</View>
<View style={s.footerSpacer} />
</KeyboardAvoidingView>
</ScrollView>
)
}
const Policies = ({
serviceDescription,
}: {
serviceDescription: ServiceDescription
}) => {
const pal = usePalette('default')
if (!serviceDescription) {
return <View />
}
const tos = validWebLink(serviceDescription.links?.termsOfService)
const pp = validWebLink(serviceDescription.links?.privacyPolicy)
if (!tos && !pp) {
return (
<View style={styles.policies}>
<View style={[styles.errorIcon, {borderColor: pal.colors.text}, s.mt2]}>
<FontAwesomeIcon
icon="exclamation"
style={pal.textLight as FontAwesomeIconStyle}
size={10}
/>
</View>
<Text style={[pal.textLight, s.pl5, s.flex1]}>
This service has not provided terms of service or a privacy policy.
</Text>
</View>
)
}
const els = []
if (tos) {
els.push(
<TextLink
key="tos"
href={tos}
text="Terms of Service"
style={[pal.link, s.underline]}
/>,
)
}
if (pp) {
els.push(
<TextLink
key="pp"
href={pp}
text="Privacy Policy"
style={[pal.link, s.underline]}
/>,
)
}
if (els.length === 2) {
els.splice(
1,
0,
<Text key="and" style={pal.textLight}>
{' '}
and{' '}
</Text>,
)
}
return (
<View style={styles.policies}>
<Text style={pal.textLight}>
By creating an account you agree to the {els}.
</Text>
</View>
)
}
function validWebLink(url?: string): string | undefined {
return url && (url.startsWith('http://') || url.startsWith('https://'))
? url
: undefined
}
const styles = StyleSheet.create({
noTopBorder: {
borderTopWidth: 0,
},
logoHero: {
paddingTop: 30,
paddingBottom: 40,
},
group: {
borderWidth: 1,
borderRadius: 10,
marginBottom: 20,
marginHorizontal: 20,
},
groupLabel: {
paddingHorizontal: 20,
paddingBottom: 5,
},
groupContent: {
borderTopWidth: 1,
flexDirection: 'row',
alignItems: 'center',
},
groupContentIcon: {
marginLeft: 10,
},
textInput: {
flex: 1,
width: '100%',
paddingVertical: 10,
paddingHorizontal: 12,
fontSize: 17,
letterSpacing: 0.25,
fontWeight: '400',
borderRadius: 10,
},
textBtn: {
flexDirection: 'row',
flex: 1,
alignItems: 'center',
},
textBtnLabel: {
flex: 1,
paddingVertical: 10,
paddingHorizontal: 12,
},
textBtnFakeInnerBtn: {
flexDirection: 'row',
alignItems: 'center',
borderRadius: 6,
paddingVertical: 6,
paddingHorizontal: 8,
marginHorizontal: 6,
},
textBtnFakeInnerBtnIcon: {
marginRight: 4,
},
picker: {
flex: 1,
width: '100%',
paddingVertical: 10,
paddingHorizontal: 12,
fontSize: 17,
borderRadius: 10,
},
pickerLabel: {
fontSize: 17,
},
checkbox: {
borderWidth: 1,
borderRadius: 2,
width: 16,
height: 16,
marginLeft: 16,
},
checkboxFilled: {
borderWidth: 1,
borderRadius: 2,
width: 16,
height: 16,
marginLeft: 16,
},
policies: {
flexDirection: 'row',
alignItems: 'flex-start',
paddingHorizontal: 20,
paddingBottom: 20,
},
error: {
backgroundColor: colors.red4,
flexDirection: 'row',
alignItems: 'center',
marginTop: -5,
marginHorizontal: 20,
marginBottom: 15,
borderRadius: 8,
paddingHorizontal: 8,
paddingVertical: 8,
},
errorFloating: {
marginBottom: 20,
marginHorizontal: 20,
borderRadius: 8,
},
errorIcon: {
borderWidth: 1,
borderColor: colors.white,
borderRadius: 30,
width: 16,
height: 16,
alignItems: 'center',
justifyContent: 'center',
marginRight: 5,
},
})

View file

@ -15,7 +15,6 @@ import {s, colors} from 'lib/styles'
import {useStores} from 'state/index'
import {CreateAccountModel} from 'state/models/ui/create-account'
import {usePalette} from 'lib/hooks/usePalette'
import {useTheme} from 'lib/ThemeContext'
import {Step1} from './Step1'
import {Step2} from './Step2'