[APP-1782] Migrate to new analytics APIs (#9735)
* Migrate logEvent to useAnalytics * Migrate logger.metric to useAnalytics * Migrate tricky spot, fix types * Migrate remaining tricky spot * Missed one * Remove metric() from logger * Migrate useGate to useAnalytics * Remove all other StatSig mentions * Update event payload * Update logger tests * Mock expo method
This commit is contained in:
@@ -5,7 +5,6 @@ import {msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {PressableScale} from '#/lib/custom-animations/PressableScale'
|
||||
import {logEvent} from '#/lib/statsig/statsig'
|
||||
import {
|
||||
useLoggedOutView,
|
||||
useLoggedOutViewControls,
|
||||
@@ -18,6 +17,7 @@ import {LandingScreen} from '#/screens/StarterPack/StarterPackLandingScreen'
|
||||
import {atoms as a, native, tokens, useTheme} from '#/alf'
|
||||
import {Button, ButtonIcon} from '#/components/Button'
|
||||
import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Times'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {SplashScreen} from './SplashScreen'
|
||||
|
||||
enum ScreenState {
|
||||
@@ -30,6 +30,7 @@ export {ScreenState as LoggedOutScreenState}
|
||||
|
||||
export function LoggedOut({onDismiss}: {onDismiss?: () => void}) {
|
||||
const {_} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const t = useTheme()
|
||||
const insets = useSafeAreaInsets()
|
||||
const setMinimalShellMode = useSetMinimalShellMode()
|
||||
@@ -94,11 +95,11 @@ export function LoggedOut({onDismiss}: {onDismiss?: () => void}) {
|
||||
<SplashScreen
|
||||
onPressSignin={() => {
|
||||
setScreenState(ScreenState.S_Login)
|
||||
logEvent('splash:signInPressed', {})
|
||||
ax.metric('splash:signInPressed', {})
|
||||
}}
|
||||
onPressCreateAccount={() => {
|
||||
setScreenState(ScreenState.S_CreateAccount)
|
||||
logEvent('splash:createAccountPressed', {})
|
||||
ax.metric('splash:createAccountPressed', {})
|
||||
}}
|
||||
/>
|
||||
) : undefined}
|
||||
|
||||
@@ -72,7 +72,6 @@ import {usePalette} from '#/lib/hooks/usePalette'
|
||||
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
|
||||
import {mimeToExt} from '#/lib/media/video/util'
|
||||
import {type NavigationProp} from '#/lib/routes/types'
|
||||
import {logEvent} from '#/lib/statsig/statsig'
|
||||
import {cleanError} from '#/lib/strings/errors'
|
||||
import {colors} from '#/lib/styles'
|
||||
import {logger} from '#/logger'
|
||||
@@ -129,6 +128,7 @@ import {LazyQuoteEmbed} from '#/components/Post/Embed/LazyQuoteEmbed'
|
||||
import * as Prompt from '#/components/Prompt'
|
||||
import * as Toast from '#/components/Toast'
|
||||
import {Text as NewText} from '#/components/Typography'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {IS_ANDROID, IS_IOS, IS_NATIVE, IS_WEB} from '#/env'
|
||||
import {BottomSheetPortalProvider} from '../../../../modules/bottom-sheet'
|
||||
import {PostLanguageSelect} from './select-language/PostLanguageSelect'
|
||||
@@ -178,6 +178,7 @@ export const ComposePost = ({
|
||||
cancelRef?: React.RefObject<CancelRef | null>
|
||||
}) => {
|
||||
const {currentAccount} = useSession()
|
||||
const ax = useAnalytics()
|
||||
const agent = useAgent()
|
||||
const queryClient = useQueryClient()
|
||||
const currentDid = currentAccount!.did
|
||||
@@ -520,7 +521,7 @@ export const ComposePost = ({
|
||||
if (postUri) {
|
||||
let index = 0
|
||||
for (let post of thread.posts) {
|
||||
logEvent('post:create', {
|
||||
ax.metric('post:create', {
|
||||
imageCount:
|
||||
post.embed.media?.type === 'images'
|
||||
? post.embed.media.images.length
|
||||
@@ -536,7 +537,7 @@ export const ComposePost = ({
|
||||
}
|
||||
}
|
||||
if (thread.posts.length > 1) {
|
||||
logEvent('thread:create', {
|
||||
ax.metric('thread:create', {
|
||||
postCount: thread.posts.length,
|
||||
isReply: !!replyTo,
|
||||
})
|
||||
@@ -594,6 +595,7 @@ export const ComposePost = ({
|
||||
}, 500)
|
||||
}, [
|
||||
_,
|
||||
ax,
|
||||
agent,
|
||||
thread,
|
||||
canPost,
|
||||
|
||||
@@ -3,12 +3,12 @@ import {Keyboard} from 'react-native'
|
||||
import {msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {logEvent} from '#/lib/statsig/statsig'
|
||||
import {type Gif} from '#/state/queries/tenor'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Button} from '#/components/Button'
|
||||
import {GifSelectDialog} from '#/components/dialogs/GifSelect'
|
||||
import {GifSquare_Stroke2_Corner0_Rounded as GifIcon} from '#/components/icons/Gif'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
|
||||
type Props = {
|
||||
onClose?: () => void
|
||||
@@ -17,15 +17,16 @@ type Props = {
|
||||
}
|
||||
|
||||
export function SelectGifBtn({onClose, onSelectGif, disabled}: Props) {
|
||||
const ax = useAnalytics()
|
||||
const {_} = useLingui()
|
||||
const ref = useRef<{open: () => void}>(null)
|
||||
const t = useTheme()
|
||||
|
||||
const onPressSelectGif = useCallback(async () => {
|
||||
logEvent('composer:gif:open', {})
|
||||
ax.metric('composer:gif:open', {})
|
||||
Keyboard.dismiss()
|
||||
ref.current?.open()
|
||||
}, [])
|
||||
}, [ax])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -24,6 +24,7 @@ import {Earth_Stroke2_Corner0_Rounded as EarthIcon} from '#/components/icons/Glo
|
||||
import {Group3_Stroke2_Corner0_Rounded as GroupIcon} from '#/components/icons/Group'
|
||||
import * as Tooltip from '#/components/Tooltip'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {IS_NATIVE} from '#/env'
|
||||
import {useThreadgateNudged} from '#/storage/hooks/threadgate-nudged'
|
||||
|
||||
@@ -42,6 +43,7 @@ export function ThreadgateBtn({
|
||||
style?: StyleProp<AnimatedStyle<ViewStyle>>
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const control = Dialog.useDialogControl()
|
||||
const [threadgateNudged, setThreadgateNudged] = useThreadgateNudged()
|
||||
const [showTooltip, setShowTooltip] = useState(false)
|
||||
@@ -66,7 +68,7 @@ export function ThreadgateBtn({
|
||||
const [persist, setPersist] = useState(false)
|
||||
|
||||
const onPress = () => {
|
||||
logger.metric('composer:threadgate:open', {
|
||||
ax.metric('composer:threadgate:open', {
|
||||
nudged: tooltipWasShown,
|
||||
})
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
useVideoLibraryPermission,
|
||||
} from '#/lib/hooks/usePermissions'
|
||||
import {openCamera, openUnifiedPicker} from '#/lib/media/picker'
|
||||
import {logger} from '#/logger'
|
||||
import {useCurrentAccountProfile} from '#/state/queries/useCurrentAccountProfile'
|
||||
import {MAX_IMAGES} from '#/view/com/composer/state/composer'
|
||||
import {UserAvatar} from '#/view/com/util/UserAvatar'
|
||||
@@ -21,11 +20,13 @@ import {Camera_Stroke2_Corner0_Rounded as CameraIcon} from '#/components/icons/C
|
||||
import {Image_Stroke2_Corner0_Rounded as ImageIcon} from '#/components/icons/Image'
|
||||
import {SubtleHover} from '#/components/SubtleHover'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {IS_NATIVE} from '#/env'
|
||||
|
||||
export function ComposerPrompt() {
|
||||
const {_} = useLingui()
|
||||
const t = useTheme()
|
||||
const ax = useAnalytics()
|
||||
const {_} = useLingui()
|
||||
const {openComposer} = useOpenComposer()
|
||||
const profile = useCurrentAccountProfile()
|
||||
const [hover, setHover] = useState(false)
|
||||
@@ -35,12 +36,12 @@ export function ComposerPrompt() {
|
||||
const sheetWrapper = useSheetWrapper()
|
||||
|
||||
const onPress = useCallback(() => {
|
||||
logger.metric('composerPrompt:press', {})
|
||||
ax.metric('composerPrompt:press', {})
|
||||
openComposer({})
|
||||
}, [openComposer])
|
||||
}, [ax, openComposer])
|
||||
|
||||
const onPressImage = useCallback(async () => {
|
||||
logger.metric('composerPrompt:gallery:press', {})
|
||||
ax.metric('composerPrompt:gallery:press', {})
|
||||
|
||||
// On web, open the composer with the gallery picker auto-opening
|
||||
if (!IS_NATIVE) {
|
||||
@@ -87,10 +88,11 @@ export function ComposerPrompt() {
|
||||
}
|
||||
} catch (err: any) {
|
||||
if (!String(err).toLowerCase().includes('cancel')) {
|
||||
logger.warn('Error opening image picker', {error: err})
|
||||
ax.logger.error('Error opening image picker', {error: err})
|
||||
}
|
||||
}
|
||||
}, [
|
||||
ax,
|
||||
openComposer,
|
||||
requestPhotoAccessIfNeeded,
|
||||
requestVideoAccessIfNeeded,
|
||||
@@ -98,7 +100,7 @@ export function ComposerPrompt() {
|
||||
])
|
||||
|
||||
const onPressCamera = useCallback(async () => {
|
||||
logger.metric('composerPrompt:camera:press', {})
|
||||
ax.metric('composerPrompt:camera:press', {})
|
||||
|
||||
try {
|
||||
if (!(await requestCameraAccessIfNeeded())) {
|
||||
@@ -126,10 +128,10 @@ export function ComposerPrompt() {
|
||||
})
|
||||
} catch (err: any) {
|
||||
if (!String(err).toLowerCase().includes('cancel')) {
|
||||
logger.warn('Error opening camera', {error: err})
|
||||
ax.logger.error('Error opening camera', {error: err})
|
||||
}
|
||||
}
|
||||
}, [openComposer, requestCameraAccessIfNeeded])
|
||||
}, [ax, openComposer, requestCameraAccessIfNeeded])
|
||||
|
||||
if (!profile) {
|
||||
return null
|
||||
|
||||
@@ -18,7 +18,6 @@ import {useOpenComposer} from '#/lib/hooks/useOpenComposer'
|
||||
import {ComposeIcon2} from '#/lib/icons'
|
||||
import {getRootNavigation, getTabState, TabState} from '#/lib/routes/helpers'
|
||||
import {type AllNavigatorParams} from '#/lib/routes/types'
|
||||
import {logEvent} from '#/lib/statsig/statsig'
|
||||
import {s} from '#/lib/styles'
|
||||
import {listenSoftReset} from '#/state/events'
|
||||
import {FeedFeedbackProvider, useFeedFeedback} from '#/state/feed-feedback'
|
||||
@@ -33,6 +32,7 @@ import {truncateAndInvalidate} from '#/state/queries/util'
|
||||
import {useSession} from '#/state/session'
|
||||
import {useSetMinimalShellMode} from '#/state/shell'
|
||||
import {useHeaderOffset} from '#/components/hooks/useHeaderOffset'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {IS_NATIVE} from '#/env'
|
||||
import {PostFeed} from '../posts/PostFeed'
|
||||
import {FAB} from '../util/fab/FAB'
|
||||
@@ -63,6 +63,7 @@ export function FeedPage({
|
||||
savedFeedConfig?: AppBskyActorDefs.SavedFeed
|
||||
feedInfo: FeedSourceInfo
|
||||
}) {
|
||||
const ax = useAnalytics()
|
||||
const {hasSession} = useSession()
|
||||
const {_} = useLingui()
|
||||
const navigation = useNavigation<NavigationProp<AllNavigatorParams>>()
|
||||
@@ -105,13 +106,13 @@ export function FeedPage({
|
||||
scrollToTop()
|
||||
truncateAndInvalidate(queryClient, FEED_RQKEY(feed))
|
||||
setHasNew(false)
|
||||
logEvent('feed:refresh', {
|
||||
ax.metric('feed:refresh', {
|
||||
feedType: feed.split('|')[0],
|
||||
feedUrl: feed,
|
||||
reason: 'soft-reset',
|
||||
})
|
||||
}
|
||||
}, [navigation, isPageFocused, scrollToTop, queryClient, feed])
|
||||
}, [ax, navigation, isPageFocused, scrollToTop, queryClient, feed])
|
||||
|
||||
// fires when page within screen is activated/deactivated
|
||||
useEffect(() => {
|
||||
@@ -129,12 +130,12 @@ export function FeedPage({
|
||||
scrollToTop()
|
||||
truncateAndInvalidate(queryClient, FEED_RQKEY(feed))
|
||||
setHasNew(false)
|
||||
logEvent('feed:refresh', {
|
||||
ax.metric('feed:refresh', {
|
||||
feedType: feed.split('|')[0],
|
||||
feedUrl: feed,
|
||||
reason: 'load-latest',
|
||||
})
|
||||
}, [scrollToTop, feed, queryClient])
|
||||
}, [ax, scrollToTop, feed, queryClient])
|
||||
|
||||
const shouldPrefetch = IS_NATIVE && isPageAdjacent
|
||||
const isDiscoverFeed = feedInfo.uri === DISCOVER_FEED_URI
|
||||
|
||||
@@ -12,14 +12,15 @@ import {usePalette} from '#/lib/hooks/usePalette'
|
||||
import {MagnifyingGlassIcon} from '#/lib/icons'
|
||||
import {type NavigationProp} from '#/lib/routes/types'
|
||||
import {s} from '#/lib/styles'
|
||||
import {logger} from '#/logger'
|
||||
import {useFeedFeedbackContext} from '#/state/feed-feedback'
|
||||
import {useSession} from '#/state/session'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {IS_WEB} from '#/env'
|
||||
import {Button} from '../util/forms/Button'
|
||||
import {Text} from '../util/text/Text'
|
||||
|
||||
export function CustomFeedEmptyState() {
|
||||
const ax = useAnalytics()
|
||||
const feedFeedback = useFeedFeedbackContext()
|
||||
const {currentAccount} = useSession()
|
||||
const hasLoggedDiscoverEmptyErrorRef = React.useRef(false)
|
||||
@@ -33,7 +34,7 @@ export function CustomFeedEmptyState() {
|
||||
!hasLoggedDiscoverEmptyErrorRef.current
|
||||
) {
|
||||
hasLoggedDiscoverEmptyErrorRef.current = true
|
||||
logger.metric('feed:discover:emptyError', {
|
||||
ax.metric('feed:discover:emptyError', {
|
||||
userDid: currentAccount.did,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ import {isStatusStillActive, validateStatus} from '#/lib/actor-status'
|
||||
import {DISCOVER_FEED_URI, KNOWN_SHUTDOWN_FEEDS} from '#/lib/constants'
|
||||
import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
|
||||
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||
import {logEvent} from '#/lib/statsig/statsig'
|
||||
import {isNetworkError} from '#/lib/strings/errors'
|
||||
import {logger} from '#/logger'
|
||||
import {usePostAuthorShadowFilter} from '#/state/cache/profile-shadow'
|
||||
@@ -69,6 +68,7 @@ import {
|
||||
} from '#/components/feeds/PostFeedVideoGridRow'
|
||||
import {TrendingInterstitial} from '#/components/interstitials/Trending'
|
||||
import {TrendingVideos as TrendingVideosInterstitial} from '#/components/interstitials/TrendingVideos'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {IS_IOS, IS_NATIVE, IS_WEB} from '#/env'
|
||||
import {DiscoverFeedLiveEventFeedsAndTrendingBanner} from '#/features/liveEvents/components/DiscoverFeedLiveEventFeedsAndTrendingBanner'
|
||||
import {ComposerPrompt} from '../feeds/ComposerPrompt'
|
||||
@@ -232,6 +232,7 @@ let PostFeed = ({
|
||||
initialNumToRender?: number
|
||||
isVideoFeed?: boolean
|
||||
}): React.ReactNode => {
|
||||
const ax = useAnalytics()
|
||||
const {_} = useLingui()
|
||||
const queryClient = useQueryClient()
|
||||
const {currentAccount, hasSession} = useSession()
|
||||
@@ -685,7 +686,7 @@ let PostFeed = ({
|
||||
// =
|
||||
|
||||
const onRefresh = useCallback(async () => {
|
||||
logEvent('feed:refresh', {
|
||||
ax.metric('feed:refresh', {
|
||||
feedType: feedType,
|
||||
feedUrl: feed,
|
||||
reason: 'pull-to-refresh',
|
||||
@@ -698,12 +699,12 @@ let PostFeed = ({
|
||||
logger.error('Failed to refresh posts feed', {message: err})
|
||||
}
|
||||
setIsPTRing(false)
|
||||
}, [refetch, setIsPTRing, onHasNew, feed, feedType])
|
||||
}, [ax, refetch, setIsPTRing, onHasNew, feed, feedType])
|
||||
|
||||
const onEndReached = useCallback(async () => {
|
||||
if (isFetching || !hasNextPage || isError) return
|
||||
|
||||
logEvent('feed:endReached', {
|
||||
ax.metric('feed:endReached', {
|
||||
feedType: feedType,
|
||||
feedUrl: feed,
|
||||
itemCount: feedItems.length,
|
||||
@@ -714,6 +715,7 @@ let PostFeed = ({
|
||||
logger.error('Failed to load more posts', {message: err})
|
||||
}
|
||||
}, [
|
||||
ax,
|
||||
isFetching,
|
||||
hasNextPage,
|
||||
isError,
|
||||
@@ -933,17 +935,13 @@ let PostFeed = ({
|
||||
|
||||
const position = getPostPosition('sliceItem', item.key)
|
||||
|
||||
logger.metric(
|
||||
'post:view',
|
||||
{
|
||||
uri: post.uri,
|
||||
authorDid: post.author.did,
|
||||
logContext: 'FeedItem',
|
||||
feedDescriptor: feedFeedback.feedDescriptor || feed,
|
||||
position,
|
||||
},
|
||||
{statsig: false},
|
||||
)
|
||||
ax.metric('post:view', {
|
||||
uri: post.uri,
|
||||
authorDid: post.author.did,
|
||||
logContext: 'FeedItem',
|
||||
feedDescriptor: feedFeedback.feedDescriptor || feed,
|
||||
position,
|
||||
})
|
||||
}
|
||||
|
||||
// Live status tracking (existing code)
|
||||
@@ -955,14 +953,10 @@ let PostFeed = ({
|
||||
) {
|
||||
if (!seenActorWithStatusRef.current.has(actor.did)) {
|
||||
seenActorWithStatusRef.current.add(actor.did)
|
||||
logger.metric(
|
||||
'live:view:post',
|
||||
{
|
||||
subject: actor.did,
|
||||
feed,
|
||||
},
|
||||
{statsig: false},
|
||||
)
|
||||
ax.metric('live:view:post', {
|
||||
subject: actor.did,
|
||||
feed,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if (item.type === 'videoGridRow') {
|
||||
@@ -976,17 +970,13 @@ let PostFeed = ({
|
||||
|
||||
const position = getPostPosition('videoGridRow', item.key)
|
||||
|
||||
logger.metric(
|
||||
'post:view',
|
||||
{
|
||||
uri: post.uri,
|
||||
authorDid: post.author.did,
|
||||
logContext: 'FeedItem',
|
||||
feedDescriptor: feedFeedback.feedDescriptor || feed,
|
||||
position,
|
||||
},
|
||||
{statsig: false},
|
||||
)
|
||||
ax.metric('post:view', {
|
||||
uri: post.uri,
|
||||
authorDid: post.author.did,
|
||||
logContext: 'FeedItem',
|
||||
feedDescriptor: feedFeedback.feedDescriptor || feed,
|
||||
position,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import {useOpenComposer} from '#/lib/hooks/useOpenComposer'
|
||||
import {usePalette} from '#/lib/hooks/usePalette'
|
||||
import {makeProfileLink} from '#/lib/routes/links'
|
||||
import {countLines} from '#/lib/strings/helpers'
|
||||
import {logger} from '#/logger'
|
||||
import {
|
||||
POST_TOMBSTONE,
|
||||
type Shadow,
|
||||
@@ -48,6 +47,7 @@ import {PostControls} from '#/components/PostControls'
|
||||
import {DiscoverDebug} from '#/components/PostControls/DiscoverDebug'
|
||||
import {RichText} from '#/components/RichText'
|
||||
import {SubtleHover} from '#/components/SubtleHover'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import * as bsky from '#/types/bsky'
|
||||
import {PostFeedReason} from './PostFeedReason'
|
||||
|
||||
@@ -158,6 +158,7 @@ let FeedItemInner = ({
|
||||
rootPost: AppBskyFeedDefs.PostView
|
||||
onShowLess?: (interaction: AppBskyFeedDefs.Interaction) => void
|
||||
}): React.ReactNode => {
|
||||
const ax = useAnalytics()
|
||||
const queryClient = useQueryClient()
|
||||
const {openComposer} = useOpenComposer()
|
||||
const pal = usePalette('default')
|
||||
@@ -198,7 +199,7 @@ let FeedItemInner = ({
|
||||
feedContext,
|
||||
reqId,
|
||||
})
|
||||
logger.metric('post:clickthroughAuthor', {
|
||||
ax.metric('post:clickthroughAuthor', {
|
||||
uri: post.uri,
|
||||
authorDid: post.author.did,
|
||||
logContext: 'FeedItem',
|
||||
@@ -222,7 +223,7 @@ let FeedItemInner = ({
|
||||
feedContext,
|
||||
reqId,
|
||||
})
|
||||
logger.metric('post:clickthroughEmbed', {
|
||||
ax.metric('post:clickthroughEmbed', {
|
||||
uri: post.uri,
|
||||
authorDid: post.author.did,
|
||||
logContext: 'FeedItem',
|
||||
@@ -237,7 +238,7 @@ let FeedItemInner = ({
|
||||
feedContext,
|
||||
reqId,
|
||||
})
|
||||
logger.metric('post:clickthroughItem', {
|
||||
ax.metric('post:clickthroughItem', {
|
||||
uri: post.uri,
|
||||
authorDid: post.author.did,
|
||||
logContext: 'FeedItem',
|
||||
|
||||
@@ -12,6 +12,7 @@ import {useResolveDidQuery} from '#/state/queries/resolve-uri'
|
||||
import {useSession} from '#/state/session'
|
||||
import {PeopleRemove2_Stroke1_Corner0_Rounded as PeopleRemoveIcon} from '#/components/icons/PeopleRemove2'
|
||||
import {ListFooter, ListMaybePlaceholder} from '#/components/Lists'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {List} from '../util/List'
|
||||
import {ProfileCardWithFollowBtn} from './ProfileCard'
|
||||
|
||||
@@ -41,6 +42,7 @@ function keyExtractor(item: ActorDefs.ProfileViewBasic) {
|
||||
|
||||
export function ProfileFollowers({name}: {name: string}) {
|
||||
const {_} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const navigation = useNavigation()
|
||||
const initialNumToRender = useInitialNumToRender()
|
||||
const {currentAccount} = useSession()
|
||||
@@ -88,14 +90,14 @@ export function ProfileFollowers({name}: {name: string}) {
|
||||
currentPageCount >= 3 &&
|
||||
currentPageCount > paginationTrackingRef.current.page
|
||||
) {
|
||||
logger.metric('profile:followers:paginate', {
|
||||
ax.metric('profile:followers:paginate', {
|
||||
contextProfileDid: resolvedDid,
|
||||
itemCount: followers.length,
|
||||
page: currentPageCount,
|
||||
})
|
||||
}
|
||||
paginationTrackingRef.current.page = currentPageCount
|
||||
}, [data?.pages?.length, resolvedDid, followers.length])
|
||||
}, [ax, data?.pages?.length, resolvedDid, followers.length])
|
||||
|
||||
const onRefresh = React.useCallback(async () => {
|
||||
setIsPTRing(true)
|
||||
@@ -125,12 +127,12 @@ export function ProfileFollowers({name}: {name: string}) {
|
||||
// track pageview
|
||||
React.useEffect(() => {
|
||||
if (resolvedDid) {
|
||||
logger.metric('profile:followers:view', {
|
||||
ax.metric('profile:followers:view', {
|
||||
contextProfileDid: resolvedDid,
|
||||
isOwnProfile: isMe,
|
||||
})
|
||||
}
|
||||
}, [resolvedDid, isMe])
|
||||
}, [ax, resolvedDid, isMe])
|
||||
|
||||
// track seen items
|
||||
const seenItemsRef = React.useRef<Set<string>>(new Set())
|
||||
@@ -147,17 +149,13 @@ export function ProfileFollowers({name}: {name: string}) {
|
||||
if (position === 0) {
|
||||
return
|
||||
}
|
||||
logger.metric(
|
||||
'profileCard:seen',
|
||||
{
|
||||
profileDid: item.did,
|
||||
position,
|
||||
...(resolvedDid !== undefined && {contextProfileDid: resolvedDid}),
|
||||
},
|
||||
{statsig: false},
|
||||
)
|
||||
ax.metric('profileCard:seen', {
|
||||
profileDid: item.did,
|
||||
position,
|
||||
...(resolvedDid !== undefined && {contextProfileDid: resolvedDid}),
|
||||
})
|
||||
},
|
||||
[followers, resolvedDid],
|
||||
[ax, followers, resolvedDid],
|
||||
)
|
||||
|
||||
if (followers.length < 1) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import {useSession} from '#/state/session'
|
||||
import {FindContactsBannerNUX} from '#/components/contacts/FindContactsBannerNUX'
|
||||
import {PeopleRemove2_Stroke1_Corner0_Rounded as PeopleRemoveIcon} from '#/components/icons/PeopleRemove2'
|
||||
import {ListFooter, ListMaybePlaceholder} from '#/components/Lists'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {IS_WEB} from '#/env'
|
||||
import {List} from '../util/List'
|
||||
import {ProfileCardWithFollowBtn} from './ProfileCard'
|
||||
@@ -44,6 +45,7 @@ function keyExtractor(item: ActorDefs.ProfileViewBasic) {
|
||||
|
||||
export function ProfileFollows({name}: {name: string}) {
|
||||
const {_} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const initialNumToRender = useInitialNumToRender()
|
||||
const {currentAccount} = useSession()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
@@ -100,14 +102,14 @@ export function ProfileFollows({name}: {name: string}) {
|
||||
currentPageCount >= 3 &&
|
||||
currentPageCount > paginationTrackingRef.current.page
|
||||
) {
|
||||
logger.metric('profile:following:paginate', {
|
||||
ax.metric('profile:following:paginate', {
|
||||
contextProfileDid: resolvedDid,
|
||||
itemCount: follows.length,
|
||||
page: currentPageCount,
|
||||
})
|
||||
}
|
||||
paginationTrackingRef.current.page = currentPageCount
|
||||
}, [data?.pages?.length, resolvedDid, follows.length])
|
||||
}, [ax, data?.pages?.length, resolvedDid, follows.length])
|
||||
|
||||
const onRefresh = React.useCallback(async () => {
|
||||
setIsPTRing(true)
|
||||
@@ -137,12 +139,12 @@ export function ProfileFollows({name}: {name: string}) {
|
||||
// track pageview
|
||||
React.useEffect(() => {
|
||||
if (resolvedDid) {
|
||||
logger.metric('profile:following:view', {
|
||||
ax.metric('profile:following:view', {
|
||||
contextProfileDid: resolvedDid,
|
||||
isOwnProfile: isMe,
|
||||
})
|
||||
}
|
||||
}, [resolvedDid, isMe])
|
||||
}, [ax, resolvedDid, isMe])
|
||||
|
||||
// track seen items
|
||||
const seenItemsRef = React.useRef<Set<string>>(new Set())
|
||||
@@ -159,17 +161,13 @@ export function ProfileFollows({name}: {name: string}) {
|
||||
if (position === 0) {
|
||||
return
|
||||
}
|
||||
logger.metric(
|
||||
'profileCard:seen',
|
||||
{
|
||||
profileDid: item.did,
|
||||
position,
|
||||
...(resolvedDid !== undefined && {contextProfileDid: resolvedDid}),
|
||||
},
|
||||
{statsig: false},
|
||||
)
|
||||
ax.metric('profileCard:seen', {
|
||||
profileDid: item.did,
|
||||
position,
|
||||
...(resolvedDid !== undefined && {contextProfileDid: resolvedDid}),
|
||||
})
|
||||
},
|
||||
[follows, resolvedDid],
|
||||
[ax, follows, resolvedDid],
|
||||
)
|
||||
|
||||
if (follows.length < 1) {
|
||||
|
||||
@@ -11,7 +11,6 @@ import {makeProfileLink} from '#/lib/routes/links'
|
||||
import {type NavigationProp} from '#/lib/routes/types'
|
||||
import {shareText, shareUrl} from '#/lib/sharing'
|
||||
import {toShareUrl} from '#/lib/strings/url-helpers'
|
||||
import {logger} from '#/logger'
|
||||
import {type Shadow} from '#/state/cache/types'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
import {Nux, useNux, useSaveNux} from '#/state/queries/nuxs'
|
||||
@@ -60,6 +59,7 @@ import * as Prompt from '#/components/Prompt'
|
||||
import {useFullVerificationState} from '#/components/verification'
|
||||
import {VerificationCreatePrompt} from '#/components/verification/VerificationCreatePrompt'
|
||||
import {VerificationRemovePrompt} from '#/components/verification/VerificationRemovePrompt'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {IS_WEB} from '#/env'
|
||||
import {Dot} from '#/features/nuxs/components/Dot'
|
||||
import {Gradient} from '#/features/nuxs/components/Gradient'
|
||||
@@ -71,6 +71,7 @@ let ProfileMenu = ({
|
||||
profile: Shadow<AppBskyActorDefs.ProfileViewDetailed>
|
||||
}): React.ReactNode => {
|
||||
const t = useTheme()
|
||||
const ax = useAnalytics()
|
||||
const {_} = useLingui()
|
||||
const {currentAccount, hasSession} = useSession()
|
||||
const {openModal} = useModalControls()
|
||||
@@ -121,7 +122,7 @@ let ProfileMenu = ({
|
||||
}, [queryClient, profile.did])
|
||||
|
||||
const onPressAddToStarterPacks = React.useCallback(() => {
|
||||
logger.metric('profile:addToStarterPack', {})
|
||||
ax.metric('profile:addToStarterPack', {})
|
||||
addToStarterPacksDialogControl.open()
|
||||
}, [addToStarterPacksDialogControl])
|
||||
|
||||
@@ -147,7 +148,7 @@ let ProfileMenu = ({
|
||||
Toast.show(_(msg({message: 'Account unmuted', context: 'toast'})))
|
||||
} catch (e: any) {
|
||||
if (e?.name !== 'AbortError') {
|
||||
logger.error('Failed to unmute account', {message: e})
|
||||
ax.logger.error('Failed to unmute account', {message: e})
|
||||
Toast.show(_(msg`There was an issue! ${e.toString()}`), 'xmark')
|
||||
}
|
||||
}
|
||||
@@ -157,12 +158,12 @@ let ProfileMenu = ({
|
||||
Toast.show(_(msg({message: 'Account muted', context: 'toast'})))
|
||||
} catch (e: any) {
|
||||
if (e?.name !== 'AbortError') {
|
||||
logger.error('Failed to mute account', {message: e})
|
||||
ax.logger.error('Failed to mute account', {message: e})
|
||||
Toast.show(_(msg`There was an issue! ${e.toString()}`), 'xmark')
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [profile.viewer?.muted, queueUnmute, _, queueMute])
|
||||
}, [ax, profile.viewer?.muted, queueUnmute, _, queueMute])
|
||||
|
||||
const blockAccount = React.useCallback(async () => {
|
||||
if (profile.viewer?.blocking) {
|
||||
@@ -171,7 +172,7 @@ let ProfileMenu = ({
|
||||
Toast.show(_(msg({message: 'Account unblocked', context: 'toast'})))
|
||||
} catch (e: any) {
|
||||
if (e?.name !== 'AbortError') {
|
||||
logger.error('Failed to unblock account', {message: e})
|
||||
ax.logger.error('Failed to unblock account', {message: e})
|
||||
Toast.show(_(msg`There was an issue! ${e.toString()}`), 'xmark')
|
||||
}
|
||||
}
|
||||
@@ -181,12 +182,12 @@ let ProfileMenu = ({
|
||||
Toast.show(_(msg({message: 'Account blocked', context: 'toast'})))
|
||||
} catch (e: any) {
|
||||
if (e?.name !== 'AbortError') {
|
||||
logger.error('Failed to block account', {message: e})
|
||||
ax.logger.error('Failed to block account', {message: e})
|
||||
Toast.show(_(msg`There was an issue! ${e.toString()}`), 'xmark')
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [profile.viewer?.blocking, _, queueUnblock, queueBlock])
|
||||
}, [ax, profile.viewer?.blocking, _, queueUnblock, queueBlock])
|
||||
|
||||
const onPressFollowAccount = React.useCallback(async () => {
|
||||
try {
|
||||
@@ -194,11 +195,11 @@ let ProfileMenu = ({
|
||||
Toast.show(_(msg({message: 'Account followed', context: 'toast'})))
|
||||
} catch (e: any) {
|
||||
if (e?.name !== 'AbortError') {
|
||||
logger.error('Failed to follow account', {message: e})
|
||||
ax.logger.error('Failed to follow account', {message: e})
|
||||
Toast.show(_(msg`There was an issue! ${e.toString()}`), 'xmark')
|
||||
}
|
||||
}
|
||||
}, [_, queueFollow])
|
||||
}, [_, ax, queueFollow])
|
||||
|
||||
const onPressUnfollowAccount = React.useCallback(async () => {
|
||||
try {
|
||||
@@ -206,11 +207,11 @@ let ProfileMenu = ({
|
||||
Toast.show(_(msg({message: 'Account unfollowed', context: 'toast'})))
|
||||
} catch (e: any) {
|
||||
if (e?.name !== 'AbortError') {
|
||||
logger.error('Failed to unfollow account', {message: e})
|
||||
ax.logger.error('Failed to unfollow account', {message: e})
|
||||
Toast.show(_(msg`There was an issue! ${e.toString()}`), 'xmark')
|
||||
}
|
||||
}
|
||||
}, [_, queueUnfollow])
|
||||
}, [_, ax, queueUnfollow])
|
||||
|
||||
const onPressReportAccount = React.useCallback(() => {
|
||||
reportDialogControl.open()
|
||||
|
||||
@@ -52,6 +52,7 @@ import {LiveStatusDialog} from '#/components/live/LiveStatusDialog'
|
||||
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
||||
import * as Menu from '#/components/Menu'
|
||||
import {ProfileHoverCard} from '#/components/ProfileHoverCard'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {IS_ANDROID, IS_NATIVE, IS_WEB, IS_WEB_TOUCH_DEVICE} from '#/env'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
|
||||
@@ -530,6 +531,7 @@ let PreviewableUserAvatar = ({
|
||||
live,
|
||||
...props
|
||||
}: PreviewableUserAvatarProps): React.ReactNode => {
|
||||
const ax = useAnalytics()
|
||||
const {_} = useLingui()
|
||||
const queryClient = useQueryClient()
|
||||
const status = useActorStatus(profile)
|
||||
@@ -543,11 +545,7 @@ let PreviewableUserAvatar = ({
|
||||
|
||||
const onOpenLiveStatus = useCallback(() => {
|
||||
playHaptic('Light')
|
||||
logger.metric(
|
||||
'live:card:open',
|
||||
{subject: profile.did, from: 'post'},
|
||||
{statsig: true},
|
||||
)
|
||||
ax.metric('live:card:open', {subject: profile.did, from: 'post'})
|
||||
liveControl.open()
|
||||
}, [liveControl, playHaptic, profile.did])
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
type HomeTabNavigatorParams,
|
||||
type NativeStackScreenProps,
|
||||
} from '#/lib/routes/types'
|
||||
import {logEvent} from '#/lib/statsig/statsig'
|
||||
import {emitSoftReset} from '#/state/events'
|
||||
import {
|
||||
type SavedFeedSourceInfo,
|
||||
@@ -36,6 +35,7 @@ import {FollowingEmptyState} from '#/view/com/posts/FollowingEmptyState'
|
||||
import {FollowingEndOfFeed} from '#/view/com/posts/FollowingEndOfFeed'
|
||||
import {NoFeedsPinned} from '#/screens/Home/NoFeedsPinned'
|
||||
import * as Layout from '#/components/Layout'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {IS_WEB} from '#/env'
|
||||
import {useDemoMode} from '#/storage/hooks/demo-mode'
|
||||
|
||||
@@ -105,6 +105,7 @@ function HomeScreenReady({
|
||||
preferences: UsePreferencesQueryResponse
|
||||
pinnedFeedInfos: SavedFeedSourceInfo[]
|
||||
}) {
|
||||
const ax = useAnalytics()
|
||||
const allFeeds = React.useMemo(
|
||||
() => pinnedFeedInfos.map(f => f.feedDescriptor),
|
||||
[pinnedFeedInfos],
|
||||
@@ -147,7 +148,7 @@ function HomeScreenReady({
|
||||
useFocusEffect(
|
||||
useNonReactiveCallback(() => {
|
||||
if (maybeSelectedFeed) {
|
||||
logEvent('home:feedDisplayed', {
|
||||
ax.metric('home:feedDisplayed', {
|
||||
index: selectedIndex,
|
||||
feedType: maybeSelectedFeed.split('|')[0],
|
||||
feedUrl: maybeSelectedFeed,
|
||||
@@ -168,14 +169,14 @@ function HomeScreenReady({
|
||||
setSelectedFeed(maybeFeed)
|
||||
|
||||
if (maybeFeed) {
|
||||
logEvent('home:feedDisplayed', {
|
||||
ax.metric('home:feedDisplayed', {
|
||||
index,
|
||||
feedType: maybeFeed.split('|')[0],
|
||||
feedUrl: maybeFeed,
|
||||
})
|
||||
}
|
||||
},
|
||||
[setSelectedFeed, setMinimalShellMode, allFeeds],
|
||||
[ax, setSelectedFeed, setMinimalShellMode, allFeeds],
|
||||
)
|
||||
|
||||
const onPressSelected = React.useCallback(() => {
|
||||
|
||||
@@ -5,7 +5,6 @@ import {useNavigation, useNavigationState} from '@react-navigation/native'
|
||||
|
||||
import {getCurrentRoute} from '#/lib/routes/helpers'
|
||||
import {type NavigationProp} from '#/lib/routes/types'
|
||||
import {logger} from '#/logger'
|
||||
import {emitSoftReset} from '#/state/events'
|
||||
import {
|
||||
type SavedFeedSourceInfo,
|
||||
@@ -19,10 +18,12 @@ import {FilterTimeline_Stroke2_Corner0_Rounded as FilterTimeline} from '#/compon
|
||||
import {PlusSmall_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus'
|
||||
import {Link} from '#/components/Link'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
|
||||
export function DesktopFeeds() {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const {data: pinnedFeedInfos, error, isLoading} = usePinnedFeedsInfos()
|
||||
const selectedFeed = useSelectedFeed()
|
||||
const setSelectedFeed = useSetSelectedFeed()
|
||||
@@ -86,14 +87,10 @@ export function DesktopFeeds() {
|
||||
feedInfo={feedInfo}
|
||||
current={current}
|
||||
onPress={() => {
|
||||
logger.metric(
|
||||
'desktopFeeds:feed:click',
|
||||
{
|
||||
feedUri: feedInfo.uri,
|
||||
feedDescriptor: feed,
|
||||
},
|
||||
{statsig: false},
|
||||
)
|
||||
ax.metric('desktopFeeds:feed:click', {
|
||||
feedUri: feedInfo.uri,
|
||||
feedDescriptor: feed,
|
||||
})
|
||||
setSelectedFeed(feed)
|
||||
navigation.navigate('Home')
|
||||
if (route.name === 'Home' && feed === selectedFeed) {
|
||||
|
||||
@@ -2,7 +2,6 @@ import {View} from 'react-native'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {logger} from '#/logger'
|
||||
import {
|
||||
useTrendingSettings,
|
||||
useTrendingSettingsApi,
|
||||
@@ -16,6 +15,7 @@ import {Trending3_Stroke2_Corner1_Rounded as TrendingIcon} from '#/components/ic
|
||||
import * as Prompt from '#/components/Prompt'
|
||||
import {TrendingTopicLink} from '#/components/TrendingTopics'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
|
||||
const TRENDING_LIMIT = 5
|
||||
|
||||
@@ -28,13 +28,14 @@ export function SidebarTrendingTopics() {
|
||||
function Inner() {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const trendingPrompt = Prompt.usePromptControl()
|
||||
const {setTrendingDisabled} = useTrendingSettingsApi()
|
||||
const {data: trending, error, isLoading} = useTrendingTopics()
|
||||
const noTopics = !isLoading && !error && !trending?.topics?.length
|
||||
|
||||
const onConfirmHide = () => {
|
||||
logger.metric('trendingTopics:hide', {context: 'sidebar'})
|
||||
ax.metric('trendingTopics:hide', {context: 'sidebar'})
|
||||
setTrendingDisabled(true)
|
||||
}
|
||||
|
||||
@@ -90,7 +91,7 @@ function Inner() {
|
||||
topic={topic}
|
||||
style={[a.self_start]}
|
||||
onPress={() => {
|
||||
logger.metric('trendingTopic:click', {context: 'sidebar'})
|
||||
ax.metric('trendingTopic:click', {context: 'sidebar'})
|
||||
}}>
|
||||
{({hovered}) => (
|
||||
<View style={[a.flex_row, a.align_center, a.gap_xs]}>
|
||||
|
||||
Reference in New Issue
Block a user