[Statsig] Instrument feed display (#3455)

* [Statsig] Instrument feed display

* Back out leftover change
This commit is contained in:
dan 2024-04-09 23:09:42 +01:00 committed by GitHub
parent c96bc92042
commit c300d4cab6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 71 additions and 15 deletions

View file

@ -44,6 +44,12 @@ export type LogEvents = {
} }
'onboarding:moderation:nextPressed': {} 'onboarding:moderation:nextPressed': {}
'onboarding:finished:nextPressed': {} 'onboarding:finished:nextPressed': {}
'home:feedDisplayed': {
feedUrl: string
feedType: string
index: number
reason: 'focus' | 'tabbar-click' | 'pager-swipe' | 'desktop-sidebar-click'
}
'feed:endReached': { 'feed:endReached': {
feedUrl: string feedUrl: string
feedType: string feedType: string

View file

@ -1,17 +1,22 @@
import React, {forwardRef} from 'react' import React, {forwardRef} from 'react'
import {Animated, View} from 'react-native' import {Animated, View} from 'react-native'
import PagerView, { import PagerView, {
PagerViewOnPageSelectedEvent,
PagerViewOnPageScrollEvent, PagerViewOnPageScrollEvent,
PagerViewOnPageSelectedEvent,
PageScrollStateChangedNativeEvent, PageScrollStateChangedNativeEvent,
} from 'react-native-pager-view' } from 'react-native-pager-view'
import {LogEvents} from '#/lib/statsig/events'
import {s} from 'lib/styles' import {s} from 'lib/styles'
export type PageSelectedEvent = PagerViewOnPageSelectedEvent export type PageSelectedEvent = PagerViewOnPageSelectedEvent
const AnimatedPagerView = Animated.createAnimatedComponent(PagerView) const AnimatedPagerView = Animated.createAnimatedComponent(PagerView)
export interface PagerRef { export interface PagerRef {
setPage: (index: number) => void setPage: (
index: number,
reason: LogEvents['home:feedDisplayed']['reason'],
) => void
} }
export interface RenderTabBarFnProps { export interface RenderTabBarFnProps {
@ -25,7 +30,10 @@ interface Props {
initialPage?: number initialPage?: number
renderTabBar: RenderTabBarFn renderTabBar: RenderTabBarFn
onPageSelected?: (index: number) => void onPageSelected?: (index: number) => void
onPageSelecting?: (index: number) => void onPageSelecting?: (
index: number,
reason: LogEvents['home:feedDisplayed']['reason'],
) => void
onPageScrollStateChanged?: ( onPageScrollStateChanged?: (
scrollState: 'idle' | 'dragging' | 'settling', scrollState: 'idle' | 'dragging' | 'settling',
) => void ) => void
@ -51,7 +59,13 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>(
const pagerView = React.useRef<PagerView>(null) const pagerView = React.useRef<PagerView>(null)
React.useImperativeHandle(ref, () => ({ React.useImperativeHandle(ref, () => ({
setPage: (index: number) => pagerView.current?.setPage(index), setPage: (
index: number,
reason: LogEvents['home:feedDisplayed']['reason'],
) => {
pagerView.current?.setPage(index)
onPageSelecting?.(index, reason)
},
})) }))
const onPageSelectedInner = React.useCallback( const onPageSelectedInner = React.useCallback(
@ -79,14 +93,14 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>(
// -prf // -prf
if (scrollState.current === 'settling') { if (scrollState.current === 'settling') {
if (lastDirection.current === -1 && offset < lastOffset.current) { if (lastDirection.current === -1 && offset < lastOffset.current) {
onPageSelecting?.(position) onPageSelecting?.(position, 'pager-swipe')
setSelectedPage(position) setSelectedPage(position)
lastDirection.current = 0 lastDirection.current = 0
} else if ( } else if (
lastDirection.current === 1 && lastDirection.current === 1 &&
offset > lastOffset.current offset > lastOffset.current
) { ) {
onPageSelecting?.(position + 1) onPageSelecting?.(position + 1, 'pager-swipe')
setSelectedPage(position + 1) setSelectedPage(position + 1)
lastDirection.current = 0 lastDirection.current = 0
} }
@ -113,7 +127,7 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>(
const onTabBarSelect = React.useCallback( const onTabBarSelect = React.useCallback(
(index: number) => { (index: number) => {
pagerView.current?.setPage(index) pagerView.current?.setPage(index)
onPageSelecting?.(index) onPageSelecting?.(index, 'tabbar-click')
}, },
[pagerView, onPageSelecting], [pagerView, onPageSelecting],
) )

View file

@ -1,6 +1,8 @@
import React from 'react' import React from 'react'
import {flushSync} from 'react-dom'
import {View} from 'react-native' import {View} from 'react-native'
import {flushSync} from 'react-dom'
import {LogEvents} from '#/lib/statsig/events'
import {s} from 'lib/styles' import {s} from 'lib/styles'
export interface RenderTabBarFnProps { export interface RenderTabBarFnProps {
@ -14,7 +16,10 @@ interface Props {
initialPage?: number initialPage?: number
renderTabBar: RenderTabBarFn renderTabBar: RenderTabBarFn
onPageSelected?: (index: number) => void onPageSelected?: (index: number) => void
onPageSelecting?: (index: number) => void onPageSelecting?: (
index: number,
reason: LogEvents['home:feedDisplayed']['reason'],
) => void
} }
export const Pager = React.forwardRef(function PagerImpl( export const Pager = React.forwardRef(function PagerImpl(
{ {
@ -31,11 +36,16 @@ export const Pager = React.forwardRef(function PagerImpl(
const anchorRef = React.useRef(null) const anchorRef = React.useRef(null)
React.useImperativeHandle(ref, () => ({ React.useImperativeHandle(ref, () => ({
setPage: (index: number) => onTabBarSelect(index), setPage: (
index: number,
reason: LogEvents['home:feedDisplayed']['reason'],
) => {
onTabBarSelect(index, reason)
},
})) }))
const onTabBarSelect = React.useCallback( const onTabBarSelect = React.useCallback(
(index: number) => { (index: number, reason: LogEvents['home:feedDisplayed']['reason']) => {
const scrollY = window.scrollY const scrollY = window.scrollY
// We want to determine if the tabbar is already "sticking" at the top (in which // We want to determine if the tabbar is already "sticking" at the top (in which
// case we should preserve and restore scroll), or if it is somewhere below in the // case we should preserve and restore scroll), or if it is somewhere below in the
@ -54,7 +64,7 @@ export const Pager = React.forwardRef(function PagerImpl(
flushSync(() => { flushSync(() => {
setSelectedPage(index) setSelectedPage(index)
onPageSelected?.(index) onPageSelected?.(index)
onPageSelecting?.(index) onPageSelecting?.(index, reason)
}) })
if (isSticking) { if (isSticking) {
const restoredScrollY = scrollYs.current[index] const restoredScrollY = scrollYs.current[index]
@ -73,7 +83,7 @@ export const Pager = React.forwardRef(function PagerImpl(
{renderTabBar({ {renderTabBar({
selectedPage, selectedPage,
tabBarAnchor: <View ref={anchorRef} />, tabBarAnchor: <View ref={anchorRef} />,
onSelect: onTabBarSelect, onSelect: e => onTabBarSelect(e, 'tabbar-click'),
})} })}
{React.Children.map(children, (child, i) => ( {React.Children.map(children, (child, i) => (
<View style={selectedPage === i ? s.flex1 : s.hidden} key={`page-${i}`}> <View style={selectedPage === i ? s.flex1 : s.hidden} key={`page-${i}`}>

View file

@ -2,8 +2,9 @@ import React from 'react'
import {ActivityIndicator, AppState, StyleSheet, View} from 'react-native' import {ActivityIndicator, AppState, StyleSheet, View} from 'react-native'
import {useFocusEffect} from '@react-navigation/native' import {useFocusEffect} from '@react-navigation/native'
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
import {useSetTitle} from '#/lib/hooks/useSetTitle' import {useSetTitle} from '#/lib/hooks/useSetTitle'
import {useGate} from '#/lib/statsig/statsig' import {logEvent, LogEvents, useGate} from '#/lib/statsig/statsig'
import {emitSoftReset} from '#/state/events' import {emitSoftReset} from '#/state/events'
import {FeedSourceInfo, usePinnedFeedsInfos} from '#/state/queries/feed' import {FeedSourceInfo, usePinnedFeedsInfos} from '#/state/queries/feed'
import {FeedDescriptor, FeedParams} from '#/state/queries/post-feed' import {FeedDescriptor, FeedParams} from '#/state/queries/post-feed'
@ -79,7 +80,7 @@ function HomeScreenReady({
// This is supposed to only happen on the web when you use the right nav. // This is supposed to only happen on the web when you use the right nav.
if (selectedIndex !== lastPagerReportedIndexRef.current) { if (selectedIndex !== lastPagerReportedIndexRef.current) {
lastPagerReportedIndexRef.current = selectedIndex lastPagerReportedIndexRef.current = selectedIndex
pagerRef.current?.setPage(selectedIndex) pagerRef.current?.setPage(selectedIndex, 'desktop-sidebar-click')
} }
}, [selectedIndex]) }, [selectedIndex])
@ -96,6 +97,17 @@ function HomeScreenReady({
}, [setDrawerSwipeDisabled, selectedIndex, setMinimalShellMode]), }, [setDrawerSwipeDisabled, selectedIndex, setMinimalShellMode]),
) )
useFocusEffect(
useNonReactiveCallback(() => {
logEvent('home:feedDisplayed', {
index: selectedIndex,
feedType: selectedFeed.split('|')[0],
feedUrl: selectedFeed,
reason: 'focus',
})
}),
)
const disableMinShellOnForegrounding = useGate( const disableMinShellOnForegrounding = useGate(
'disable_min_shell_on_foregrounding', 'disable_min_shell_on_foregrounding',
) )
@ -123,6 +135,19 @@ function HomeScreenReady({
[setDrawerSwipeDisabled, setSelectedFeed, setMinimalShellMode, allFeeds], [setDrawerSwipeDisabled, setSelectedFeed, setMinimalShellMode, allFeeds],
) )
const onPageSelecting = React.useCallback(
(index: number, reason: LogEvents['home:feedDisplayed']['reason']) => {
const feed = allFeeds[index]
logEvent('home:feedDisplayed', {
index,
feedType: feed.split('|')[0],
feedUrl: feed,
reason,
})
},
[allFeeds],
)
const onPressSelected = React.useCallback(() => { const onPressSelected = React.useCallback(() => {
emitSoftReset() emitSoftReset()
}, []) }, [])
@ -175,6 +200,7 @@ function HomeScreenReady({
ref={pagerRef} ref={pagerRef}
testID="homeScreen" testID="homeScreen"
initialPage={selectedIndex} initialPage={selectedIndex}
onPageSelecting={onPageSelecting}
onPageSelected={onPageSelected} onPageSelected={onPageSelected}
onPageScrollStateChanged={onPageScrollStateChanged} onPageScrollStateChanged={onPageScrollStateChanged}
renderTabBar={renderTabBar}> renderTabBar={renderTabBar}>