Add Discover interstitial, settings, includes pin for now
This commit is contained in:
@@ -27,14 +27,23 @@ import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
|||||||
import * as Hider from '#/components/moderation/Hider'
|
import * as Hider from '#/components/moderation/Hider'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
|
||||||
|
type DisplayVariant = 'default' | 'compact'
|
||||||
|
|
||||||
export function VideoPostCard({
|
export function VideoPostCard({
|
||||||
post,
|
post,
|
||||||
sourceContext,
|
sourceContext,
|
||||||
moderation,
|
moderation,
|
||||||
|
variant = 'default',
|
||||||
|
onInteract,
|
||||||
}: {
|
}: {
|
||||||
post: AppBskyFeedDefs.PostView
|
post: AppBskyFeedDefs.PostView
|
||||||
sourceContext: VideoFeedSourceContext
|
sourceContext: VideoFeedSourceContext
|
||||||
moderation: ModerationDecision
|
moderation: ModerationDecision
|
||||||
|
variant?: DisplayVariant
|
||||||
|
/**
|
||||||
|
* Callback for metrics and stuff
|
||||||
|
*/
|
||||||
|
onInteract: () => void
|
||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_, i18n} = useLingui()
|
const {_, i18n} = useLingui()
|
||||||
@@ -51,6 +60,7 @@ export function VideoPostCard({
|
|||||||
*/
|
*/
|
||||||
if (!AppBskyEmbedVideo.isView(embed)) return null
|
if (!AppBskyEmbedVideo.isView(embed)) return null
|
||||||
|
|
||||||
|
const isCompact = variant === 'compact'
|
||||||
const text = AppBskyFeedPost.isRecord(post.record) ? post.record?.text : ''
|
const text = AppBskyFeedPost.isRecord(post.record) ? post.record?.text : ''
|
||||||
const likeCount = post?.likeCount ?? 0
|
const likeCount = post?.likeCount ?? 0
|
||||||
const repostCount = post?.repostCount ?? 0
|
const repostCount = post?.repostCount ?? 0
|
||||||
@@ -71,6 +81,9 @@ export function VideoPostCard({
|
|||||||
initialPostUri: post.uri,
|
initialPostUri: post.uri,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
onPress={() => {
|
||||||
|
onInteract()
|
||||||
|
}}
|
||||||
onPressIn={onPressIn}
|
onPressIn={onPressIn}
|
||||||
onPressOut={onPressOut}
|
onPressOut={onPressOut}
|
||||||
style={[
|
style={[
|
||||||
@@ -169,7 +182,7 @@ export function VideoPostCard({
|
|||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{repostCount > 0 && (
|
{!isCompact && repostCount > 0 && (
|
||||||
<View style={[a.flex_row, a.align_center, a.gap_xs]}>
|
<View style={[a.flex_row, a.align_center, a.gap_xs]}>
|
||||||
<Repost size="sm" fill="white" />
|
<Repost size="sm" fill="white" />
|
||||||
<Text style={[a.text_sm, a.font_bold, {color: 'white'}]}>
|
<Text style={[a.text_sm, a.font_bold, {color: 'white'}]}>
|
||||||
@@ -182,7 +195,7 @@ export function VideoPostCard({
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<View style={[a.pr_xs, {paddingTop: 6, gap: 4}]}>
|
<View style={[a.pr_xs, {paddingTop: 6, gap: 4}]}>
|
||||||
{text && (
|
{!isCompact && text && (
|
||||||
<Text style={[a.text_md, a.leading_snug]} numberOfLines={2} emoji>
|
<Text style={[a.text_md, a.leading_snug]} numberOfLines={2} emoji>
|
||||||
{text}
|
{text}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -207,7 +220,11 @@ export function VideoPostCard({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function VideoPostCardPlaceholder() {
|
export function VideoPostCardPlaceholder({
|
||||||
|
variant = 'default',
|
||||||
|
}: {
|
||||||
|
variant?: DisplayVariant
|
||||||
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const black = select(t.name, {
|
const black = select(t.name, {
|
||||||
light: t.palette.black,
|
light: t.palette.black,
|
||||||
@@ -228,42 +245,49 @@ export function VideoPostCardPlaceholder() {
|
|||||||
]}>
|
]}>
|
||||||
<MediaInsetBorder />
|
<MediaInsetBorder />
|
||||||
</View>
|
</View>
|
||||||
<VideoPostCardTextPlaceholder />
|
<VideoPostCardTextPlaceholder variant={variant} />
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function VideoPostCardTextPlaceholder({
|
export function VideoPostCardTextPlaceholder({
|
||||||
author,
|
author,
|
||||||
|
variant,
|
||||||
}: {
|
}: {
|
||||||
author?: AppBskyActorDefs.ProfileViewBasic
|
author?: AppBskyActorDefs.ProfileViewBasic
|
||||||
|
variant?: DisplayVariant
|
||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
|
const isCompact = variant === 'compact'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[a.flex_1]}>
|
<View style={[a.flex_1]}>
|
||||||
<View style={[a.pr_xs, {paddingTop: 8, gap: 6}]}>
|
<View style={[a.pr_xs, {paddingTop: 8, gap: 6}]}>
|
||||||
<View
|
{!isCompact && (
|
||||||
style={[
|
<>
|
||||||
a.w_full,
|
<View
|
||||||
a.rounded_xs,
|
style={[
|
||||||
t.atoms.bg_contrast_50,
|
a.w_full,
|
||||||
{
|
a.rounded_xs,
|
||||||
height: 14,
|
t.atoms.bg_contrast_50,
|
||||||
},
|
{
|
||||||
]}
|
height: 14,
|
||||||
/>
|
},
|
||||||
<View
|
]}
|
||||||
style={[
|
/>
|
||||||
a.w_full,
|
<View
|
||||||
a.rounded_xs,
|
style={[
|
||||||
t.atoms.bg_contrast_50,
|
a.w_full,
|
||||||
{
|
a.rounded_xs,
|
||||||
height: 14,
|
t.atoms.bg_contrast_50,
|
||||||
width: '70%',
|
{
|
||||||
},
|
height: 14,
|
||||||
]}
|
width: '70%',
|
||||||
/>
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
{author ? (
|
{author ? (
|
||||||
<View style={[a.flex_row, a.gap_xs, a.align_center]}>
|
<View style={[a.flex_row, a.gap_xs, a.align_center]}>
|
||||||
<UserAvatar type="user" size={20} avatar={author.avatar} />
|
<UserAvatar type="user" size={20} avatar={author.avatar} />
|
||||||
@@ -298,8 +322,9 @@ export function VideoPostCardTextPlaceholder({
|
|||||||
height: 12,
|
height: 12,
|
||||||
width: '75%',
|
width: '75%',
|
||||||
},
|
},
|
||||||
]}
|
]}>
|
||||||
/>
|
<MediaInsetBorder />
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -0,0 +1,184 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {ScrollView,View} from 'react-native'
|
||||||
|
import {AppBskyEmbedVideo} from '@atproto/api'
|
||||||
|
import {msg, Trans} from '@lingui/macro'
|
||||||
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
|
import {VIDEO_FEED_URI} from '#/lib/constants'
|
||||||
|
import {logEvent} from '#/lib/statsig/statsig'
|
||||||
|
import {useTrendingSettingsApi} from '#/state/preferences/trending'
|
||||||
|
import {useSavedFeeds} from '#/state/queries/feed'
|
||||||
|
import {usePostFeedQuery} from '#/state/queries/post-feed'
|
||||||
|
import {useAddSavedFeedsMutation} from '#/state/queries/preferences'
|
||||||
|
import {atoms as a, useGutters,useTheme} from '#/alf'
|
||||||
|
import {Button, ButtonIcon,ButtonText} from '#/components/Button'
|
||||||
|
import {Divider} from '#/components/Divider'
|
||||||
|
import {Pin_Stroke2_Corner0_Rounded as Pin} from '#/components/icons/Pin'
|
||||||
|
import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times'
|
||||||
|
import {Trending2_Stroke2_Corner2_Rounded as Graph} from '#/components/icons/Trending2'
|
||||||
|
import {Text} from '#/components/Typography'
|
||||||
|
import {
|
||||||
|
VideoPostCard,
|
||||||
|
VideoPostCardPlaceholder,
|
||||||
|
} from '#/components/VideoPostCard'
|
||||||
|
|
||||||
|
const CARD_WIDTH = 100
|
||||||
|
|
||||||
|
export function TrendingVideos() {
|
||||||
|
const t = useTheme()
|
||||||
|
const {_} = useLingui()
|
||||||
|
const gutters = useGutters([0, 'base'])
|
||||||
|
const {data, isLoading, error} = usePostFeedQuery(`feedgen|${VIDEO_FEED_URI}`)
|
||||||
|
const {setTrendingVideoDisabled} = useTrendingSettingsApi()
|
||||||
|
|
||||||
|
const {data: saved} = useSavedFeeds()
|
||||||
|
const isSavedAlready = React.useMemo(() => {
|
||||||
|
return !!saved?.feeds?.some(info => info.config.value === VIDEO_FEED_URI)
|
||||||
|
}, [saved])
|
||||||
|
|
||||||
|
const {mutateAsync: addSavedFeeds, isPending: isPinPending} =
|
||||||
|
useAddSavedFeedsMutation()
|
||||||
|
const pinFeed = React.useCallback(
|
||||||
|
(e: any) => {
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
addSavedFeeds([
|
||||||
|
{
|
||||||
|
type: 'feed',
|
||||||
|
value: VIDEO_FEED_URI,
|
||||||
|
pinned: true,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
// prevent navigation
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
[addSavedFeeds],
|
||||||
|
)
|
||||||
|
|
||||||
|
const hide = React.useCallback(() => {
|
||||||
|
setTrendingVideoDisabled(true)
|
||||||
|
logEvent('trendingVideos:hide', {context: 'interstitial'})
|
||||||
|
}, [setTrendingVideoDisabled])
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.pt_lg,
|
||||||
|
a.pb_md,
|
||||||
|
a.border_t,
|
||||||
|
t.atoms.border_contrast_low,
|
||||||
|
t.atoms.bg_contrast_25,
|
||||||
|
]}>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
gutters,
|
||||||
|
a.pb_sm,
|
||||||
|
a.flex_row,
|
||||||
|
a.align_center,
|
||||||
|
a.justify_between,
|
||||||
|
]}>
|
||||||
|
<View style={[a.flex_1, a.flex_row, a.align_center, a.gap_xs]}>
|
||||||
|
<Graph />
|
||||||
|
<Text style={[a.text_md, a.font_bold, a.leading_snug]}>
|
||||||
|
<Trans>Trending Videos</Trans>
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<Button
|
||||||
|
label={_(msg`Dismiss this section`)}
|
||||||
|
size="tiny"
|
||||||
|
variant="ghost"
|
||||||
|
color="secondary"
|
||||||
|
shape="round"
|
||||||
|
onPress={hide}>
|
||||||
|
<ButtonIcon icon={X} />
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
horizontal
|
||||||
|
showsHorizontalScrollIndicator={false}
|
||||||
|
snapToInterval={(CARD_WIDTH + a.gap_sm.gap) * 2}>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.flex_row,
|
||||||
|
a.gap_sm,
|
||||||
|
a.pb_sm,
|
||||||
|
{
|
||||||
|
paddingLeft: gutters.paddingLeft,
|
||||||
|
paddingRight: gutters.paddingRight,
|
||||||
|
},
|
||||||
|
]}>
|
||||||
|
{isLoading ? (
|
||||||
|
Array(10)
|
||||||
|
.fill(0)
|
||||||
|
.map((_, i) => (
|
||||||
|
<View key={i} style={[{width: CARD_WIDTH}]}>
|
||||||
|
<VideoPostCardPlaceholder variant="compact" />
|
||||||
|
</View>
|
||||||
|
))
|
||||||
|
) : error || !data ? (
|
||||||
|
<Text>
|
||||||
|
<Trans>Whoops! Trending videos failed to load.</Trans>
|
||||||
|
</Text>
|
||||||
|
) : (
|
||||||
|
data.pages
|
||||||
|
.flatMap(page => page.slices)
|
||||||
|
.map(slice => slice.items[0])
|
||||||
|
.filter(Boolean)
|
||||||
|
.filter(item => AppBskyEmbedVideo.isView(item.post.embed))
|
||||||
|
.map(item => (
|
||||||
|
<View key={item.post.uri} style={[{width: CARD_WIDTH}]}>
|
||||||
|
<VideoPostCard
|
||||||
|
variant="compact"
|
||||||
|
post={item.post}
|
||||||
|
moderation={item.moderation}
|
||||||
|
sourceContext={{
|
||||||
|
type: 'feedgen',
|
||||||
|
uri: VIDEO_FEED_URI,
|
||||||
|
}}
|
||||||
|
onInteract={() => {
|
||||||
|
logEvent('trendingVideo:click', {context: 'interstitial'})
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
{!isSavedAlready && (
|
||||||
|
<View style={[gutters, a.pt_xs]}>
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.pt_sm,
|
||||||
|
a.flex_row,
|
||||||
|
a.align_center,
|
||||||
|
a.justify_between,
|
||||||
|
a.gap_md,
|
||||||
|
]}>
|
||||||
|
<Text style={[a.flex_1, a.text_sm, a.leading_snug]}>
|
||||||
|
<Trans>Pin to your home screen for easy access</Trans>
|
||||||
|
</Text>
|
||||||
|
<Button
|
||||||
|
disabled={isPinPending}
|
||||||
|
label={_(msg`Pin`)}
|
||||||
|
size="small"
|
||||||
|
variant="solid"
|
||||||
|
color="primary"
|
||||||
|
onPress={pinFeed}>
|
||||||
|
<ButtonText>{_(msg`Pin`)}</ButtonText>
|
||||||
|
<ButtonIcon icon={Pin} position="right" />
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -249,6 +249,15 @@ export type LogEvents = {
|
|||||||
'recommendedTopic:click': {
|
'recommendedTopic:click': {
|
||||||
context: 'explore'
|
context: 'explore'
|
||||||
}
|
}
|
||||||
|
'trendingVideos:show': {
|
||||||
|
context: 'settings'
|
||||||
|
}
|
||||||
|
'trendingVideos:hide': {
|
||||||
|
context: 'settings' | 'interstitial' | 'explore'
|
||||||
|
}
|
||||||
|
'trendingVideo:click': {
|
||||||
|
context: 'interstitial' | 'explore'
|
||||||
|
}
|
||||||
|
|
||||||
'progressGuide:hide': {}
|
'progressGuide:hide': {}
|
||||||
'progressGuide:followDialog:open': {}
|
'progressGuide:followDialog:open': {}
|
||||||
|
|||||||
@@ -37,8 +37,9 @@ export function ContentAndMediaSettingsScreen({}: Props) {
|
|||||||
const inAppBrowserPref = useInAppBrowser()
|
const inAppBrowserPref = useInAppBrowser()
|
||||||
const setUseInAppBrowser = useSetInAppBrowser()
|
const setUseInAppBrowser = useSetInAppBrowser()
|
||||||
const {enabled: trendingEnabled} = useTrendingConfig()
|
const {enabled: trendingEnabled} = useTrendingConfig()
|
||||||
const {trendingDisabled} = useTrendingSettings()
|
const {trendingDisabled, trendingVideoDisabled} = useTrendingSettings()
|
||||||
const {setTrendingDisabled} = useTrendingSettingsApi()
|
const {setTrendingDisabled, setTrendingVideoDisabled} =
|
||||||
|
useTrendingSettingsApi()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout.Screen>
|
<Layout.Screen>
|
||||||
@@ -138,6 +139,27 @@ export function ContentAndMediaSettingsScreen({}: Props) {
|
|||||||
<Toggle.Platform />
|
<Toggle.Platform />
|
||||||
</SettingsList.Item>
|
</SettingsList.Item>
|
||||||
</Toggle.Item>
|
</Toggle.Item>
|
||||||
|
<Toggle.Item
|
||||||
|
name="show_trending_videos"
|
||||||
|
label={_(msg`Enable trending videos`)}
|
||||||
|
value={!trendingVideoDisabled}
|
||||||
|
onChange={value => {
|
||||||
|
const hide = Boolean(!value)
|
||||||
|
if (hide) {
|
||||||
|
logEvent('trendingVideos:hide', {context: 'settings'})
|
||||||
|
} else {
|
||||||
|
logEvent('trendingVideos:show', {context: 'settings'})
|
||||||
|
}
|
||||||
|
setTrendingVideoDisabled(hide)
|
||||||
|
}}>
|
||||||
|
<SettingsList.Item>
|
||||||
|
<SettingsList.ItemIcon icon={Graph} />
|
||||||
|
<SettingsList.ItemText>
|
||||||
|
<Trans>Enable trending videos</Trans>
|
||||||
|
</SettingsList.ItemText>
|
||||||
|
<Toggle.Platform />
|
||||||
|
</SettingsList.Item>
|
||||||
|
</Toggle.Item>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</SettingsList.Container>
|
</SettingsList.Container>
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ const schema = z.object({
|
|||||||
/** @deprecated */
|
/** @deprecated */
|
||||||
mutedThreads: z.array(z.string()),
|
mutedThreads: z.array(z.string()),
|
||||||
trendingDisabled: z.boolean().optional(),
|
trendingDisabled: z.boolean().optional(),
|
||||||
|
trendingVideoDisabled: z.boolean().optional(),
|
||||||
})
|
})
|
||||||
export type Schema = z.infer<typeof schema>
|
export type Schema = z.infer<typeof schema>
|
||||||
|
|
||||||
@@ -172,6 +173,7 @@ export const defaults: Schema = {
|
|||||||
hasCheckedForStarterPack: false,
|
hasCheckedForStarterPack: false,
|
||||||
subtitlesEnabled: true,
|
subtitlesEnabled: true,
|
||||||
trendingDisabled: false,
|
trendingDisabled: false,
|
||||||
|
trendingVideoDisabled: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
export function tryParse(rawData: string): Schema | undefined {
|
export function tryParse(rawData: string): Schema | undefined {
|
||||||
|
|||||||
@@ -4,18 +4,27 @@ import * as persisted from '#/state/persisted'
|
|||||||
|
|
||||||
type StateContext = {
|
type StateContext = {
|
||||||
trendingDisabled: Exclude<persisted.Schema['trendingDisabled'], undefined>
|
trendingDisabled: Exclude<persisted.Schema['trendingDisabled'], undefined>
|
||||||
|
trendingVideoDisabled: Exclude<
|
||||||
|
persisted.Schema['trendingVideoDisabled'],
|
||||||
|
undefined
|
||||||
|
>
|
||||||
}
|
}
|
||||||
type ApiContext = {
|
type ApiContext = {
|
||||||
setTrendingDisabled(
|
setTrendingDisabled(
|
||||||
hidden: Exclude<persisted.Schema['trendingDisabled'], undefined>,
|
hidden: Exclude<persisted.Schema['trendingDisabled'], undefined>,
|
||||||
): void
|
): void
|
||||||
|
setTrendingVideoDisabled(
|
||||||
|
hidden: Exclude<persisted.Schema['trendingVideoDisabled'], undefined>,
|
||||||
|
): void
|
||||||
}
|
}
|
||||||
|
|
||||||
const StateContext = React.createContext<StateContext>({
|
const StateContext = React.createContext<StateContext>({
|
||||||
trendingDisabled: Boolean(persisted.defaults.trendingDisabled),
|
trendingDisabled: Boolean(persisted.defaults.trendingDisabled),
|
||||||
|
trendingVideoDisabled: Boolean(persisted.defaults.trendingVideoDisabled),
|
||||||
})
|
})
|
||||||
const ApiContext = React.createContext<ApiContext>({
|
const ApiContext = React.createContext<ApiContext>({
|
||||||
setTrendingDisabled() {},
|
setTrendingDisabled() {},
|
||||||
|
setTrendingVideoDisabled() {},
|
||||||
})
|
})
|
||||||
|
|
||||||
function usePersistedBooleanValue<T extends keyof persisted.Schema>(key: T) {
|
function usePersistedBooleanValue<T extends keyof persisted.Schema>(key: T) {
|
||||||
@@ -43,14 +52,19 @@ function usePersistedBooleanValue<T extends keyof persisted.Schema>(key: T) {
|
|||||||
export function Provider({children}: React.PropsWithChildren<{}>) {
|
export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||||
const [trendingDisabled, setTrendingDisabled] =
|
const [trendingDisabled, setTrendingDisabled] =
|
||||||
usePersistedBooleanValue('trendingDisabled')
|
usePersistedBooleanValue('trendingDisabled')
|
||||||
|
const [trendingVideoDisabled, setTrendingVideoDisabled] =
|
||||||
|
usePersistedBooleanValue('trendingVideoDisabled')
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Context
|
* Context
|
||||||
*/
|
*/
|
||||||
const state = React.useMemo(() => ({trendingDisabled}), [trendingDisabled])
|
const state = React.useMemo(
|
||||||
|
() => ({trendingDisabled, trendingVideoDisabled}),
|
||||||
|
[trendingDisabled, trendingVideoDisabled],
|
||||||
|
)
|
||||||
const api = React.useMemo(
|
const api = React.useMemo(
|
||||||
() => ({setTrendingDisabled}),
|
() => ({setTrendingDisabled, setTrendingVideoDisabled}),
|
||||||
[setTrendingDisabled],
|
[setTrendingDisabled, setTrendingVideoDisabled],
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ import {
|
|||||||
PostFeedVideoGridRowPlaceholder,
|
PostFeedVideoGridRowPlaceholder,
|
||||||
} from '#/components/feeds/PostFeedVideoGridRow'
|
} from '#/components/feeds/PostFeedVideoGridRow'
|
||||||
import {TrendingInterstitial} from '#/components/interstitials/Trending'
|
import {TrendingInterstitial} from '#/components/interstitials/Trending'
|
||||||
|
import {TrendingVideos as TrendingVideosInterstitial} from '#/components/interstitials/TrendingVideos'
|
||||||
import {DiscoverFallbackHeader} from './DiscoverFallbackHeader'
|
import {DiscoverFallbackHeader} from './DiscoverFallbackHeader'
|
||||||
import {FeedShutdownMsg} from './FeedShutdownMsg'
|
import {FeedShutdownMsg} from './FeedShutdownMsg'
|
||||||
import {PostFeedErrorMessage} from './PostFeedErrorMessage'
|
import {PostFeedErrorMessage} from './PostFeedErrorMessage'
|
||||||
@@ -116,6 +117,10 @@ type FeedRow =
|
|||||||
type: 'interstitialTrending'
|
type: 'interstitialTrending'
|
||||||
key: string
|
key: string
|
||||||
}
|
}
|
||||||
|
| {
|
||||||
|
type: 'interstitialTrendingVideos'
|
||||||
|
key: string
|
||||||
|
}
|
||||||
|
|
||||||
export function getFeedPostSlice(feedRow: FeedRow): FeedPostSlice | null {
|
export function getFeedPostSlice(feedRow: FeedRow): FeedPostSlice | null {
|
||||||
if (feedRow.type === 'sliceItem') {
|
if (feedRow.type === 'sliceItem') {
|
||||||
@@ -287,7 +292,7 @@ let PostFeed = ({
|
|||||||
const showProgressIntersitial =
|
const showProgressIntersitial =
|
||||||
(followProgressGuide || followAndLikeProgressGuide) && !isDesktop
|
(followProgressGuide || followAndLikeProgressGuide) && !isDesktop
|
||||||
|
|
||||||
const {trendingDisabled} = useTrendingSettings()
|
const {trendingDisabled, trendingVideoDisabled} = useTrendingSettings()
|
||||||
|
|
||||||
const feedItems: FeedRow[] = React.useMemo(() => {
|
const feedItems: FeedRow[] = React.useMemo(() => {
|
||||||
let feedKind: 'following' | 'discover' | 'profile' | 'thevids' | undefined
|
let feedKind: 'following' | 'discover' | 'profile' | 'thevids' | undefined
|
||||||
@@ -380,6 +385,13 @@ let PostFeed = ({
|
|||||||
'interstitial2-' + sliceIndex + '-' + lastFetchedAt,
|
'interstitial2-' + sliceIndex + '-' + lastFetchedAt,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
} else if (sliceIndex === 15) {
|
||||||
|
if (isNative && !trendingVideoDisabled) {
|
||||||
|
arr.push({
|
||||||
|
type: 'interstitialTrendingVideos',
|
||||||
|
key: 'interstitial-' + sliceIndex + '-' + lastFetchedAt,
|
||||||
|
})
|
||||||
|
}
|
||||||
} else if (sliceIndex === 30) {
|
} else if (sliceIndex === 30) {
|
||||||
arr.push({
|
arr.push({
|
||||||
type: 'interstitialFollows',
|
type: 'interstitialFollows',
|
||||||
@@ -475,6 +487,7 @@ let PostFeed = ({
|
|||||||
hasSession,
|
hasSession,
|
||||||
showProgressIntersitial,
|
showProgressIntersitial,
|
||||||
trendingDisabled,
|
trendingDisabled,
|
||||||
|
trendingVideoDisabled,
|
||||||
gtTablet,
|
gtTablet,
|
||||||
gtMobile,
|
gtMobile,
|
||||||
isVideoFeed,
|
isVideoFeed,
|
||||||
@@ -566,6 +579,8 @@ let PostFeed = ({
|
|||||||
return <ProgressGuide />
|
return <ProgressGuide />
|
||||||
} else if (row.type === 'interstitialTrending') {
|
} else if (row.type === 'interstitialTrending') {
|
||||||
return <TrendingInterstitial />
|
return <TrendingInterstitial />
|
||||||
|
} else if (row.type === 'interstitialTrendingVideos') {
|
||||||
|
return <TrendingVideosInterstitial />
|
||||||
} else if (row.type === 'sliceItem') {
|
} else if (row.type === 'sliceItem') {
|
||||||
const slice = row.slice
|
const slice = row.slice
|
||||||
if (slice.isFallbackMarker) {
|
if (slice.isFallbackMarker) {
|
||||||
|
|||||||
Reference in New Issue
Block a user