Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/components/PostControls/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
25 changes: 25 additions & 0 deletions src/logger/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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': {}
Expand Down
20 changes: 14 additions & 6 deletions src/screens/Profile/components/ProfileFeedHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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([
{
Expand All @@ -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(
Expand All @@ -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()

Expand All @@ -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([
Expand All @@ -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 (
<>
Expand Down Expand Up @@ -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(
Expand All @@ -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(() => {
Expand Down
1 change: 1 addition & 0 deletions src/screens/VideoFeed/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1027,6 +1027,7 @@ function PlayPauseTapArea({
const [queueLike] = usePostLikeMutationQueue(
post,
undefined,
undefined,
'ImmersiveVideo',
)
const {sendInteraction} = useFeedFeedbackContext()
Expand Down
30 changes: 19 additions & 11 deletions src/state/queries/post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -99,15 +100,16 @@ 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'],
) {
const queryClient = useQueryClient()
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,
Expand Down Expand Up @@ -159,6 +161,7 @@ export function usePostLikeMutationQueue(
}

function usePostLikeMutation(
feedDescriptor: string | undefined,
logContext: LogEvents['post:like']['logContext'],
post: Shadow<AppBskyFeedDefs.PostView>,
) {
Expand All @@ -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)
Expand All @@ -191,19 +194,21 @@ function usePostLikeMutation(
post.replyCount != null
? toClout(post.likeCount + post.repostCount + post.replyCount)
: undefined,
feedDescriptor: feedDescriptor,
})
return agent.like(uri, cid, via)
},
})
}

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)
},
})
Expand All @@ -212,15 +217,16 @@ 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'],
) {
const queryClient = useQueryClient()
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,
Expand Down Expand Up @@ -270,6 +276,7 @@ export function usePostRepostMutationQueue(
}

function usePostRepostMutation(
feedDescriptor: string | undefined,
logContext: LogEvents['post:repost']['logContext'],
) {
const agent = useAgent()
Expand All @@ -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})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We good with no longer sending this data to statsig? statsig is now opt-in for logger.metric

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is that actually how this works? logEvent is deprecated, and i was under the impression logger.metric was how we do it now (with an option to disable sending to statsig). we want everything to be going to statsig, and we are using logger.metric a lot now, so we'll need to definitely change that if this is the case

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
},
})
Expand Down Expand Up @@ -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})
},
})
Expand All @@ -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})
},
})
Expand Down
Loading