diff --git a/src/components/ageAssurance/AgeAssuranceAccountCard.tsx b/src/components/ageAssurance/AgeAssuranceAccountCard.tsx index 530e43d449..a00a8c71ae 100644 --- a/src/components/ageAssurance/AgeAssuranceAccountCard.tsx +++ b/src/components/ageAssurance/AgeAssuranceAccountCard.tsx @@ -4,6 +4,7 @@ import {useLingui} from '@lingui/react' import {dateDiff, useGetTimeAgo} from '#/lib/hooks/useTimeAgo' import {useAgeAssurance} from '#/state/ageAssurance/useAgeAssurance' +import {logger} from '#/state/ageAssurance/util' import {atoms as a, useBreakpoints, useTheme, type ViewStyleProp} from '#/alf' import {Admonition} from '#/components/Admonition' import {AgeAssuranceAppealDialog} from '#/components/ageAssurance/AgeAssuranceAppealDialog' @@ -83,6 +84,7 @@ function Inner({style}: ViewStyleProp & {}) { label={_(msg`Contact our moderation team`)} {...createStaticClick(() => { appealControl.open() + logger.metric('ageAssurance:appealDialogOpen', {}) })}> contact our moderation team {' '} @@ -109,7 +111,12 @@ function Inner({style}: ViewStyleProp & {}) { size="small" variant="solid" color={hasInitiated ? 'secondary' : 'primary'} - onPress={() => control.open()}> + onPress={() => { + control.open() + logger.metric('ageAssurance:initDialogOpen', { + hasInitiatedPreviously: hasInitiated, + }) + }}> {hasInitiated ? ( Verify again diff --git a/src/components/ageAssurance/AgeAssuranceAdmonition.tsx b/src/components/ageAssurance/AgeAssuranceAdmonition.tsx index d140b7873e..1c77adbbb8 100644 --- a/src/components/ageAssurance/AgeAssuranceAdmonition.tsx +++ b/src/components/ageAssurance/AgeAssuranceAdmonition.tsx @@ -3,6 +3,7 @@ import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useAgeAssurance} from '#/state/ageAssurance/useAgeAssurance' +import {logger} from '#/state/ageAssurance/util' import {atoms as a, select, useTheme, type ViewStyleProp} from '#/alf' import {useDialogControl} from '#/components/ageAssurance/AgeAssuranceInitDialog' import type * as Dialog from '#/components/Dialog' @@ -87,7 +88,10 @@ function Inner({ + style={[a.text_sm, a.leading_snug, a.font_bold]} + onPress={() => { + logger.metric('ageAssurance:navigateToSettings', {}) + }}> account settings. diff --git a/src/components/ageAssurance/AgeAssuranceAppealDialog.tsx b/src/components/ageAssurance/AgeAssuranceAppealDialog.tsx index 166f6c26d9..cc0d568cab 100644 --- a/src/components/ageAssurance/AgeAssuranceAppealDialog.tsx +++ b/src/components/ageAssurance/AgeAssuranceAppealDialog.tsx @@ -5,7 +5,7 @@ import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useMutation} from '@tanstack/react-query' -import {logger} from '#/logger' +import {logger} from '#/state/ageAssurance/util' import {useAgent, useSession} from '#/state/session' import * as Toast from '#/view/com/util/Toast' import {atoms as a, useBreakpoints, web} from '#/alf' @@ -45,6 +45,8 @@ function Inner({control}: {control: Dialog.DialogControlProps}) { const {mutate, isPending} = useMutation({ mutationFn: async () => { + logger.metric('ageAssurance:appealDialogSubmit', {}) + await agent.createModerationReport( { reasonType: ComAtprotoModerationDefs.REASONAPPEAL, diff --git a/src/components/ageAssurance/AgeAssuranceDismissibleFeedBanner.tsx b/src/components/ageAssurance/AgeAssuranceDismissibleFeedBanner.tsx index a628daa03f..579740dcfa 100644 --- a/src/components/ageAssurance/AgeAssuranceDismissibleFeedBanner.tsx +++ b/src/components/ageAssurance/AgeAssuranceDismissibleFeedBanner.tsx @@ -4,6 +4,7 @@ import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useAgeAssurance} from '#/state/ageAssurance/useAgeAssurance' +import {logger} from '#/state/ageAssurance/util' import {Nux, useNux, useSaveNux} from '#/state/queries/nuxs' import {atoms as a, select, useTheme} from '#/alf' import {useAgeAssuranceCopy} from '#/components/ageAssurance/useAgeAssuranceCopy' @@ -72,7 +73,10 @@ export function AgeAssuranceDismissibleFeedBanner() { { + close() + logger.metric('ageAssurance:navigateToSettings', {}) + }} style={[a.w_full, a.justify_between, a.align_center, a.gap_md]}> { + close() + logger.metric('ageAssurance:dismissFeedBanner', {}) + }} style={[ a.absolute, a.justify_center, diff --git a/src/components/ageAssurance/AgeAssuranceDismissibleNotice.tsx b/src/components/ageAssurance/AgeAssuranceDismissibleNotice.tsx index 30e2fbec44..c9f242ca88 100644 --- a/src/components/ageAssurance/AgeAssuranceDismissibleNotice.tsx +++ b/src/components/ageAssurance/AgeAssuranceDismissibleNotice.tsx @@ -3,6 +3,7 @@ import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useAgeAssurance} from '#/state/ageAssurance/useAgeAssurance' +import {logger} from '#/state/ageAssurance/util' import {Nux, useNux, useSaveNux} from '#/state/queries/nuxs' import {atoms as a, type ViewStyleProp} from '#/alf' import {AgeAssuranceAdmonition} from '#/components/ageAssurance/AgeAssuranceAdmonition' @@ -37,13 +38,14 @@ export function AgeAssuranceDismissibleNotice({style}: ViewStyleProp & {}) { variant="solid" color="secondary_inverted" shape="round" - onPress={() => + onPress={() => { save({ id: Nux.AgeAssuranceDismissibleNotice, completed: true, data: undefined, }) - } + logger.metric('ageAssurance:dismissSettingsNotice', {}) + }} style={[ a.absolute, { diff --git a/src/components/ageAssurance/AgeAssuranceInitDialog.tsx b/src/components/ageAssurance/AgeAssuranceInitDialog.tsx index e3df8dabce..a189d9af29 100644 --- a/src/components/ageAssurance/AgeAssuranceInitDialog.tsx +++ b/src/components/ageAssurance/AgeAssuranceInitDialog.tsx @@ -16,6 +16,7 @@ import {isEmailMaybeInvalid} from '#/lib/strings/email' import {type AppLanguage} from '#/locale/languages' import {useAgeAssuranceContext} from '#/state/ageAssurance' import {useInitAgeAssurance} from '#/state/ageAssurance/useInitAgeAssurance' +import {logger} from '#/state/ageAssurance/util' import {useLanguagePrefs} from '#/state/preferences' import {useSession} from '#/state/session' import {atoms as a, useTheme, web} from '#/alf' @@ -115,6 +116,8 @@ function Inner() { const onSubmit = async () => { setLanguageError(false) + logger.metric('ageAssurance:initDialogSubmit', {}) + try { const {status} = runEmailValidation() @@ -138,6 +141,7 @@ function Inner() { msg`Please enter a valid, non-temporary email address. You may need to access this email in the future.`, ), ) + logger.metric('ageAssurance:initDialogError', {code: 'InvalidEmail'}) } else if (e.error === 'DidTooLong') { setError( <> @@ -153,10 +157,12 @@ function Inner() { , ) + logger.metric('ageAssurance:initDialogError', {code: 'DidTooLong'}) } } else { const {clean, raw} = cleanError(e) setError(clean || raw || _(msg`Something went wrong, please try again`)) + logger.metric('ageAssurance:initDialogError', {code: 'other'}) } } } diff --git a/src/components/ageAssurance/AgeAssuranceRedirectDialog.tsx b/src/components/ageAssurance/AgeAssuranceRedirectDialog.tsx index 41e706feed..ff2e0bfd0f 100644 --- a/src/components/ageAssurance/AgeAssuranceRedirectDialog.tsx +++ b/src/components/ageAssurance/AgeAssuranceRedirectDialog.tsx @@ -7,6 +7,7 @@ import {retry} from '#/lib/async/retry' import {wait} from '#/lib/async/wait' import {isNative} from '#/platform/detection' import {useAgeAssuranceAPIContext} from '#/state/ageAssurance' +import {logger} from '#/state/ageAssurance/util' import {useAgent} from '#/state/session' import {atoms as a, useTheme, web} from '#/alf' import {AgeAssuranceBadge} from '#/components/ageAssurance/AgeAssuranceBadge' @@ -92,6 +93,8 @@ export function Inner({}: {optimisticState?: AgeAssuranceRedirectDialogState}) { polling.current = true + logger.metric('ageAssurance:redirectDialogOpen', {}) + wait( 3e3, retry( @@ -124,12 +127,15 @@ export function Inner({}: {optimisticState?: AgeAssuranceRedirectDialogState}) { control.clear() control.control.close() + + logger.metric('ageAssurance:redirectDialogSuccess', {}) }) .catch(() => { if (unmounted.current) return setError(true) // try a refetch anyway refreshAgeAssuranceState() + logger.metric('ageAssurance:redirectDialogFail', {}) }) return () => { diff --git a/src/components/ageAssurance/AgeRestrictedScreen.tsx b/src/components/ageAssurance/AgeRestrictedScreen.tsx index 2a98824154..05dfb9e719 100644 --- a/src/components/ageAssurance/AgeRestrictedScreen.tsx +++ b/src/components/ageAssurance/AgeRestrictedScreen.tsx @@ -3,6 +3,7 @@ import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useAgeAssurance} from '#/state/ageAssurance/useAgeAssurance' +import {logger} from '#/state/ageAssurance/util' import {atoms as a} from '#/alf' import {Admonition} from '#/components/Admonition' import {AgeAssuranceBadge} from '#/components/ageAssurance/AgeAssuranceBadge' @@ -77,7 +78,10 @@ export function AgeRestrictedScreen({ to="/settings/account" size="small" variant="solid" - color="primary"> + color="primary" + onPress={() => { + logger.metric('ageAssurance:navigateToSettings', {}) + }}> Go to account settings diff --git a/src/logger/metrics.ts b/src/logger/metrics.ts index 3390c4b4be..dfca1f7d8e 100644 --- a/src/logger/metrics.ts +++ b/src/logger/metrics.ts @@ -457,4 +457,20 @@ export type MetricEvents = { name: string value: string } + + 'ageAssurance:navigateToSettings': {} + 'ageAssurance:dismissFeedBanner': {} + 'ageAssurance:dismissSettingsNotice': {} + 'ageAssurance:initDialogOpen': { + hasInitiatedPreviously: boolean + } + 'ageAssurance:initDialogSubmit': {} + 'ageAssurance:initDialogError': { + code: string + } + 'ageAssurance:redirectDialogOpen': {} + 'ageAssurance:redirectDialogSuccess': {} + 'ageAssurance:redirectDialogFail': {} + 'ageAssurance:appealDialogOpen': {} + 'ageAssurance:appealDialogSubmit': {} } diff --git a/src/state/ageAssurance/index.tsx b/src/state/ageAssurance/index.tsx index aab954e6cd..eded747732 100644 --- a/src/state/ageAssurance/index.tsx +++ b/src/state/ageAssurance/index.tsx @@ -6,17 +6,15 @@ import {networkRetry} from '#/lib/async/retry' import {useGetAndRegisterPushToken} from '#/lib/notifications/notifications' import {useGate} from '#/lib/statsig/statsig' import {isNetworkError} from '#/lib/strings/errors' -import {Logger} from '#/logger' import { type AgeAssuranceAPIContextType, type AgeAssuranceContextType, } from '#/state/ageAssurance/types' import {useIsAgeAssuranceEnabled} from '#/state/ageAssurance/useIsAgeAssuranceEnabled' +import {logger} from '#/state/ageAssurance/util' import {useGeolocation} from '#/state/geolocation' import {useAgent} from '#/state/session' -const logger = Logger.create(Logger.Context.AgeAssurance) - export const createAgeAssuranceQueryKey = (did: string) => ['ageAssurance', did] as const diff --git a/src/state/ageAssurance/useAgeAssurance.ts b/src/state/ageAssurance/useAgeAssurance.ts index 455f38c926..0215cc88dc 100644 --- a/src/state/ageAssurance/useAgeAssurance.ts +++ b/src/state/ageAssurance/useAgeAssurance.ts @@ -1,11 +1,9 @@ import {useMemo} from 'react' -import {Logger} from '#/logger' import {useAgeAssuranceContext} from '#/state/ageAssurance' +import {logger} from '#/state/ageAssurance/util' import {usePreferencesQuery} from '#/state/queries/preferences' -const logger = Logger.create(Logger.Context.AgeAssurance) - type AgeAssurance = ReturnType & { /** * The age the user has declared in their preferences, if any. diff --git a/src/state/ageAssurance/util.ts b/src/state/ageAssurance/util.ts new file mode 100644 index 0000000000..6b0e97b1c1 --- /dev/null +++ b/src/state/ageAssurance/util.ts @@ -0,0 +1,3 @@ +import {Logger} from '#/logger' + +export const logger = Logger.create(Logger.Context.AgeAssurance)