Add feature gate

This commit is contained in:
Eric Bailey
2025-01-17 16:48:40 -06:00
parent e2512141cd
commit c69aed8b3c
4 changed files with 48 additions and 28 deletions
+1
View File
@@ -7,3 +7,4 @@ export type Gate =
| 'test_gate_1' | 'test_gate_1'
| 'test_gate_2' | 'test_gate_2'
| 'trending_topics_beta' | 'trending_topics_beta'
| 'yolo'
@@ -1,9 +1,11 @@
import React from 'react'
import {msg, Trans} from '@lingui/macro' import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {NativeStackScreenProps} from '@react-navigation/native-stack' import {NativeStackScreenProps} from '@react-navigation/native-stack'
import {CommonNavigatorParams} from '#/lib/routes/types' import {CommonNavigatorParams} from '#/lib/routes/types'
import {logEvent} from '#/lib/statsig/statsig' import {logEvent} from '#/lib/statsig/statsig'
import {useGate} from '#/lib/statsig/statsig'
import {isNative} from '#/platform/detection' import {isNative} from '#/platform/detection'
import {useAutoplayDisabled, useSetAutoplayDisabled} from '#/state/preferences' import {useAutoplayDisabled, useSetAutoplayDisabled} from '#/state/preferences'
import { import {
@@ -40,6 +42,10 @@ export function ContentAndMediaSettingsScreen({}: Props) {
const {trendingDisabled, trendingVideoDisabled} = useTrendingSettings() const {trendingDisabled, trendingVideoDisabled} = useTrendingSettings()
const {setTrendingDisabled, setTrendingVideoDisabled} = const {setTrendingDisabled, setTrendingVideoDisabled} =
useTrendingSettingsApi() useTrendingSettingsApi()
const gate = useGate()
const areVideoFeedsEnabled = React.useMemo(() => {
return gate('yolo')
}, [gate])
return ( return (
<Layout.Screen> <Layout.Screen>
@@ -139,27 +145,29 @@ export function ContentAndMediaSettingsScreen({}: Props) {
<Toggle.Platform /> <Toggle.Platform />
</SettingsList.Item> </SettingsList.Item>
</Toggle.Item> </Toggle.Item>
<Toggle.Item {areVideoFeedsEnabled && (
name="show_trending_videos" <Toggle.Item
label={_(msg`Enable trending videos`)} name="show_trending_videos"
value={!trendingVideoDisabled} label={_(msg`Enable trending videos`)}
onChange={value => { value={!trendingVideoDisabled}
const hide = Boolean(!value) onChange={value => {
if (hide) { const hide = Boolean(!value)
logEvent('trendingVideos:hide', {context: 'settings'}) if (hide) {
} else { logEvent('trendingVideos:hide', {context: 'settings'})
logEvent('trendingVideos:show', {context: 'settings'}) } else {
} logEvent('trendingVideos:show', {context: 'settings'})
setTrendingVideoDisabled(hide) }
}}> setTrendingVideoDisabled(hide)
<SettingsList.Item> }}>
<SettingsList.ItemIcon icon={Graph} /> <SettingsList.Item>
<SettingsList.ItemText> <SettingsList.ItemIcon icon={Graph} />
<Trans>Enable trending videos</Trans> <SettingsList.ItemText>
</SettingsList.ItemText> <Trans>Enable trending videos</Trans>
<Toggle.Platform /> </SettingsList.ItemText>
</SettingsList.Item> <Toggle.Platform />
</Toggle.Item> </SettingsList.Item>
</Toggle.Item>
)}
</> </>
)} )}
</SettingsList.Container> </SettingsList.Container>
+13 -5
View File
@@ -21,6 +21,7 @@ import {
} from '#/lib/constants' } from '#/lib/constants'
import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender' import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
import {useGate} from '#/lib/statsig/statsig'
import {logEvent} from '#/lib/statsig/statsig' import {logEvent} from '#/lib/statsig/statsig'
import {useTheme} from '#/lib/ThemeContext' import {useTheme} from '#/lib/ThemeContext'
import {logger} from '#/logger' import {logger} from '#/logger'
@@ -188,7 +189,13 @@ let PostFeed = ({
const lastFetchRef = React.useRef<number>(Date.now()) const lastFetchRef = React.useRef<number>(Date.now())
const [feedType, feedUri, feedTab] = feed.split('|') const [feedType, feedUri, feedTab] = feed.split('|')
const {gtMobile, gtTablet} = useBreakpoints() const {gtMobile, gtTablet} = useBreakpoints()
const isVideoFeed = feedUri === VIDEO_FEED_URI const gate = useGate()
const areVideoFeedsEnabled = React.useMemo(() => {
return isNative && gate('yolo')
}, [gate])
const isVideoFeedAndIsEnabled = React.useMemo(() => {
return feedUri === VIDEO_FEED_URI && areVideoFeedsEnabled
}, [feedUri, areVideoFeedsEnabled])
const opts = React.useMemo( const opts = React.useMemo(
() => ({enabled, ignoreFilterFor}), () => ({enabled, ignoreFilterFor}),
@@ -329,7 +336,7 @@ let PostFeed = ({
} else if (data) { } else if (data) {
let sliceIndex = -1 let sliceIndex = -1
if (isVideoFeed && isNative) { if (isVideoFeedAndIsEnabled) {
const rows: FeedPostSliceItem[][] = [] const rows: FeedPostSliceItem[][] = []
let slices: {slice: FeedPostSlice; index: number}[] = [] let slices: {slice: FeedPostSlice; index: number}[] = []
for (const page of data.pages) { for (const page of data.pages) {
@@ -386,7 +393,7 @@ let PostFeed = ({
}) })
} }
} else if (sliceIndex === 15) { } else if (sliceIndex === 15) {
if (isNative && !trendingVideoDisabled) { if (areVideoFeedsEnabled && !trendingVideoDisabled) {
arr.push({ arr.push({
type: 'interstitialTrendingVideos', type: 'interstitialTrendingVideos',
key: 'interstitial-' + sliceIndex + '-' + lastFetchedAt, key: 'interstitial-' + sliceIndex + '-' + lastFetchedAt,
@@ -461,7 +468,7 @@ let PostFeed = ({
}) })
} }
} else { } else {
if (isVideoFeed && isNative) { if (isVideoFeedAndIsEnabled) {
arr.push({ arr.push({
type: 'videoGridRowPlaceholder', type: 'videoGridRowPlaceholder',
key: 'videoGridRowPlaceholder', key: 'videoGridRowPlaceholder',
@@ -490,7 +497,8 @@ let PostFeed = ({
trendingVideoDisabled, trendingVideoDisabled,
gtTablet, gtTablet,
gtMobile, gtMobile,
isVideoFeed, isVideoFeedAndIsEnabled,
areVideoFeedsEnabled,
]) ])
// events // events
+5 -2
View File
@@ -10,9 +10,10 @@ import {
import {msg, Trans} from '@lingui/macro' import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {useGate} from '#/lib/statsig/statsig'
import {cleanError} from '#/lib/strings/errors' import {cleanError} from '#/lib/strings/errors'
import {logger} from '#/logger' import {logger} from '#/logger'
import {isNative,isWeb} from '#/platform/detection' import {isNative, isWeb} from '#/platform/detection'
import {useModerationOpts} from '#/state/preferences/moderation-opts' import {useModerationOpts} from '#/state/preferences/moderation-opts'
import {useGetPopularFeedsQuery} from '#/state/queries/feed' import {useGetPopularFeedsQuery} from '#/state/queries/feed'
import {usePreferencesQuery} from '#/state/queries/preferences' import {usePreferencesQuery} from '#/state/queries/preferences'
@@ -308,6 +309,7 @@ export function Explore() {
error: feedsError, error: feedsError,
fetchNextPage: fetchNextFeedsPage, fetchNextPage: fetchNextFeedsPage,
} = useGetPopularFeedsQuery({limit: 10}) } = useGetPopularFeedsQuery({limit: 10})
const gate = useGate()
const isLoadingMoreProfiles = isFetchingNextProfilesPage && !isLoadingProfiles const isLoadingMoreProfiles = isFetchingNextProfilesPage && !isLoadingProfiles
const onLoadMoreProfiles = React.useCallback(async () => { const onLoadMoreProfiles = React.useCallback(async () => {
@@ -348,7 +350,7 @@ export function Explore() {
key: `trending-topics`, key: `trending-topics`,
}) })
if (isNative) { if (isNative && gate('yolo')) {
i.push({ i.push({
type: 'trendingVideos', type: 'trendingVideos',
key: `trending-videos`, key: `trending-videos`,
@@ -508,6 +510,7 @@ export function Explore() {
preferencesError, preferencesError,
hasNextProfilesPage, hasNextProfilesPage,
hasNextFeedsPage, hasNextFeedsPage,
gate,
]) ])
const renderItem = React.useCallback( const renderItem = React.useCallback(