Skip to content

Commit

Permalink
Merge branch 'main' into hailey/expo-updates
Browse files Browse the repository at this point in the history
  • Loading branch information
haileyok committed Mar 14, 2024
2 parents 3a34108 + 1c25c76 commit 85c676f
Show file tree
Hide file tree
Showing 17 changed files with 163 additions and 31 deletions.
44 changes: 43 additions & 1 deletion src/lib/statsig/events.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,47 @@
export type Events = {
export type LogEvents = {
init: {
initMs: number
}
'feed:endReached': {
feedType: string
itemCount: number
}
'post:create': {
imageCount: number
isReply: boolean
hasLink: boolean
hasQuote: boolean
langs: string
logContext: 'Composer'
}
'post:like': {
logContext: 'FeedItem' | 'PostThreadItem' | 'Post'
}
'post:repost': {
logContext: 'FeedItem' | 'PostThreadItem' | 'Post'
}
'post:unlike': {
logContext: 'FeedItem' | 'PostThreadItem' | 'Post'
}
'post:unrepost': {
logContext: 'FeedItem' | 'PostThreadItem' | 'Post'
}
'profile:follow': {
logContext:
| 'RecommendedFollowsItem'
| 'PostThreadItem'
| 'ProfileCard'
| 'ProfileHeader'
| 'ProfileHeaderSuggestedFollows'
| 'ProfileMenu'
}
'profile:unfollow': {
logContext:
| 'RecommendedFollowsItem'
| 'PostThreadItem'
| 'ProfileCard'
| 'ProfileHeader'
| 'ProfileHeaderSuggestedFollows'
| 'ProfileMenu'
}
}
8 changes: 5 additions & 3 deletions src/lib/statsig/statsig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import {
} from 'statsig-react-native-expo'
import {useSession} from '../../state/session'
import {sha256} from 'js-sha256'
import {Events} from './events'
import {LogEvents} from './events'

export type {LogEvents}

const statsigOptions = {
environment: {
Expand All @@ -31,9 +33,9 @@ export function attachRouteToLogEvents(
getCurrentRouteName = getRouteName
}

export function logEvent<E extends keyof Events>(
export function logEvent<E extends keyof LogEvents>(
eventName: E & string,
rawMetadata?: Events[E] & FlatJSONRecord,
rawMetadata: LogEvents[E] & FlatJSONRecord,
) {
const fullMetadata = {
...rawMetadata,
Expand Down
47 changes: 35 additions & 12 deletions src/state/queries/post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {Shadow} from '#/state/cache/types'
import {getAgent} from '#/state/session'
import {updatePostShadow} from '#/state/cache/post-shadow'
import {track} from '#/lib/analytics/analytics'
import {logEvent, LogEvents} from '#/lib/statsig/statsig'
import {useToggleMutationQueue} from '#/lib/hooks/useToggleMutationQueue'

export const RQKEY = (postUri: string) => ['post', postUri]
Expand Down Expand Up @@ -58,12 +59,14 @@ export function useGetPost() {

export function usePostLikeMutationQueue(
post: Shadow<AppBskyFeedDefs.PostView>,
logContext: LogEvents['post:like']['logContext'] &
LogEvents['post:unlike']['logContext'],
) {
const postUri = post.uri
const postCid = post.cid
const initialLikeUri = post.viewer?.like
const likeMutation = usePostLikeMutation()
const unlikeMutation = usePostUnlikeMutation()
const likeMutation = usePostLikeMutation(logContext)
const unlikeMutation = usePostUnlikeMutation(logContext)

const queueToggle = useToggleMutationQueue({
initialState: initialLikeUri,
Expand Down Expand Up @@ -111,22 +114,30 @@ export function usePostLikeMutationQueue(
return [queueLike, queueUnlike]
}

function usePostLikeMutation() {
function usePostLikeMutation(logContext: LogEvents['post:like']['logContext']) {
return useMutation<
{uri: string}, // responds with the uri of the like
Error,
{uri: string; cid: string} // the post's uri and cid
>({
mutationFn: post => getAgent().like(post.uri, post.cid),
mutationFn: post => {
logEvent('post:like', {logContext})
return getAgent().like(post.uri, post.cid)
},
onSuccess() {
track('Post:Like')
},
})
}

function usePostUnlikeMutation() {
function usePostUnlikeMutation(
logContext: LogEvents['post:unlike']['logContext'],
) {
return useMutation<void, Error, {postUri: string; likeUri: string}>({
mutationFn: ({likeUri}) => getAgent().deleteLike(likeUri),
mutationFn: ({likeUri}) => {
logEvent('post:unlike', {logContext})
return getAgent().deleteLike(likeUri)
},
onSuccess() {
track('Post:Unlike')
},
Expand All @@ -135,12 +146,14 @@ function usePostUnlikeMutation() {

export function usePostRepostMutationQueue(
post: Shadow<AppBskyFeedDefs.PostView>,
logContext: LogEvents['post:repost']['logContext'] &
LogEvents['post:unrepost']['logContext'],
) {
const postUri = post.uri
const postCid = post.cid
const initialRepostUri = post.viewer?.repost
const repostMutation = usePostRepostMutation()
const unrepostMutation = usePostUnrepostMutation()
const repostMutation = usePostRepostMutation(logContext)
const unrepostMutation = usePostUnrepostMutation(logContext)

const queueToggle = useToggleMutationQueue({
initialState: initialRepostUri,
Expand Down Expand Up @@ -188,22 +201,32 @@ export function usePostRepostMutationQueue(
return [queueRepost, queueUnrepost]
}

function usePostRepostMutation() {
function usePostRepostMutation(
logContext: LogEvents['post:repost']['logContext'],
) {
return useMutation<
{uri: string}, // responds with the uri of the repost
Error,
{uri: string; cid: string} // the post's uri and cid
>({
mutationFn: post => getAgent().repost(post.uri, post.cid),
mutationFn: post => {
logEvent('post:repost', {logContext})
return getAgent().repost(post.uri, post.cid)
},
onSuccess() {
track('Post:Repost')
},
})
}

function usePostUnrepostMutation() {
function usePostUnrepostMutation(
logContext: LogEvents['post:unrepost']['logContext'],
) {
return useMutation<void, Error, {postUri: string; repostUri: string}>({
mutationFn: ({repostUri}) => getAgent().deleteRepost(repostUri),
mutationFn: ({repostUri}) => {
logEvent('post:unrepost', {logContext})
return getAgent().deleteRepost(repostUri)
},
onSuccess() {
track('Post:Unrepost')
},
Expand Down
17 changes: 13 additions & 4 deletions src/state/queries/profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {RQKEY as RQKEY_MY_MUTED} from './my-muted-accounts'
import {RQKEY as RQKEY_MY_BLOCKED} from './my-blocked-accounts'
import {STALE} from '#/state/queries'
import {track} from '#/lib/analytics/analytics'
import {logEvent, LogEvents} from '#/lib/statsig/statsig'
import {ThreadNode} from './post-thread'

export const RQKEY = (did: string) => ['profile', did]
Expand Down Expand Up @@ -186,11 +187,13 @@ export function useProfileUpdateMutation() {

export function useProfileFollowMutationQueue(
profile: Shadow<AppBskyActorDefs.ProfileViewDetailed>,
logContext: LogEvents['profile:follow']['logContext'] &
LogEvents['profile:unfollow']['logContext'],
) {
const did = profile.did
const initialFollowingUri = profile.viewer?.following
const followMutation = useProfileFollowMutation()
const unfollowMutation = useProfileUnfollowMutation()
const followMutation = useProfileFollowMutation(logContext)
const unfollowMutation = useProfileUnfollowMutation(logContext)

const queueToggle = useToggleMutationQueue({
initialState: initialFollowingUri,
Expand Down Expand Up @@ -237,9 +240,12 @@ export function useProfileFollowMutationQueue(
return [queueFollow, queueUnfollow]
}

function useProfileFollowMutation() {
function useProfileFollowMutation(
logContext: LogEvents['profile:follow']['logContext'],
) {
return useMutation<{uri: string; cid: string}, Error, {did: string}>({
mutationFn: async ({did}) => {
logEvent('profile:follow', {logContext})
return await getAgent().follow(did)
},
onSuccess(data, variables) {
Expand All @@ -248,9 +254,12 @@ function useProfileFollowMutation() {
})
}

function useProfileUnfollowMutation() {
function useProfileUnfollowMutation(
logContext: LogEvents['profile:unfollow']['logContext'],
) {
return useMutation<void, Error, {did: string; followUri: string}>({
mutationFn: async ({followUri}) => {
logEvent('profile:unfollow', {logContext})
track('Profile:Unfollow', {username: followUri})
return await getAgent().deleteFollow(followUri)
},
Expand Down
7 changes: 5 additions & 2 deletions src/view/com/auth/onboarding/RecommendedFollowsItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function RecommendedFollowsItem({
)
}

export function ProfileCard({
function ProfileCard({
profile,
onFollowStateChange,
moderation,
Expand All @@ -72,7 +72,10 @@ export function ProfileCard({
const pal = usePalette('default')
const [addingMoreSuggestions, setAddingMoreSuggestions] =
React.useState(false)
const [queueFollow, queueUnfollow] = useProfileFollowMutationQueue(profile)
const [queueFollow, queueUnfollow] = useProfileFollowMutationQueue(
profile,
'RecommendedFollowsItem',
)

const onToggleFollow = React.useCallback(async () => {
try {
Expand Down
11 changes: 11 additions & 0 deletions src/view/com/composer/Composer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import {logger} from '#/logger'
import {ComposerReplyTo} from 'view/com/composer/ComposerReplyTo'
import * as Prompt from '#/components/Prompt'
import {useDialogStateControlContext} from 'state/dialogs'
import {logEvent} from '#/lib/statsig/statsig'

type Props = ComposerOpts
export const ComposePost = observer(function ComposePost({
Expand Down Expand Up @@ -255,6 +256,16 @@ export const ComposePost = observer(function ComposePost({
setIsProcessing(false)
return
} finally {
if (postUri) {
logEvent('post:create', {
imageCount: gallery.size,
isReply: replyTo != null,
hasLink: extLink != null,
hasQuote: quote != null,
langs: langPrefs.postLanguage,
logContext: 'Composer',
})
}
track('Create Post', {
imageCount: gallery.size,
})
Expand Down
5 changes: 4 additions & 1 deletion src/view/com/post-thread/PostThreadFollowBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ function PostThreadFollowBtnLoaded({
const {isTabletOrDesktop} = useWebMediaQueries()
const profile: Shadow<AppBskyActorDefs.ProfileViewBasic> =
useProfileShadow(profileUnshadowed)
const [queueFollow, queueUnfollow] = useProfileFollowMutationQueue(profile)
const [queueFollow, queueUnfollow] = useProfileFollowMutationQueue(
profile,
'PostThreadItem',
)
const requireAuth = useRequireAuth()

const isFollowing = !!profile.viewer?.following
Expand Down
2 changes: 2 additions & 0 deletions src/view/com/post-thread/PostThreadItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ let PostThreadItemLoaded = ({
record={record}
richText={richText}
onPressReply={onPressReply}
logContext="PostThreadItem"
/>
</View>
</View>
Expand Down Expand Up @@ -560,6 +561,7 @@ let PostThreadItemLoaded = ({
record={record}
richText={richText}
onPressReply={onPressReply}
logContext="PostThreadItem"
/>
</View>
</View>
Expand Down
1 change: 1 addition & 0 deletions src/view/com/post/Post.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ function PostInner({
record={record}
richText={richText}
onPressReply={onPressReply}
logContext="Post"
/>
</View>
</View>
Expand Down
16 changes: 15 additions & 1 deletion src/view/com/posts/Feed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {useLingui} from '@lingui/react'
import {DiscoverFallbackHeader} from './DiscoverFallbackHeader'
import {FALLBACK_MARKER_POST} from '#/lib/api/feed/home'
import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender'
import {logEvent} from '#/lib/statsig/statsig'

const LOADING_ITEM = {_reactKey: '__loading__'}
const EMPTY_FEED_ITEM = {_reactKey: '__empty__'}
Expand Down Expand Up @@ -223,16 +224,29 @@ let Feed = ({
setIsPTRing(false)
}, [refetch, track, setIsPTRing, onHasNew])

const feedType = feed.split('|')[0]
const onEndReached = React.useCallback(async () => {
if (isFetching || !hasNextPage || isError) return

logEvent('feed:endReached', {
feedType: feedType,
itemCount: feedItems.length,
})
track('Feed:onEndReached')
try {
await fetchNextPage()
} catch (err) {
logger.error('Failed to load more posts', {message: err})
}
}, [isFetching, hasNextPage, isError, fetchNextPage, track])
}, [
isFetching,
hasNextPage,
isError,
fetchNextPage,
track,
feedType,
feedItems.length,
])

const onPressTryAgain = React.useCallback(() => {
refetch()
Expand Down
1 change: 1 addition & 0 deletions src/view/com/posts/FeedItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ let FeedItemInner = ({
showAppealLabelItem={
post.author.did === currentAccount?.did && isModeratedPost
}
logContext="FeedItem"
/>
</View>
</View>
Expand Down
7 changes: 6 additions & 1 deletion src/view/com/profile/FollowButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,18 @@ export function FollowButton({
followedType = 'default',
profile,
labelStyle,
logContext,
}: {
unfollowedType?: ButtonType
followedType?: ButtonType
profile: Shadow<AppBskyActorDefs.ProfileViewBasic>
labelStyle?: StyleProp<TextStyle>
logContext: 'ProfileCard'
}) {
const [queueFollow, queueUnfollow] = useProfileFollowMutationQueue(profile)
const [queueFollow, queueUnfollow] = useProfileFollowMutationQueue(
profile,
logContext,
)
const {_} = useLingui()

const onPressFollow = async () => {
Expand Down
4 changes: 3 additions & 1 deletion src/view/com/profile/ProfileCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,9 @@ export function ProfileCardWithFollowBtn({
renderButton={
isMe
? undefined
: profileShadow => <FollowButton profile={profileShadow} />
: profileShadow => (
<FollowButton profile={profileShadow} logContext="ProfileCard" />
)
}
/>
)
Expand Down
Loading

0 comments on commit 85c676f

Please sign in to comment.