Migrate tricky spot, fix types
This commit is contained in:
@@ -38,7 +38,7 @@ type LoggerType = {
|
|||||||
useContext: (context: Exclude<Logger['context'], undefined>) => LoggerType
|
useContext: (context: Exclude<Logger['context'], undefined>) => LoggerType
|
||||||
Context: typeof Logger.Context
|
Context: typeof Logger.Context
|
||||||
}
|
}
|
||||||
type AnalyticsContextType = {
|
export type AnalyticsContextType = {
|
||||||
metadata: Metadata
|
metadata: Metadata
|
||||||
logger: LoggerType
|
logger: LoggerType
|
||||||
metric: <E extends keyof Metrics>(
|
metric: <E extends keyof Metrics>(
|
||||||
@@ -49,7 +49,7 @@ type AnalyticsContextType = {
|
|||||||
feature: (feature: Features) => boolean
|
feature: (feature: Features) => boolean
|
||||||
Features: typeof Features
|
Features: typeof Features
|
||||||
}
|
}
|
||||||
type AnalyticsBaseContextType = Omit<
|
export type AnalyticsBaseContextType = Omit<
|
||||||
AnalyticsContextType,
|
AnalyticsContextType,
|
||||||
'feature' | 'Features'
|
'feature' | 'Features'
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -234,15 +234,12 @@ function Inner(props: ReportDialogProps) {
|
|||||||
}
|
}
|
||||||
}, [_, submitReport, state, dispatch, props, setPending, setSuccess])
|
}, [_, submitReport, state, dispatch, props, setPending, setSuccess])
|
||||||
|
|
||||||
|
// TODO once
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
ax.metric(
|
ax.metric('reportDialog:open', {
|
||||||
'reportDialog:open',
|
subjectType: props.subject.type,
|
||||||
{
|
})
|
||||||
subjectType: props.subject.type,
|
}, [ax, props.subject])
|
||||||
},
|
|
||||||
{statsig: false},
|
|
||||||
)
|
|
||||||
}, [props.subject])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog.ScrollableInner
|
<Dialog.ScrollableInner
|
||||||
|
|||||||
@@ -127,13 +127,9 @@ function Inner({
|
|||||||
color="primary"
|
color="primary"
|
||||||
style={[a.justify_center]}
|
style={[a.justify_center]}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
ax.metric(
|
ax.metric('verification:learn-more', {
|
||||||
'verification:learn-more',
|
location: 'verifierDialog',
|
||||||
{
|
})
|
||||||
location: 'verifierDialog',
|
|
||||||
},
|
|
||||||
{statsig: true},
|
|
||||||
)
|
|
||||||
}}>
|
}}>
|
||||||
<ButtonText>
|
<ButtonText>
|
||||||
<Trans context="english-only-resource">Learn more</Trans>
|
<Trans context="english-only-resource">Learn more</Trans>
|
||||||
|
|||||||
@@ -171,6 +171,7 @@ function SyncStatus({
|
|||||||
info: AppBskyContactDefs.SyncStatus
|
info: AppBskyContactDefs.SyncStatus
|
||||||
refetchStatus: () => Promise<any>
|
refetchStatus: () => Promise<any>
|
||||||
}) {
|
}) {
|
||||||
|
const ax = useAnalytics()
|
||||||
const agent = useAgent()
|
const agent = useAgent()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
|||||||
@@ -29,17 +29,28 @@ import {LinearGradientBackground} from '#/components/LinearGradientBackground'
|
|||||||
import {InlineLinkText} from '#/components/Link'
|
import {InlineLinkText} from '#/components/Link'
|
||||||
import {ScreenTransition} from '#/components/ScreenTransition'
|
import {ScreenTransition} from '#/components/ScreenTransition'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {IS_ANDROID} from '#/env'
|
import {useAnalytics} from '#/analytics'
|
||||||
import {GCP_PROJECT_ID} from '#/env'
|
import {GCP_PROJECT_ID, IS_ANDROID} from '#/env'
|
||||||
import * as bsky from '#/types/bsky'
|
import * as bsky from '#/types/bsky'
|
||||||
|
|
||||||
export function Signup({onPressBack}: {onPressBack: () => void}) {
|
export function Signup({onPressBack}: {onPressBack: () => void}) {
|
||||||
|
const ax = useAnalytics()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const [state, dispatch] = useReducer(reducer, initialState)
|
const [state, dispatch] = useReducer(reducer, {
|
||||||
|
...initialState,
|
||||||
|
analytics: ax,
|
||||||
|
})
|
||||||
const {gtMobile} = useBreakpoints()
|
const {gtMobile} = useBreakpoints()
|
||||||
const submit = useSubmitSignup()
|
const submit = useSubmitSignup()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch({
|
||||||
|
type: 'setAnalytics',
|
||||||
|
value: ax,
|
||||||
|
})
|
||||||
|
}, [ax])
|
||||||
|
|
||||||
const activeStarterPack = useActiveStarterPack()
|
const activeStarterPack = useActiveStarterPack()
|
||||||
const {
|
const {
|
||||||
data: starterPack,
|
data: starterPack,
|
||||||
|
|||||||
+27
-23
@@ -12,9 +12,9 @@ import {DEFAULT_SERVICE} from '#/lib/constants'
|
|||||||
import {cleanError} from '#/lib/strings/errors'
|
import {cleanError} from '#/lib/strings/errors'
|
||||||
import {createFullHandle} from '#/lib/strings/handles'
|
import {createFullHandle} from '#/lib/strings/handles'
|
||||||
import {getAge} from '#/lib/strings/time'
|
import {getAge} from '#/lib/strings/time'
|
||||||
import {logger} from '#/logger'
|
|
||||||
import {useSessionApi} from '#/state/session'
|
import {useSessionApi} from '#/state/session'
|
||||||
import {useOnboardingDispatch} from '#/state/shell'
|
import {useOnboardingDispatch} from '#/state/shell'
|
||||||
|
import {type AnalyticsContextType, useAnalytics} from '#/analytics'
|
||||||
|
|
||||||
export type ServiceDescription = ComAtprotoServerDescribeServer.OutputSchema
|
export type ServiceDescription = ComAtprotoServerDescribeServer.OutputSchema
|
||||||
|
|
||||||
@@ -39,6 +39,8 @@ type ErrorField =
|
|||||||
| 'date-of-birth'
|
| 'date-of-birth'
|
||||||
|
|
||||||
export type SignupState = {
|
export type SignupState = {
|
||||||
|
analytics?: AnalyticsContextType
|
||||||
|
|
||||||
hasPrev: boolean
|
hasPrev: boolean
|
||||||
activeStep: SignupStep
|
activeStep: SignupStep
|
||||||
screenTransitionDirection: 'Forward' | 'Backward'
|
screenTransitionDirection: 'Forward' | 'Backward'
|
||||||
@@ -65,6 +67,7 @@ export type SignupState = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type SignupAction =
|
export type SignupAction =
|
||||||
|
| {type: 'setAnalytics'; value: AnalyticsContextType}
|
||||||
| {type: 'prev'}
|
| {type: 'prev'}
|
||||||
| {type: 'next'}
|
| {type: 'next'}
|
||||||
| {type: 'finish'}
|
| {type: 'finish'}
|
||||||
@@ -83,6 +86,8 @@ export type SignupAction =
|
|||||||
| {type: 'incrementBackgroundCount'}
|
| {type: 'incrementBackgroundCount'}
|
||||||
|
|
||||||
export const initialState: SignupState = {
|
export const initialState: SignupState = {
|
||||||
|
analytics: undefined,
|
||||||
|
|
||||||
hasPrev: false,
|
hasPrev: false,
|
||||||
activeStep: SignupStep.INFO,
|
activeStep: SignupStep.INFO,
|
||||||
screenTransitionDirection: 'Forward',
|
screenTransitionDirection: 'Forward',
|
||||||
@@ -126,6 +131,10 @@ export function reducer(s: SignupState, a: SignupAction): SignupState {
|
|||||||
let next = {...s}
|
let next = {...s}
|
||||||
|
|
||||||
switch (a.type) {
|
switch (a.type) {
|
||||||
|
case 'setAnalytics': {
|
||||||
|
next.analytics = a.value
|
||||||
|
break
|
||||||
|
}
|
||||||
case 'prev': {
|
case 'prev': {
|
||||||
if (s.activeStep !== SignupStep.INFO) {
|
if (s.activeStep !== SignupStep.INFO) {
|
||||||
next.screenTransitionDirection = 'Backward'
|
next.screenTransitionDirection = 'Backward'
|
||||||
@@ -194,16 +203,12 @@ export function reducer(s: SignupState, a: SignupAction): SignupState {
|
|||||||
next.fieldErrors[a.field] = (next.fieldErrors[a.field] || 0) + 1
|
next.fieldErrors[a.field] = (next.fieldErrors[a.field] || 0) + 1
|
||||||
|
|
||||||
// Log the field error
|
// Log the field error
|
||||||
logger.metric(
|
s.analytics?.metric('signup:fieldError', {
|
||||||
'signup:fieldError',
|
field: a.field,
|
||||||
{
|
errorCount: next.fieldErrors[a.field],
|
||||||
field: a.field,
|
errorMessage: a.value,
|
||||||
errorCount: next.fieldErrors[a.field],
|
activeStep: next.activeStep,
|
||||||
errorMessage: a.value,
|
})
|
||||||
activeStep: next.activeStep,
|
|
||||||
},
|
|
||||||
{statsig: true},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -220,24 +225,22 @@ export function reducer(s: SignupState, a: SignupAction): SignupState {
|
|||||||
next.backgroundCount = s.backgroundCount + 1
|
next.backgroundCount = s.backgroundCount + 1
|
||||||
|
|
||||||
// Log background/foreground event during signup
|
// Log background/foreground event during signup
|
||||||
logger.metric(
|
s.analytics?.metric('signup:backgrounded', {
|
||||||
'signup:backgrounded',
|
activeStep: next.activeStep,
|
||||||
{
|
backgroundCount: next.backgroundCount,
|
||||||
activeStep: next.activeStep,
|
})
|
||||||
backgroundCount: next.backgroundCount,
|
|
||||||
},
|
|
||||||
{statsig: true},
|
|
||||||
)
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
next.hasPrev = next.activeStep !== SignupStep.INFO
|
next.hasPrev = next.activeStep !== SignupStep.INFO
|
||||||
|
|
||||||
logger.debug('signup', next)
|
s.analytics?.logger.debug('signup', next)
|
||||||
|
|
||||||
if (s.activeStep !== next.activeStep) {
|
if (s.activeStep !== next.activeStep) {
|
||||||
logger.debug('signup: step changed', {activeStep: next.activeStep})
|
s.analytics?.logger.debug('signup: step changed', {
|
||||||
|
activeStep: next.activeStep,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return next
|
return next
|
||||||
@@ -252,6 +255,7 @@ SignupContext.displayName = 'SignupContext'
|
|||||||
export const useSignupContext = () => React.useContext(SignupContext)
|
export const useSignupContext = () => React.useContext(SignupContext)
|
||||||
|
|
||||||
export function useSubmitSignup() {
|
export function useSubmitSignup() {
|
||||||
|
const ax = useAnalytics()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const {createAccount} = useSessionApi()
|
const {createAccount} = useSessionApi()
|
||||||
const onboardingDispatch = useOnboardingDispatch()
|
const onboardingDispatch = useOnboardingDispatch()
|
||||||
@@ -295,7 +299,7 @@ export function useSubmitSignup() {
|
|||||||
!state.pendingSubmit?.verificationCode
|
!state.pendingSubmit?.verificationCode
|
||||||
) {
|
) {
|
||||||
dispatch({type: 'setStep', value: SignupStep.CAPTCHA})
|
dispatch({type: 'setStep', value: SignupStep.CAPTCHA})
|
||||||
logger.error('Signup Flow Error', {
|
ax.logger.error('Signup Flow Error', {
|
||||||
errorMessage: 'Verification captcha code was not set.',
|
errorMessage: 'Verification captcha code was not set.',
|
||||||
registrationHandle: state.handle,
|
registrationHandle: state.handle,
|
||||||
})
|
})
|
||||||
@@ -358,7 +362,7 @@ export function useSubmitSignup() {
|
|||||||
})
|
})
|
||||||
dispatch({type: 'setStep', value: isHandleError ? 2 : 1})
|
dispatch({type: 'setStep', value: isHandleError ? 2 : 1})
|
||||||
|
|
||||||
logger.error('Signup Flow Error', {
|
ax.logger.error('Signup Flow Error', {
|
||||||
errorMessage: error,
|
errorMessage: error,
|
||||||
registrationHandle: state.handle,
|
registrationHandle: state.handle,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import {
|
|||||||
PUBLIC_BSKY_SERVICE,
|
PUBLIC_BSKY_SERVICE,
|
||||||
} from '#/lib/constants'
|
} from '#/lib/constants'
|
||||||
import {createFullHandle} from '#/lib/strings/handles'
|
import {createFullHandle} from '#/lib/strings/handles'
|
||||||
import {logger} from '#/logger'
|
|
||||||
import {useDebouncedValue} from '#/components/live/utils'
|
import {useDebouncedValue} from '#/components/live/utils'
|
||||||
|
import {useAnalytics} from '#/analytics'
|
||||||
import * as bsky from '#/types/bsky'
|
import * as bsky from '#/types/bsky'
|
||||||
import {Agent} from '../session/agent'
|
import {Agent} from '../session/agent'
|
||||||
|
|
||||||
@@ -36,6 +36,7 @@ export function useHandleAvailabilityQuery(
|
|||||||
},
|
},
|
||||||
debounceDelayMs = 500,
|
debounceDelayMs = 500,
|
||||||
) {
|
) {
|
||||||
|
const ax = useAnalytics()
|
||||||
const name = username.trim()
|
const name = username.trim()
|
||||||
const debouncedHandle = useDebouncedValue(name, debounceDelayMs)
|
const debouncedHandle = useDebouncedValue(name, debounceDelayMs)
|
||||||
|
|
||||||
@@ -51,11 +52,16 @@ export function useHandleAvailabilityQuery(
|
|||||||
),
|
),
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const handle = createFullHandle(name, serviceDomain)
|
const handle = createFullHandle(name, serviceDomain)
|
||||||
return await checkHandleAvailability(handle, serviceDid, {
|
const res = await checkHandleAvailability(handle, serviceDid, {
|
||||||
email,
|
email,
|
||||||
birthDate,
|
birthDate,
|
||||||
typeahead: true,
|
|
||||||
})
|
})
|
||||||
|
if (res.available) {
|
||||||
|
ax.metric('signup:handleAvailable', {typeahead: true})
|
||||||
|
} else {
|
||||||
|
ax.metric('signup:handleTaken', {typeahead: true})
|
||||||
|
}
|
||||||
|
return res
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
@@ -67,11 +73,9 @@ export async function checkHandleAvailability(
|
|||||||
{
|
{
|
||||||
email,
|
email,
|
||||||
birthDate,
|
birthDate,
|
||||||
typeahead,
|
|
||||||
}: {
|
}: {
|
||||||
email?: string
|
email?: string
|
||||||
birthDate?: string
|
birthDate?: string
|
||||||
typeahead?: boolean
|
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
if (serviceDid === BSKY_SERVICE_DID) {
|
if (serviceDid === BSKY_SERVICE_DID) {
|
||||||
@@ -89,8 +93,6 @@ export async function checkHandleAvailability(
|
|||||||
ComAtprotoTempCheckHandleAvailability.isResultAvailable,
|
ComAtprotoTempCheckHandleAvailability.isResultAvailable,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
logger.metric('signup:handleAvailable', {typeahead}, {statsig: true})
|
|
||||||
|
|
||||||
return {available: true} as const
|
return {available: true} as const
|
||||||
} else if (
|
} else if (
|
||||||
bsky.dangerousIsType<ComAtprotoTempCheckHandleAvailability.ResultUnavailable>(
|
bsky.dangerousIsType<ComAtprotoTempCheckHandleAvailability.ResultUnavailable>(
|
||||||
@@ -98,7 +100,6 @@ export async function checkHandleAvailability(
|
|||||||
ComAtprotoTempCheckHandleAvailability.isResultUnavailable,
|
ComAtprotoTempCheckHandleAvailability.isResultUnavailable,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
logger.metric('signup:handleTaken', {typeahead}, {statsig: true})
|
|
||||||
return {
|
return {
|
||||||
available: false,
|
available: false,
|
||||||
suggestions: data.result.suggestions,
|
suggestions: data.result.suggestions,
|
||||||
@@ -117,11 +118,9 @@ export async function checkHandleAvailability(
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (res.data.did) {
|
if (res.data.did) {
|
||||||
logger.metric('signup:handleTaken', {typeahead}, {statsig: true})
|
|
||||||
return {available: false} as const
|
return {available: false} as const
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch {}
|
||||||
logger.metric('signup:handleAvailable', {typeahead}, {statsig: true})
|
|
||||||
return {available: true} as const
|
return {available: true} as const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user