Add metrics for composer threadgate (#9401)

* add metrics for composer threadgate

* add metrics to the in-thread version

* fix type error
This commit is contained in:
Samuel Newman
2025-11-17 20:51:01 +02:00
committed by GitHub
parent 53b3bd93a5
commit bc62b3da76
4 changed files with 37 additions and 1 deletions
+5
View File
@@ -17,6 +17,7 @@ import {useLingui} from '@lingui/react'
import {HITSLOP_10} from '#/lib/constants' import {HITSLOP_10} from '#/lib/constants'
import {makeListLink, makeProfileLink} from '#/lib/routes/links' import {makeListLink, makeProfileLink} from '#/lib/routes/links'
import {logger} from '#/logger'
import {isNative} from '#/platform/detection' import {isNative} from '#/platform/detection'
import { import {
type ThreadgateAllowUISetting, type ThreadgateAllowUISetting,
@@ -89,6 +90,8 @@ export function WhoCanReply({post, isThreadAuthor, style}: WhoCanReplyProps) {
Keyboard.dismiss() Keyboard.dismiss()
} }
if (isThreadAuthor) { if (isThreadAuthor) {
logger.metric('thread:click:editOwnThreadgate', {})
// wait on prefetch if it manages to resolve in under 200ms // wait on prefetch if it manages to resolve in under 200ms
// otherwise, proceed immediately and show the spinner -sfn // otherwise, proceed immediately and show the spinner -sfn
Promise.race([ Promise.race([
@@ -98,6 +101,8 @@ export function WhoCanReply({post, isThreadAuthor, style}: WhoCanReplyProps) {
editDialogControl.open() editDialogControl.open()
}) })
} else { } else {
logger.metric('thread:click:viewSomeoneElsesThreadgate', {})
infoDialogControl.open() infoDialogControl.open()
} }
} }
@@ -10,6 +10,7 @@ import {useLingui} from '@lingui/react'
import {useQueryClient} from '@tanstack/react-query' import {useQueryClient} from '@tanstack/react-query'
import {useHaptics} from '#/lib/haptics' import {useHaptics} from '#/lib/haptics'
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
import {logger} from '#/logger' import {logger} from '#/logger'
import {isIOS} from '#/platform/detection' import {isIOS} from '#/platform/detection'
import {STALE} from '#/state/queries' import {STALE} from '#/state/queries'
@@ -79,13 +80,26 @@ export function PostInteractionSettingsControlledDialog({
}: PostInteractionSettingsFormProps & { }: PostInteractionSettingsFormProps & {
control: Dialog.DialogControlProps control: Dialog.DialogControlProps
}) { }) {
const onClose = useNonReactiveCallback(() => {
logger.metric('composer:threadgate:save', {
hasChanged: !!rest.isDirty,
persist: !!rest.persist,
replyOptions:
rest.threadgateAllowUISettings?.map(gate => gate.type)?.join(',') ?? '',
quotesEnabled: !rest.postgate?.embeddingRules?.find(
v => v.$type === embeddingRules.disableRule.$type,
),
})
})
return ( return (
<Dialog.Outer <Dialog.Outer
control={control} control={control}
nativeOptions={{ nativeOptions={{
preventExpansion: true, preventExpansion: true,
preventDismiss: rest.isDirty && rest.persist, preventDismiss: rest.isDirty && rest.persist,
}}> }}
onClose={onClose}>
<Dialog.Handle /> <Dialog.Handle />
<DialogInner {...rest} /> <DialogInner {...rest} />
</Dialog.Outer> </Dialog.Outer>
+12
View File
@@ -203,6 +203,16 @@ export type MetricEvents = {
'composer:gif:open': {} 'composer:gif:open': {}
'composer:gif:select': {} 'composer:gif:select': {}
'composer:threadgate:open': {
nudged: boolean
}
'composer:threadgate:save': {
replyOptions: string
quotesEnabled: boolean
persist: boolean
hasChanged: boolean
}
// Data events // Data events
'account:create:begin': {} 'account:create:begin': {}
'account:create:success': { 'account:create:success': {
@@ -514,6 +524,8 @@ export type MetricEvents = {
[key: string]: any [key: string]: any
} }
'thread:click:headerMenuOpen': {} 'thread:click:headerMenuOpen': {}
'thread:click:editOwnThreadgate': {}
'thread:click:viewSomeoneElsesThreadgate': {}
'activitySubscription:enable': { 'activitySubscription:enable': {
setting: 'posts' | 'posts_and_replies' setting: 'posts' | 'posts_and_replies'
} }
@@ -45,6 +45,7 @@ export function ThreadgateBtn({
const control = Dialog.useDialogControl() const control = Dialog.useDialogControl()
const [threadgateNudged, setThreadgateNudged] = useThreadgateNudged() const [threadgateNudged, setThreadgateNudged] = useThreadgateNudged()
const [showTooltip, setShowTooltip] = useState(false) const [showTooltip, setShowTooltip] = useState(false)
const [tooltipWasShown] = useState(!threadgateNudged)
useEffect(() => { useEffect(() => {
if (!threadgateNudged) { if (!threadgateNudged) {
@@ -65,6 +66,10 @@ export function ThreadgateBtn({
const [persist, setPersist] = useState(false) const [persist, setPersist] = useState(false)
const onPress = () => { const onPress = () => {
logger.metric('composer:threadgate:open', {
nudged: tooltipWasShown,
})
if (isNative && Keyboard.isVisible()) { if (isNative && Keyboard.isVisible()) {
Keyboard.dismiss() Keyboard.dismiss()
} }