···4848 return
4949 }
5050 onSuccess(code)
5151- } catch (e: unknown) {
5151+ } catch (e) {
5252 // We don't actually want to record an error here, because this will happen quite a bit. We will only be able to
5353- // get hte href of the iframe if it's on our domain, so all the hcaptcha requests will throw here, although it's
5353+ // get the href of the iframe if it's on our domain, so all the hcaptcha requests will throw here, although it's
5454 // harmless. Our other indicators of time-to-complete and back press should be more reliable in catching issues.
5555 }
5656 }, [stateParam, onSuccess, onError])
···11import {useEffect, useRef, useState} from 'react'
22import {type TextInput, View} from 'react-native'
33-import {msg} from '@lingui/core/macro'
44-import {useLingui} from '@lingui/react'
55-import {Plural, Trans} from '@lingui/react/macro'
33+import {Plural, Trans, useLingui} from '@lingui/react/macro'
64import * as EmailValidator from 'email-validator'
75import type tldts from 'tldts'
86···6058 refetchServer: () => void
6159 isLoadingStarterPack: boolean
6260}) {
6363- const {_} = useLingui()
6161+ const {t: l} = useLingui()
6462 const ax = useAnalytics()
6563 const {state, dispatch} = useSignupContext()
6664 const preemptivelyCompleteActivePolicyUpdate =
···9492 const tldtsRef = useRef<typeof tldts>(undefined)
9593 useEffect(() => {
9694 // @ts-expect-error - valid path
9797- import('tldts/dist/index.cjs.min.js').then(tldts => {
9595+ void import('tldts/dist/index.cjs.min.js').then(tldts => {
9896 tldtsRef.current = tldts
9997 })
10098 // This will get used in the avatar creator a few steps later, so lets preload it now
10199 // @ts-expect-error - valid path
102102- import('react-native-view-shot/src/index')
100100+ void import('react-native-view-shot/src/index')
103101 }, [])
104102105103 const onNextPress = () => {
···115113 if (state.serviceDescription?.inviteCodeRequired && !inviteCode) {
116114 return dispatch({
117115 type: 'setError',
118118- value: _(msg`Please enter your invite code.`),
116116+ value: l`Please enter your invite code.`,
119117 field: 'invite-code',
120118 })
121119 }
122120 if (!email) {
123121 return dispatch({
124122 type: 'setError',
125125- value: _(msg`Please enter your email.`),
123123+ value: l`Please enter your email.`,
126124 field: 'email',
127125 })
128126 }
129127 if (!EmailValidator.validate(email)) {
130128 return dispatch({
131129 type: 'setError',
132132- value: _(msg`Your email appears to be invalid.`),
130130+ value: l`Your email appears to be invalid.`,
133131 field: 'email',
134132 })
135133 }
···139137 setHasWarnedEmail(true)
140138 return dispatch({
141139 type: 'setError',
142142- value: _(
143143- msg`Please double-check that you have entered your email address correctly.`,
144144- ),
140140+ value: l`Please double-check that you have entered your email address correctly.`,
145141 })
146142 }
147143 } else if (hasWarnedEmail) {
···151147 if (!password) {
152148 return dispatch({
153149 type: 'setError',
154154- value: _(msg`Please choose your password.`),
150150+ value: l`Please choose your password.`,
155151 field: 'password',
156152 })
157153 }
158154 if (password.length < 8) {
159155 return dispatch({
160156 type: 'setError',
161161- value: _(msg`Your password must be at least 8 characters long.`),
157157+ value: l`Your password must be at least 8 characters long.`,
162158 field: 'password',
163159 })
164160 }
···205201 dispatch({type: 'clearError'})
206202 }
207203 }}
208208- label={_(msg`Required for this provider`)}
204204+ label={l`Required for this provider`}
209205 defaultValue={state.inviteCode}
210206 autoCapitalize="none"
211207 autoComplete="email"
···241237 dispatch({type: 'clearError'})
242238 }
243239 }}
244244- label={_(msg`Enter your email address`)}
240240+ label={l`Enter your email address`}
245241 defaultValue={state.email}
246242 autoCapitalize="none"
247243 autoComplete="email"
···269265 dispatch({type: 'clearError'})
270266 }
271267 }}
272272- label={_(msg`Choose your password`)}
268268+ label={l`Choose your password`}
273269 defaultValue={state.password}
274270 secureTextEntry
275271 autoComplete="new-password"
···297293 value: sanitizeDate(new Date(date)),
298294 })
299295 }}
300300- label={_(msg`Date of birth`)}
301301- accessibilityHint={_(msg`Select your date of birth`)}
296296+ label={l`Date of birth`}
297297+ accessibilityHint={l`Select your date of birth`}
302298 maximumDate={new Date()}
303299 />
304300 </View>
···331327 <Trans>
332328 Have we got your location wrong?{' '}
333329 <SimpleInlineLinkText
334334- label={_(
335335- msg`Tap here to confirm your location with GPS.`,
336336- )}
330330+ label={l`Tap here to confirm your location with GPS.`}
337331 {...createStaticClick(() => {
338332 locationControl.open()
339333 })}>
···363357 props.closeDialog(() => {
364358 // set this after close!
365359 setDeviceGeolocation(props.geolocation)
366366- Toast.show(_(msg`Your location has been updated.`), {
360360+ Toast.show(l`Your location has been updated.`, {
367361 type: 'success',
368362 })
369363 })
···380374 onBackPress={onPressBack}
381375 onNextPress={onNextPress}
382376 onRetryPress={refetchServer}
383383- overrideNextText={hasWarnedEmail ? _(msg`It's correct`) : undefined}
377377+ overrideNextText={hasWarnedEmail ? l`It's correct` : undefined}
384378 />
385379 </>
386380 )
+12-13
src/screens/Signup/index.tsx
···33import ReactNativeDeviceAttest from 'react-native-device-attest'
44import Animated, {FadeIn, LayoutAnimationConfig} from 'react-native-reanimated'
55import {AppBskyGraphStarterpack} from '@atproto/api'
66-import {msg} from '@lingui/core/macro'
77-import {useLingui} from '@lingui/react'
88-import {Trans} from '@lingui/react/macro'
66+import {Trans, useLingui} from '@lingui/react/macro'
97108import {FEEDBACK_FORM_URL} from '#/lib/constants'
119import {logger} from '#/logger'
···36343735export function Signup({onPressBack}: {onPressBack: () => void}) {
3836 const ax = useAnalytics()
3939- const {_} = useLingui()
3737+ const {t: l} = useLingui()
4038 const t = useTheme()
4139 const [state, dispatch] = useReducer(reducer, {
4240 ...initialState,
···6159 uri: activeStarterPack?.uri,
6260 })
63616262+ // eslint-disable-next-line react/hook-use-state
6463 const [isFetchedAtMount] = useState(starterPack != null)
6564 const showStarterPackCard =
6665 activeStarterPack?.uri && !isFetchingStarterPack && starterPack
···8584 dispatch({type: 'setServiceDescription', value: undefined})
8685 dispatch({
8786 type: 'setError',
8888- value: _(
8989- msg`Unable to contact your service. Please check your Internet connection.`,
9090- ),
8787+ value: l`Unable to contact your service. Please check your Internet connection.`,
9188 })
9289 } else if (serviceInfo) {
9390 dispatch({type: 'setServiceDescription', value: serviceInfo})
9491 dispatch({type: 'setError', value: ''})
9592 }
9696- }, [_, serviceInfo, isError])
9393+ }, [l, serviceInfo, isError])
97949895 useEffect(() => {
9996 if (state.pendingSubmit) {
10097 if (!state.pendingSubmit.mutableProcessed) {
9898+ // OK to mutate assuming it's never read in render.
9999+ // eslint-disable-next-line react-hooks/immutability, react-compiler/react-compiler
101100 state.pendingSubmit.mutableProcessed = true
102102- submit(state, dispatch)
101101+ void submit(state, dispatch)
103102 }
104103 }
105104 }, [state, dispatch, submit])
···133132 <SignupContext.Provider value={{state, dispatch}}>
134133 <LoggedOutLayout
135134 leadin=""
136136- title={_(msg`Create Account`)}
137137- description={_(msg`We're so excited to have you join us!`)}
135135+ title={l`Create account`}
136136+ description={l`We’re so excited to have you join us!`}
138137 scrollable>
139138 <View testID="createAccount" style={a.flex_1}>
140139 {showStarterPackCard &&
···204203 isFetchingStarterPack && !isErrorStarterPack
205204 }
206205 isServerError={isError}
207207- refetchServer={refetch}
206206+ refetchServer={() => void refetch()}
208207 />
209208 ) : state.activeStep === SignupStep.HANDLE ? (
210209 <StepHandle />
···231230 ]}>
232231 <Trans>Having trouble?</Trans>{' '}
233232 <InlineLinkText
234234- label={_(msg`Contact support`)}
233233+ label={l`Contact support`}
235234 to={FEEDBACK_FORM_URL({email: state.email})}
236235 style={[!gtMobile && a.text_md]}>
237236 <Trans>Contact support</Trans>
+14-14
src/screens/Signup/state.ts
···44 ComAtprotoServerCreateAccount,
55 type ComAtprotoServerDescribeServer,
66} from '@atproto/api'
77-import {msg} from '@lingui/core/macro'
88-import {useLingui} from '@lingui/react'
77+import {useLingui} from '@lingui/react/macro'
98import * as EmailValidator from 'email-validator'
1091110import {DEFAULT_SERVICE} from '#/lib/constants'
···18171918export type ServiceDescription = ComAtprotoServerDescribeServer.OutputSchema
20192121-const DEFAULT_DATE = new Date(Date.now() - 60e3 * 60 * 24 * 365 * 20) // default to 20 years ago
2020+const date = new Date()
2121+date.setFullYear(date.getFullYear() - 20) // default to 20 years ago
2222+const DEFAULT_DATE = date
22232324export enum SignupStep {
2425 INFO,
···256257257258export function useSubmitSignup() {
258259 const ax = useAnalytics()
259259- const {_} = useLingui()
260260+ const {t: l} = useLingui()
260261 const {createAccount} = useSessionApi()
261262 const onboardingDispatch = useOnboardingDispatch()
262263···266267 dispatch({type: 'setStep', value: SignupStep.INFO})
267268 return dispatch({
268269 type: 'setError',
269269- value: _(msg`Please enter your email.`),
270270+ value: l`Please enter your email.`,
270271 field: 'email',
271272 })
272273 }
···274275 dispatch({type: 'setStep', value: SignupStep.INFO})
275276 return dispatch({
276277 type: 'setError',
277277- value: _(msg`Your email appears to be invalid.`),
278278+ value: l`Your email appears to be invalid.`,
278279 field: 'email',
279280 })
280281 }
···282283 dispatch({type: 'setStep', value: SignupStep.INFO})
283284 return dispatch({
284285 type: 'setError',
285285- value: _(msg`Please choose your password.`),
286286+ value: l`Please choose your password.`,
286287 field: 'password',
287288 })
288289 }
···290291 dispatch({type: 'setStep', value: SignupStep.HANDLE})
291292 return dispatch({
292293 type: 'setError',
293293- value: _(msg`Please choose your handle.`),
294294+ value: l`Please choose your handle.`,
294295 field: 'handle',
295296 })
296297 }
···305306 })
306307 return dispatch({
307308 type: 'setError',
308308- value: _(msg`Please complete the verification captcha.`),
309309+ value: l`Please complete the verification captcha.`,
309310 })
310311 }
311312 dispatch({type: 'setError', value: ''})
···337338 * createAccount fails, one tab is not stuck in onboarding — Eric
338339 */
339340 onboardingDispatch({type: 'start'})
340340- } catch (e: any) {
341341+ } catch (err) {
342342+ const e = err as Error
341343 let errMsg = e.toString()
342344 if (e instanceof ComAtprotoServerCreateAccount.InvalidInviteCodeError) {
343345 dispatch({
344346 type: 'setError',
345345- value: _(
346346- msg`Invite code not accepted. Check that you input it correctly and try again.`,
347347- ),
347347+ value: l`Invite code not accepted. Check that you input it correctly and try again.`,
348348 field: 'invite-code',
349349 })
350350 dispatch({type: 'setStep', value: SignupStep.INFO})
···370370 dispatch({type: 'setIsLoading', value: false})
371371 }
372372 },
373373- [_, onboardingDispatch, createAccount],
373373+ [l, ax.logger, createAccount, onboardingDispatch],
374374 )
375375}
+1-1
src/state/birthdate.ts
···1414 * Stores the timestamp of the birthday update locally. This is used to
1515 * debounce birthday updates globally.
1616 *
1717- * Use {@link useIsBirthDateUpdateAllowed} to check if an update is allowed.
1717+ * Use {@link useIsBirthdateUpdateAllowed} to check if an update is allowed.
1818 */
1919export function snoozeBirthdateUpdateAllowedForDid(did: string) {
2020 account.set([did, 'birthdateLastUpdatedAt'], new Date().toISOString())