diff options
author | Samuel Newman <mozzius@protonmail.com> | 2025-03-27 20:17:07 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-03-27 20:17:07 +0200 |
commit | 5ceaee57938892157491ae2941d05f90c1d74149 (patch) | |
tree | d5c2df5937570fd4f3393ecf431e37c6675d80c7 /src/screens/Signup/state.ts | |
parent | 7d1ebf6a027085ddc10a7dad2075d5e52d314233 (diff) | |
download | voidsky-5ceaee57938892157491ae2941d05f90c1d74149.tar.zst |
Instrument signup (#8037)
Diffstat (limited to 'src/screens/Signup/state.ts')
-rw-r--r-- | src/screens/Signup/state.ts | 90 |
1 files changed, 79 insertions, 11 deletions
diff --git a/src/screens/Signup/state.ts b/src/screens/Signup/state.ts index 3daf36a9b..48ea4ccd9 100644 --- a/src/screens/Signup/state.ts +++ b/src/screens/Signup/state.ts @@ -2,7 +2,7 @@ import React, {useCallback} from 'react' import {LayoutAnimation} from 'react-native' import { ComAtprotoServerCreateAccount, - ComAtprotoServerDescribeServer, + type ComAtprotoServerDescribeServer, } from '@atproto/api' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' @@ -56,6 +56,11 @@ export type SignupState = { isLoading: boolean pendingSubmit: null | SubmitTask + + // Tracking + signupStartTime: number + fieldErrors: Record<ErrorField, number> + backgroundCount: number } export type SignupAction = @@ -74,6 +79,7 @@ export type SignupAction = | {type: 'clearError'} | {type: 'setIsLoading'; value: boolean} | {type: 'submit'; task: SubmitTask} + | {type: 'incrementBackgroundCount'} export const initialState: SignupState = { hasPrev: false, @@ -93,6 +99,17 @@ export const initialState: SignupState = { isLoading: false, pendingSubmit: null, + + // Tracking + signupStartTime: Date.now(), + fieldErrors: { + 'invite-code': 0, + email: 0, + handle: 0, + password: 0, + 'date-of-birth': 0, + }, + backgroundCount: 0, } export function is13(date: Date) { @@ -169,6 +186,23 @@ export function reducer(s: SignupState, a: SignupAction): SignupState { case 'setError': { next.error = a.value next.errorField = a.field + + // Track field errors + if (a.field) { + next.fieldErrors[a.field] = (next.fieldErrors[a.field] || 0) + 1 + + // Log the field error + logger.metric( + 'signup:fieldError', + { + field: a.field, + errorCount: next.fieldErrors[a.field], + errorMessage: a.value, + activeStep: next.activeStep, + }, + {statsig: true}, + ) + } break } case 'clearError': { @@ -180,6 +214,20 @@ export function reducer(s: SignupState, a: SignupAction): SignupState { next.pendingSubmit = a.task break } + case 'incrementBackgroundCount': { + next.backgroundCount = s.backgroundCount + 1 + + // Log background/foreground event during signup + logger.metric( + 'signup:backgrounded', + { + activeStep: next.activeStep, + backgroundCount: next.backgroundCount, + }, + {statsig: true}, + ) + break + } } next.hasPrev = next.activeStep !== SignupStep.INFO @@ -212,6 +260,7 @@ export function useSubmitSignup() { return dispatch({ type: 'setError', value: _(msg`Please enter your email.`), + field: 'email', }) } if (!EmailValidator.validate(state.email)) { @@ -219,6 +268,7 @@ export function useSubmitSignup() { return dispatch({ type: 'setError', value: _(msg`Your email appears to be invalid.`), + field: 'email', }) } if (!state.password) { @@ -226,6 +276,7 @@ export function useSubmitSignup() { return dispatch({ type: 'setError', value: _(msg`Please choose your password.`), + field: 'password', }) } if (!state.handle) { @@ -233,6 +284,7 @@ export function useSubmitSignup() { return dispatch({ type: 'setError', value: _(msg`Please choose your handle.`), + field: 'handle', }) } if ( @@ -253,15 +305,26 @@ export function useSubmitSignup() { dispatch({type: 'setIsLoading', value: true}) try { - await createAccount({ - service: state.serviceUrl, - email: state.email, - handle: createFullHandle(state.handle, state.userDomain), - password: state.password, - birthDate: state.dateOfBirth, - inviteCode: state.inviteCode.trim(), - verificationCode: state.pendingSubmit?.verificationCode, - }) + await createAccount( + { + service: state.serviceUrl, + email: state.email, + handle: createFullHandle(state.handle, state.userDomain), + password: state.password, + birthDate: state.dateOfBirth, + inviteCode: state.inviteCode.trim(), + verificationCode: state.pendingSubmit?.verificationCode, + }, + { + signupDuration: Date.now() - state.signupStartTime, + fieldErrorsTotal: Object.values(state.fieldErrors).reduce( + (a, b) => a + b, + 0, + ), + backgroundCount: state.backgroundCount, + }, + ) + /* * Must happen last so that if the user has multiple tabs open and * createAccount fails, one tab is not stuck in onboarding — Eric @@ -275,6 +338,7 @@ export function useSubmitSignup() { value: _( msg`Invite code not accepted. Check that you input it correctly and try again.`, ), + field: 'invite-code', }) dispatch({type: 'setStep', value: SignupStep.INFO}) return @@ -284,7 +348,11 @@ export function useSubmitSignup() { const isHandleError = error.toLowerCase().includes('handle') dispatch({type: 'setIsLoading', value: false}) - dispatch({type: 'setError', value: error}) + dispatch({ + type: 'setError', + value: error, + field: isHandleError ? 'handle' : undefined, + }) dispatch({type: 'setStep', value: isHandleError ? 2 : 1}) logger.error('Signup Flow Error', { |