diff options
-rw-r--r-- | src/components/PostControls/index.tsx | 3 | ||||
-rw-r--r-- | src/logger/metrics.ts | 25 | ||||
-rw-r--r-- | src/screens/Profile/components/ProfileFeedHeader.tsx | 20 | ||||
-rw-r--r-- | src/screens/VideoFeed/index.tsx | 1 | ||||
-rw-r--r-- | src/state/queries/post.ts | 30 |
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}) }, }) |