about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/components/PostControls/index.tsx3
-rw-r--r--src/logger/metrics.ts25
-rw-r--r--src/screens/Profile/components/ProfileFeedHeader.tsx20
-rw-r--r--src/screens/VideoFeed/index.tsx1
-rw-r--r--src/state/queries/post.ts30
5 files changed, 62 insertions, 17 deletions
diff --git a/src/components/PostControls/index.tsx b/src/components/PostControls/index.tsx
index f024928ee..f871cf356 100644
--- a/src/components/PostControls/index.tsx
+++ b/src/components/PostControls/index.tsx
@@ -69,14 +69,17 @@ let PostControls = ({
   const {_, i18n} = useLingui()
   const {gtMobile} = useBreakpoints()
   const {openComposer} = useOpenComposer()
+  const {feedDescriptor} = useFeedFeedbackContext()
   const [queueLike, queueUnlike] = usePostLikeMutationQueue(
     post,
     viaRepost,
+    feedDescriptor,
     logContext,
   )
   const [queueRepost, queueUnrepost] = usePostRepostMutationQueue(
     post,
     viaRepost,
+    feedDescriptor,
     logContext,
   )
   const requireAuth = useRequireAuth()
diff --git a/src/logger/metrics.ts b/src/logger/metrics.ts
index dfb8cd541..cfd77c5a1 100644
--- a/src/logger/metrics.ts
+++ b/src/logger/metrics.ts
@@ -130,6 +130,27 @@ export type MetricEvents = {
     feedType: string
     reason: 'pull-to-refresh' | 'soft-reset' | 'load-latest'
   }
+  'feed:save': {
+    feedUrl: string
+  }
+  'feed:unsave': {
+    feedUrl: string
+  }
+  'feed:pin': {
+    feedUrl: string
+  }
+  'feed:unpin': {
+    feedUrl: string
+  }
+  'feed:like': {
+    feedUrl: string
+  }
+  'feed:unlike': {
+    feedUrl: string
+  }
+  'feed:share': {
+    feedUrl: string
+  }
   'discover:showMore': {
     feedContext: string
   }
@@ -175,15 +196,19 @@ export type MetricEvents = {
     likerClout: number | undefined
     postClout: number | undefined
     logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo'
+    feedDescriptor?: string
   }
   'post:repost': {
     logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo'
+    feedDescriptor?: string
   }
   'post:unlike': {
     logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo'
+    feedDescriptor?: string
   }
   'post:unrepost': {
     logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo'
+    feedDescriptor?: string
   }
   'post:mute': {}
   'post:unmute': {}
diff --git a/src/screens/Profile/components/ProfileFeedHeader.tsx b/src/screens/Profile/components/ProfileFeedHeader.tsx
index 26fa08fdb..5bc05ec56 100644
--- a/src/screens/Profile/components/ProfileFeedHeader.tsx
+++ b/src/screens/Profile/components/ProfileFeedHeader.tsx
@@ -113,13 +113,14 @@ export function ProfileFeedHeader({info}: {info: FeedSourceFeedInfo}) {
   const isSaved = Boolean(savedFeedConfig)
   const isPinned = Boolean(savedFeedConfig?.pinned)
 
-  const onToggleSaved = React.useCallback(async () => {
+  const onToggleSaved = async () => {
     try {
       playHaptic()
 
       if (savedFeedConfig) {
         await removeFeed(savedFeedConfig)
         Toast.show(_(msg`Removed from your feeds`))
+        logger.metric('feed:unsave', {feedUrl: info.uri})
       } else {
         await addSavedFeeds([
           {
@@ -129,6 +130,7 @@ export function ProfileFeedHeader({info}: {info: FeedSourceFeedInfo}) {
           },
         ])
         Toast.show(_(msg`Saved to your feeds`))
+        logger.metric('feed:save', {feedUrl: info.uri})
       }
     } catch (err) {
       Toast.show(
@@ -139,9 +141,9 @@ export function ProfileFeedHeader({info}: {info: FeedSourceFeedInfo}) {
       )
       logger.error('Failed to update feeds', {message: err})
     }
-  }, [_, playHaptic, info, removeFeed, addSavedFeeds, savedFeedConfig])
+  }
 
-  const onTogglePinned = React.useCallback(async () => {
+  const onTogglePinned = async () => {
     try {
       playHaptic()
 
@@ -156,8 +158,10 @@ export function ProfileFeedHeader({info}: {info: FeedSourceFeedInfo}) {
 
         if (pinned) {
           Toast.show(_(msg`Pinned ${info.displayName} to Home`))
+          logger.metric('feed:pin', {feedUrl: info.uri})
         } else {
           Toast.show(_(msg`Unpinned ${info.displayName} from Home`))
+          logger.metric('feed:unpin', {feedUrl: info.uri})
         }
       } else {
         await addSavedFeeds([
@@ -168,12 +172,13 @@ export function ProfileFeedHeader({info}: {info: FeedSourceFeedInfo}) {
           },
         ])
         Toast.show(_(msg`Pinned ${info.displayName} to Home`))
+        logger.metric('feed:pin', {feedUrl: info.uri})
       }
     } catch (e) {
       Toast.show(_(msg`There was an issue contacting the server`), 'xmark')
       logger.error('Failed to toggle pinned feed', {message: e})
     }
-  }, [playHaptic, info, _, savedFeedConfig, updateSavedFeeds, addSavedFeeds])
+  }
 
   return (
     <>
@@ -394,16 +399,18 @@ function DialogInner({
   const isLiked = !!likeUri
   const feedRkey = React.useMemo(() => new AtUri(info.uri).rkey, [info.uri])
 
-  const onToggleLiked = React.useCallback(async () => {
+  const onToggleLiked = async () => {
     try {
       playHaptic()
 
       if (isLiked && likeUri) {
         await unlikeFeed({uri: likeUri})
         setLikeUri('')
+        logger.metric('feed:unlike', {feedUrl: info.uri})
       } else {
         const res = await likeFeed({uri: info.uri, cid: info.cid})
         setLikeUri(res.uri)
+        logger.metric('feed:like', {feedUrl: info.uri})
       }
     } catch (err) {
       Toast.show(
@@ -414,12 +421,13 @@ function DialogInner({
       )
       logger.error('Failed to toggle like', {message: err})
     }
-  }, [playHaptic, isLiked, likeUri, unlikeFeed, setLikeUri, likeFeed, info, _])
+  }
 
   const onPressShare = React.useCallback(() => {
     playHaptic()
     const url = toShareUrl(info.route.href)
     shareUrl(url)
+    logger.metric('feed:share', {feedUrl: info.uri})
   }, [info, playHaptic])
 
   const onPressReport = React.useCallback(() => {
diff --git a/src/screens/VideoFeed/index.tsx b/src/screens/VideoFeed/index.tsx
index 21eb53baf..8a75751f7 100644
--- a/src/screens/VideoFeed/index.tsx
+++ b/src/screens/VideoFeed/index.tsx
@@ -1027,6 +1027,7 @@ function PlayPauseTapArea({
   const [queueLike] = usePostLikeMutationQueue(
     post,
     undefined,
+    undefined,
     'ImmersiveVideo',
   )
   const {sendInteraction} = useFeedFeedbackContext()
diff --git a/src/state/queries/post.ts b/src/state/queries/post.ts
index 4700a7fdc..e92847e75 100644
--- a/src/state/queries/post.ts
+++ b/src/state/queries/post.ts
@@ -3,7 +3,8 @@ import {type AppBskyActorDefs, type AppBskyFeedDefs, AtUri} from '@atproto/api'
 import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
 
 import {useToggleMutationQueue} from '#/lib/hooks/useToggleMutationQueue'
-import {logEvent, type LogEvents, toClout} from '#/lib/statsig/statsig'
+import {type LogEvents, toClout} from '#/lib/statsig/statsig'
+import {logger} from '#/logger'
 import {updatePostShadow} from '#/state/cache/post-shadow'
 import {type Shadow} from '#/state/cache/types'
 import {useAgent, useSession} from '#/state/session'
@@ -99,6 +100,7 @@ export function useGetPosts() {
 export function usePostLikeMutationQueue(
   post: Shadow<AppBskyFeedDefs.PostView>,
   viaRepost: {uri: string; cid: string} | undefined,
+  feedDescriptor: string | undefined,
   logContext: LogEvents['post:like']['logContext'] &
     LogEvents['post:unlike']['logContext'],
 ) {
@@ -106,8 +108,8 @@ export function usePostLikeMutationQueue(
   const postUri = post.uri
   const postCid = post.cid
   const initialLikeUri = post.viewer?.like
-  const likeMutation = usePostLikeMutation(logContext, post)
-  const unlikeMutation = usePostUnlikeMutation(logContext)
+  const likeMutation = usePostLikeMutation(feedDescriptor, logContext, post)
+  const unlikeMutation = usePostUnlikeMutation(feedDescriptor, logContext)
 
   const queueToggle = useToggleMutationQueue({
     initialState: initialLikeUri,
@@ -159,6 +161,7 @@ export function usePostLikeMutationQueue(
 }
 
 function usePostLikeMutation(
+  feedDescriptor: string | undefined,
   logContext: LogEvents['post:like']['logContext'],
   post: Shadow<AppBskyFeedDefs.PostView>,
 ) {
@@ -176,7 +179,7 @@ function usePostLikeMutation(
       if (currentAccount) {
         ownProfile = findProfileQueryData(queryClient, currentAccount.did)
       }
-      logEvent('post:like', {
+      logger.metric('post:like', {
         logContext,
         doesPosterFollowLiker: postAuthor.viewer
           ? Boolean(postAuthor.viewer.followedBy)
@@ -191,6 +194,7 @@ function usePostLikeMutation(
           post.replyCount != null
             ? toClout(post.likeCount + post.repostCount + post.replyCount)
             : undefined,
+        feedDescriptor: feedDescriptor,
       })
       return agent.like(uri, cid, via)
     },
@@ -198,12 +202,13 @@ function usePostLikeMutation(
 }
 
 function usePostUnlikeMutation(
+  feedDescriptor: string | undefined,
   logContext: LogEvents['post:unlike']['logContext'],
 ) {
   const agent = useAgent()
   return useMutation<void, Error, {postUri: string; likeUri: string}>({
     mutationFn: ({likeUri}) => {
-      logEvent('post:unlike', {logContext})
+      logger.metric('post:unlike', {logContext, feedDescriptor})
       return agent.deleteLike(likeUri)
     },
   })
@@ -212,6 +217,7 @@ function usePostUnlikeMutation(
 export function usePostRepostMutationQueue(
   post: Shadow<AppBskyFeedDefs.PostView>,
   viaRepost: {uri: string; cid: string} | undefined,
+  feedDescriptor: string | undefined,
   logContext: LogEvents['post:repost']['logContext'] &
     LogEvents['post:unrepost']['logContext'],
 ) {
@@ -219,8 +225,8 @@ export function usePostRepostMutationQueue(
   const postUri = post.uri
   const postCid = post.cid
   const initialRepostUri = post.viewer?.repost
-  const repostMutation = usePostRepostMutation(logContext)
-  const unrepostMutation = usePostUnrepostMutation(logContext)
+  const repostMutation = usePostRepostMutation(feedDescriptor, logContext)
+  const unrepostMutation = usePostUnrepostMutation(feedDescriptor, logContext)
 
   const queueToggle = useToggleMutationQueue({
     initialState: initialRepostUri,
@@ -270,6 +276,7 @@ export function usePostRepostMutationQueue(
 }
 
 function usePostRepostMutation(
+  feedDescriptor: string | undefined,
   logContext: LogEvents['post:repost']['logContext'],
 ) {
   const agent = useAgent()
@@ -279,19 +286,20 @@ function usePostRepostMutation(
     {uri: string; cid: string; via?: {uri: string; cid: string}} // the post's uri and cid, and the repost uri/cid if present
   >({
     mutationFn: ({uri, cid, via}) => {
-      logEvent('post:repost', {logContext})
+      logger.metric('post:repost', {logContext, feedDescriptor})
       return agent.repost(uri, cid, via)
     },
   })
 }
 
 function usePostUnrepostMutation(
+  feedDescriptor: string | undefined,
   logContext: LogEvents['post:unrepost']['logContext'],
 ) {
   const agent = useAgent()
   return useMutation<void, Error, {postUri: string; repostUri: string}>({
     mutationFn: ({repostUri}) => {
-      logEvent('post:unrepost', {logContext})
+      logger.metric('post:unrepost', {logContext, feedDescriptor})
       return agent.deleteRepost(repostUri)
     },
   })
@@ -363,7 +371,7 @@ function useThreadMuteMutation() {
     {uri: string} // the root post's uri
   >({
     mutationFn: ({uri}) => {
-      logEvent('post:mute', {})
+      logger.metric('post:mute', {})
       return agent.api.app.bsky.graph.muteThread({root: uri})
     },
   })
@@ -373,7 +381,7 @@ function useThreadUnmuteMutation() {
   const agent = useAgent()
   return useMutation<{}, Error, {uri: string}>({
     mutationFn: ({uri}) => {
-      logEvent('post:unmute', {})
+      logger.metric('post:unmute', {})
       return agent.api.app.bsky.graph.unmuteThread({root: uri})
     },
   })