yolo (#7499)
* tweaks to constants (#7478) * add did * use correct did * typo * tweak * Prevent Drawer gesture conflicting with Suggestions scroll (#7468) * Extract BlockDrawerGeesture * Block drawer when scrolling interstitials (cherry picked from commit9e3f2f4374) * yolo interstitial * yolo mode * right swipe * fix nav gesture * vibe controls * collapsible post text * rm blurview, cover for tall videos * smarter video source handling * use thumbnails, improve perf significantly * better android loading * improve aspect ratio * optimize source changes * rm spinner on ios * whoops, remove debug `false` * FIX WRONG VIDEOS SHOWING UP * don't spring on way down * release video players when leaving screen * remove jank animation * Add grid * improve contract, fix double tap * Filter out posts without videos * Only do grid on native * Pipe through feedSourceUri and link to feed * Handle passed through params * Partial revert, just filter posts to start at index * Clean up cards, remove entry interstitial * Tweak handle * Change constant name * Rename some things * Make types legit * Clean up more naming * Add placeholder for grid view * Handle web, set up new organization * Begin work on Header * Replace types * Squashed commit of the following: commit3d1be4c0f1Author: Samuel Newman <mozzius@protonmail.com> Date: Fri Jan 17 01:08:05 2025 +0000 extend animation commitc9f199413bAuthor: Samuel Newman <mozzius@protonmail.com> Date: Fri Jan 17 01:01:24 2025 +0000 fix gap commit22e520795fAuthor: Samuel Newman <mozzius@protonmail.com> Date: Fri Jan 17 00:50:16 2025 +0000 thinner bar, format time commitc32427f214Author: Samuel Newman <mozzius@protonmail.com> Date: Fri Jan 17 00:47:57 2025 +0000 fix 2 in 3 screens commitcbf84c08d6Author: Samuel Newman <mozzius@protonmail.com> Date: Fri Jan 17 00:45:46 2025 +0000 rm unneeded var commit7e0e100177Author: Samuel Newman <mozzius@protonmail.com> Date: Fri Jan 17 00:41:18 2025 +0000 scrubberrrrr * use white with opacity rather than gray * Simultaneous gesture * cleanup attempt * fix jank * link to profile on press * fix jitter fr this time * mostly fix android flicker * Maybe fix row generation * Add content hider to video card * emoji in post text * reduce update rate * fix type error * Fix grid layout trailing single item * Add Discover interstitial, settings, includes pin for now * Explore interstitial, handle dimissal, pinning, compact card * Only use grid placeholder on native * Update events * Add feature gate * android nav bar fixes + lower update speed * fix interval + decel rate on interstitials * attempt to fix broken scrub on android (not working) * follow button * Part out the interstitials for perf, add view more * Remove prod web route * Wrap interstitials with BlockDrawerGesture * Bring video cropping in line with images (#7462) * Mimic image cropping for videos on web * Same on native * Rename variables for clarity * Fix Android scrubbing * Add FeedFeedbackProvider * Remove swipe gesture * fix light status bar behaviour * bump * feedback * Copy pasta to new location * Copy pasta part deux * Filter only videos * Make whole text clickable to expand (cherry picked from commit 4cf31120779f4e06eb4c296b3d4b53814d432b07) * move scrubber to own file * end card * add icon to end card * add min view time to viewability config * play haptic on like * tweak feedback * tweak feedback again * Moderation (cherry picked from commit 6b6b471cfb363031284b3e7a1f6e0ade3ac4ae47) * remove bad check * fix feedback for new video grid * change prop name to items as well * Simplify logic * Fix mod footer * Give scrubber more space on android * Add subtle track behind scrubber, adjust opacity * wire in feed context again... * Add better a11y desc to card * Fix key issue * Update a11y copy * Fix scrubber height * improve scrubber animation * Make follow button more obvious * Make header back button more clear * Disable interactions with actual video el * keep content away from the bottom safe area * fix blur * fix moderation issue * improve contrast on mod screen * Make moderation static per item * Memoize rows * Optimizations * Take video moderation into account * Only blur titles for list blur * Change copy * Bump blur radius * animate text in both directions * Rm unused field * Filter by root early * Refactor for clarity * add compose prompt to scrubber * rm log * tweak gradient * Bump SDK, use contentMode to power video feed * Ensure ProfileFeed view also supports video feed * improve scrubber on android * rm border from footer * Update prod video feed did * Separate caches * Add lil hover to View More * Fix undefined logic, remove header for interstitial * Ungate * Fix stuckness * remove extra useless map * Fix effect cleanup * Send seen without cleanup * Simplify react stuff * Earlier early return to avoid loading flash * remove scrubber placeholder * Remove opacity hack * Render useEvent conditionally * Fix Android flash --------- Co-authored-by: dan <dan.abramov@gmail.com> Co-authored-by: Samuel Newman <mozzius@protonmail.com> Co-authored-by: Eric Bailey <git@esb.lol>
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
import React from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {AppBskyActorDefs} from '@atproto/api'
|
||||
import {AppBskyActorDefs, AppBskyFeedDefs} from '@atproto/api'
|
||||
import {msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {NavigationProp, useNavigation} from '@react-navigation/native'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
|
||||
import {VIDEO_FEED_URIS} from '#/lib/constants'
|
||||
import {ComposeIcon2} from '#/lib/icons'
|
||||
import {getRootNavigation, getTabState, TabState} from '#/lib/routes/helpers'
|
||||
import {AllNavigatorParams} from '#/lib/routes/types'
|
||||
@@ -15,6 +16,7 @@ import {isNative} from '#/platform/detection'
|
||||
import {listenSoftReset} from '#/state/events'
|
||||
import {FeedFeedbackProvider, useFeedFeedback} from '#/state/feed-feedback'
|
||||
import {useSetHomeBadge} from '#/state/home-badge'
|
||||
import {SavedFeedSourceInfo} from '#/state/queries/feed'
|
||||
import {RQKEY as FEED_RQKEY} from '#/state/queries/post-feed'
|
||||
import {FeedDescriptor, FeedParams} from '#/state/queries/post-feed'
|
||||
import {truncateAndInvalidate} from '#/state/queries/util'
|
||||
@@ -39,6 +41,7 @@ export function FeedPage({
|
||||
renderEmptyState,
|
||||
renderEndOfFeed,
|
||||
savedFeedConfig,
|
||||
feedInfo,
|
||||
}: {
|
||||
testID?: string
|
||||
feed: FeedDescriptor
|
||||
@@ -48,6 +51,7 @@ export function FeedPage({
|
||||
renderEmptyState: () => JSX.Element
|
||||
renderEndOfFeed?: () => JSX.Element
|
||||
savedFeedConfig?: AppBskyActorDefs.SavedFeed
|
||||
feedInfo: SavedFeedSourceInfo
|
||||
}) {
|
||||
const {hasSession} = useSession()
|
||||
const {_} = useLingui()
|
||||
@@ -61,6 +65,13 @@ export function FeedPage({
|
||||
const scrollElRef = React.useRef<ListMethods>(null)
|
||||
const [hasNew, setHasNew] = React.useState(false)
|
||||
const setHomeBadge = useSetHomeBadge()
|
||||
const isVideoFeed = React.useMemo(() => {
|
||||
const isBskyVideoFeed = VIDEO_FEED_URIS.includes(feedInfo.uri)
|
||||
const feedIsVideoMode =
|
||||
feedInfo.contentMode === AppBskyFeedDefs.CONTENTMODEVIDEO
|
||||
const _isVideoFeed = isBskyVideoFeed || feedIsVideoMode
|
||||
return isNative && _isVideoFeed
|
||||
}, [feedInfo])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isPageFocused) {
|
||||
@@ -134,6 +145,7 @@ export function FeedPage({
|
||||
renderEndOfFeed={renderEndOfFeed}
|
||||
headerOffset={headerOffset}
|
||||
savedFeedConfig={savedFeedConfig}
|
||||
isVideoFeed={isVideoFeed}
|
||||
/>
|
||||
</FeedFeedbackProvider>
|
||||
</MainScrollProvider>
|
||||
|
||||
@@ -40,7 +40,6 @@ export function PostThreadComposePrompt({
|
||||
t.atoms.border_contrast_low,
|
||||
t.atoms.bg,
|
||||
]}
|
||||
onPressIn={ios(() => playHaptic('Light'))}
|
||||
onPress={() => {
|
||||
onPressCompose()
|
||||
playHaptic('Light')
|
||||
|
||||
+197
-76
@@ -9,7 +9,7 @@ import {
|
||||
View,
|
||||
ViewStyle,
|
||||
} from 'react-native'
|
||||
import {AppBskyActorDefs} from '@atproto/api'
|
||||
import {AppBskyActorDefs, AppBskyEmbedVideo} from '@atproto/api'
|
||||
import {msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
@@ -20,7 +20,7 @@ import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
|
||||
import {logEvent} from '#/lib/statsig/statsig'
|
||||
import {useTheme} from '#/lib/ThemeContext'
|
||||
import {logger} from '#/logger'
|
||||
import {isIOS, isWeb} from '#/platform/detection'
|
||||
import {isIOS, isNative, isWeb} from '#/platform/detection'
|
||||
import {listenPostCreated} from '#/state/events'
|
||||
import {useFeedFeedbackContext} from '#/state/feed-feedback'
|
||||
import {useTrendingSettings} from '#/state/preferences/trending'
|
||||
@@ -29,18 +29,24 @@ import {
|
||||
FeedDescriptor,
|
||||
FeedParams,
|
||||
FeedPostSlice,
|
||||
FeedPostSliceItem,
|
||||
pollLatest,
|
||||
RQKEY,
|
||||
usePostFeedQuery,
|
||||
} from '#/state/queries/post-feed'
|
||||
import {useSession} from '#/state/session'
|
||||
import {useProgressGuide} from '#/state/shell/progress-guide'
|
||||
import {List, ListRef} from '#/view/com/util/List'
|
||||
import {PostFeedLoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
|
||||
import {LoadMoreRetryBtn} from '#/view/com/util/LoadMoreRetryBtn'
|
||||
import {useBreakpoints} from '#/alf'
|
||||
import {ProgressGuide, SuggestedFollows} from '#/components/FeedInterstitials'
|
||||
import {
|
||||
PostFeedVideoGridRow,
|
||||
PostFeedVideoGridRowPlaceholder,
|
||||
} from '#/components/feeds/PostFeedVideoGridRow'
|
||||
import {TrendingInterstitial} from '#/components/interstitials/Trending'
|
||||
import {List, ListRef} from '../util/List'
|
||||
import {PostFeedLoadingPlaceholder} from '../util/LoadingPlaceholder'
|
||||
import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
|
||||
import {TrendingVideos as TrendingVideosInterstitial} from '#/components/interstitials/TrendingVideos'
|
||||
import {DiscoverFallbackHeader} from './DiscoverFallbackHeader'
|
||||
import {FeedShutdownMsg} from './FeedShutdownMsg'
|
||||
import {PostFeedErrorMessage} from './PostFeedErrorMessage'
|
||||
@@ -69,7 +75,7 @@ type FeedRow =
|
||||
key: string
|
||||
}
|
||||
| {
|
||||
type: 'slice'
|
||||
type: 'slice' // TODO can we remove?
|
||||
key: string
|
||||
slice: FeedPostSlice
|
||||
}
|
||||
@@ -80,6 +86,17 @@ type FeedRow =
|
||||
indexInSlice: number
|
||||
showReplyTo: boolean
|
||||
}
|
||||
| {
|
||||
type: 'videoGridRowPlaceholder'
|
||||
key: string
|
||||
}
|
||||
| {
|
||||
type: 'videoGridRow'
|
||||
key: string
|
||||
items: FeedPostSliceItem[]
|
||||
sourceFeedUri: string
|
||||
feedContexts: (string | undefined)[]
|
||||
}
|
||||
| {
|
||||
type: 'sliceViewFullThread'
|
||||
key: string
|
||||
@@ -97,12 +114,28 @@ type FeedRow =
|
||||
type: 'interstitialTrending'
|
||||
key: string
|
||||
}
|
||||
| {
|
||||
type: 'interstitialTrendingVideos'
|
||||
key: string
|
||||
}
|
||||
|
||||
export function getFeedPostSlice(feedRow: FeedRow): FeedPostSlice | null {
|
||||
export function getItemsForFeedback(feedRow: FeedRow):
|
||||
| {
|
||||
item: FeedPostSliceItem
|
||||
feedContext: string | undefined
|
||||
}[] {
|
||||
if (feedRow.type === 'sliceItem') {
|
||||
return feedRow.slice
|
||||
return feedRow.slice.items.map(item => ({
|
||||
item,
|
||||
feedContext: feedRow.slice.feedContext,
|
||||
}))
|
||||
} else if (feedRow.type === 'videoGridRow') {
|
||||
return feedRow.items.map((item, i) => ({
|
||||
item,
|
||||
feedContext: feedRow.feedContexts[i],
|
||||
}))
|
||||
} else {
|
||||
return null
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,6 +164,7 @@ let PostFeed = ({
|
||||
extraData,
|
||||
savedFeedConfig,
|
||||
initialNumToRender: initialNumToRenderOverride,
|
||||
isVideoFeed = false,
|
||||
}: {
|
||||
feed: FeedDescriptor
|
||||
feedParams?: FeedParams
|
||||
@@ -152,6 +186,7 @@ let PostFeed = ({
|
||||
extraData?: any
|
||||
savedFeedConfig?: AppBskyActorDefs.SavedFeed
|
||||
initialNumToRender?: number
|
||||
isVideoFeed?: boolean
|
||||
}): React.ReactNode => {
|
||||
const theme = useTheme()
|
||||
const {_} = useLingui()
|
||||
@@ -163,8 +198,10 @@ let PostFeed = ({
|
||||
const checkForNewRef = React.useRef<(() => void) | null>(null)
|
||||
const lastFetchRef = React.useRef<number>(Date.now())
|
||||
const [feedType, feedUri, feedTab] = feed.split('|')
|
||||
const {gtTablet} = useBreakpoints()
|
||||
const {gtMobile, gtTablet} = useBreakpoints()
|
||||
const areVideoFeedsEnabled = isNative
|
||||
|
||||
const feedCacheKey = feedParams?.feedCacheKey
|
||||
const opts = React.useMemo(
|
||||
() => ({enabled, ignoreFilterFor}),
|
||||
[enabled, ignoreFilterFor],
|
||||
@@ -267,10 +304,10 @@ let PostFeed = ({
|
||||
const showProgressIntersitial =
|
||||
(followProgressGuide || followAndLikeProgressGuide) && !isDesktop
|
||||
|
||||
const {trendingDisabled} = useTrendingSettings()
|
||||
const {trendingDisabled, trendingVideoDisabled} = useTrendingSettings()
|
||||
|
||||
const feedItems: FeedRow[] = React.useMemo(() => {
|
||||
let feedKind: 'following' | 'discover' | 'profile' | undefined
|
||||
let feedKind: 'following' | 'discover' | 'profile' | 'thevids' | undefined
|
||||
if (feedType === 'following') {
|
||||
feedKind = 'following'
|
||||
} else if (feedUri === DISCOVER_FEED_URI) {
|
||||
@@ -303,81 +340,132 @@ let PostFeed = ({
|
||||
})
|
||||
} else if (data) {
|
||||
let sliceIndex = -1
|
||||
for (const page of data?.pages) {
|
||||
for (const slice of page.slices) {
|
||||
sliceIndex++
|
||||
|
||||
if (hasSession) {
|
||||
if (feedKind === 'discover') {
|
||||
if (sliceIndex === 0) {
|
||||
if (showProgressIntersitial) {
|
||||
if (isVideoFeed) {
|
||||
const videos: {
|
||||
item: FeedPostSliceItem
|
||||
feedContext: string | undefined
|
||||
}[] = []
|
||||
for (const page of data.pages) {
|
||||
for (const slice of page.slices) {
|
||||
const item = slice.items.at(0)
|
||||
if (item && AppBskyEmbedVideo.isView(item.post.embed)) {
|
||||
videos.push({item, feedContext: slice.feedContext})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const rows: {
|
||||
item: FeedPostSliceItem
|
||||
feedContext: string | undefined
|
||||
}[][] = []
|
||||
for (let i = 0; i < videos.length; i++) {
|
||||
const video = videos[i]
|
||||
const item = video.item
|
||||
const cols = gtMobile ? 3 : 2
|
||||
const rowItem = {item, feedContext: video.feedContext}
|
||||
if (i % cols === 0) {
|
||||
rows.push([rowItem])
|
||||
} else {
|
||||
rows[rows.length - 1].push(rowItem)
|
||||
}
|
||||
}
|
||||
|
||||
for (const row of rows) {
|
||||
sliceIndex++
|
||||
arr.push({
|
||||
type: 'videoGridRow',
|
||||
key: row.map(r => r.item._reactKey).join('-'),
|
||||
items: row.map(r => r.item),
|
||||
sourceFeedUri: feedUri,
|
||||
feedContexts: row.map(r => r.feedContext),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
for (const page of data?.pages) {
|
||||
for (const slice of page.slices) {
|
||||
sliceIndex++
|
||||
|
||||
if (hasSession) {
|
||||
if (feedKind === 'discover') {
|
||||
if (sliceIndex === 0) {
|
||||
if (showProgressIntersitial) {
|
||||
arr.push({
|
||||
type: 'interstitialProgressGuide',
|
||||
key: 'interstitial-' + sliceIndex + '-' + lastFetchedAt,
|
||||
})
|
||||
}
|
||||
if (!gtTablet && !trendingDisabled) {
|
||||
arr.push({
|
||||
type: 'interstitialTrending',
|
||||
key:
|
||||
'interstitial2-' + sliceIndex + '-' + lastFetchedAt,
|
||||
})
|
||||
}
|
||||
} else if (sliceIndex === 15) {
|
||||
if (areVideoFeedsEnabled && !trendingVideoDisabled) {
|
||||
arr.push({
|
||||
type: 'interstitialTrendingVideos',
|
||||
key: 'interstitial-' + sliceIndex + '-' + lastFetchedAt,
|
||||
})
|
||||
}
|
||||
} else if (sliceIndex === 30) {
|
||||
arr.push({
|
||||
type: 'interstitialProgressGuide',
|
||||
type: 'interstitialFollows',
|
||||
key: 'interstitial-' + sliceIndex + '-' + lastFetchedAt,
|
||||
})
|
||||
}
|
||||
if (!gtTablet && !trendingDisabled) {
|
||||
} else if (feedKind === 'profile') {
|
||||
if (sliceIndex === 5) {
|
||||
arr.push({
|
||||
type: 'interstitialTrending',
|
||||
key: 'interstitial2-' + sliceIndex + '-' + lastFetchedAt,
|
||||
type: 'interstitialFollows',
|
||||
key: 'interstitial-' + sliceIndex + '-' + lastFetchedAt,
|
||||
})
|
||||
}
|
||||
} else if (sliceIndex === 30) {
|
||||
arr.push({
|
||||
type: 'interstitialFollows',
|
||||
key: 'interstitial-' + sliceIndex + '-' + lastFetchedAt,
|
||||
})
|
||||
}
|
||||
} else if (feedKind === 'profile') {
|
||||
if (sliceIndex === 5) {
|
||||
arr.push({
|
||||
type: 'interstitialFollows',
|
||||
key: 'interstitial-' + sliceIndex + '-' + lastFetchedAt,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (slice.isIncompleteThread && slice.items.length >= 3) {
|
||||
const beforeLast = slice.items.length - 2
|
||||
const last = slice.items.length - 1
|
||||
arr.push({
|
||||
type: 'sliceItem',
|
||||
key: slice.items[0]._reactKey,
|
||||
slice: slice,
|
||||
indexInSlice: 0,
|
||||
showReplyTo: false,
|
||||
})
|
||||
arr.push({
|
||||
type: 'sliceViewFullThread',
|
||||
key: slice._reactKey + '-viewFullThread',
|
||||
uri: slice.items[0].uri,
|
||||
})
|
||||
arr.push({
|
||||
type: 'sliceItem',
|
||||
key: slice.items[beforeLast]._reactKey,
|
||||
slice: slice,
|
||||
indexInSlice: beforeLast,
|
||||
showReplyTo:
|
||||
slice.items[beforeLast].parentAuthor?.did !==
|
||||
slice.items[beforeLast].post.author.did,
|
||||
})
|
||||
arr.push({
|
||||
type: 'sliceItem',
|
||||
key: slice.items[last]._reactKey,
|
||||
slice: slice,
|
||||
indexInSlice: last,
|
||||
showReplyTo: false,
|
||||
})
|
||||
} else {
|
||||
for (let i = 0; i < slice.items.length; i++) {
|
||||
if (slice.isIncompleteThread && slice.items.length >= 3) {
|
||||
const beforeLast = slice.items.length - 2
|
||||
const last = slice.items.length - 1
|
||||
arr.push({
|
||||
type: 'sliceItem',
|
||||
key: slice.items[i]._reactKey,
|
||||
key: slice.items[0]._reactKey,
|
||||
slice: slice,
|
||||
indexInSlice: i,
|
||||
showReplyTo: i === 0,
|
||||
indexInSlice: 0,
|
||||
showReplyTo: false,
|
||||
})
|
||||
arr.push({
|
||||
type: 'sliceViewFullThread',
|
||||
key: slice._reactKey + '-viewFullThread',
|
||||
uri: slice.items[0].uri,
|
||||
})
|
||||
arr.push({
|
||||
type: 'sliceItem',
|
||||
key: slice.items[beforeLast]._reactKey,
|
||||
slice: slice,
|
||||
indexInSlice: beforeLast,
|
||||
showReplyTo:
|
||||
slice.items[beforeLast].parentAuthor?.did !==
|
||||
slice.items[beforeLast].post.author.did,
|
||||
})
|
||||
arr.push({
|
||||
type: 'sliceItem',
|
||||
key: slice.items[last]._reactKey,
|
||||
slice: slice,
|
||||
indexInSlice: last,
|
||||
showReplyTo: false,
|
||||
})
|
||||
} else {
|
||||
for (let i = 0; i < slice.items.length; i++) {
|
||||
arr.push({
|
||||
type: 'sliceItem',
|
||||
key: slice.items[i]._reactKey,
|
||||
slice: slice,
|
||||
indexInSlice: i,
|
||||
showReplyTo: i === 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -390,10 +478,17 @@ let PostFeed = ({
|
||||
})
|
||||
}
|
||||
} else {
|
||||
arr.push({
|
||||
type: 'loading',
|
||||
key: 'loading',
|
||||
})
|
||||
if (isVideoFeed) {
|
||||
arr.push({
|
||||
type: 'videoGridRowPlaceholder',
|
||||
key: 'videoGridRowPlaceholder',
|
||||
})
|
||||
} else {
|
||||
arr.push({
|
||||
type: 'loading',
|
||||
key: 'loading',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return arr
|
||||
@@ -409,7 +504,11 @@ let PostFeed = ({
|
||||
hasSession,
|
||||
showProgressIntersitial,
|
||||
trendingDisabled,
|
||||
trendingVideoDisabled,
|
||||
gtTablet,
|
||||
gtMobile,
|
||||
isVideoFeed,
|
||||
areVideoFeedsEnabled,
|
||||
])
|
||||
|
||||
// events
|
||||
@@ -498,6 +597,8 @@ let PostFeed = ({
|
||||
return <ProgressGuide />
|
||||
} else if (row.type === 'interstitialTrending') {
|
||||
return <TrendingInterstitial />
|
||||
} else if (row.type === 'interstitialTrendingVideos') {
|
||||
return <TrendingVideosInterstitial />
|
||||
} else if (row.type === 'sliceItem') {
|
||||
const slice = row.slice
|
||||
if (slice.isFallbackMarker) {
|
||||
@@ -532,6 +633,25 @@ let PostFeed = ({
|
||||
)
|
||||
} else if (row.type === 'sliceViewFullThread') {
|
||||
return <ViewFullThread uri={row.uri} />
|
||||
} else if (row.type === 'videoGridRowPlaceholder') {
|
||||
return (
|
||||
<View>
|
||||
<PostFeedVideoGridRowPlaceholder />
|
||||
<PostFeedVideoGridRowPlaceholder />
|
||||
<PostFeedVideoGridRowPlaceholder />
|
||||
</View>
|
||||
)
|
||||
} else if (row.type === 'videoGridRow') {
|
||||
return (
|
||||
<PostFeedVideoGridRow
|
||||
items={row.items}
|
||||
sourceContext={{
|
||||
type: 'feedgen',
|
||||
uri: row.sourceFeedUri,
|
||||
sourceInterstitial: feedCacheKey ?? 'none',
|
||||
}}
|
||||
/>
|
||||
)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
@@ -545,6 +665,7 @@ let PostFeed = ({
|
||||
_,
|
||||
onPressRetryLoadMore,
|
||||
feedUri,
|
||||
feedCacheKey,
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -152,6 +152,9 @@ let List = React.forwardRef<ListMethods, ListProps>(
|
||||
|
||||
return (
|
||||
<FlatList_INTERNAL
|
||||
showsVerticalScrollIndicator={!isAndroid} // overridable
|
||||
onViewableItemsChanged={onViewableItemsChanged}
|
||||
viewabilityConfig={viewabilityConfig}
|
||||
{...props}
|
||||
automaticallyAdjustsScrollIndicatorInsets={
|
||||
automaticallyAdjustsScrollIndicatorInsets
|
||||
@@ -166,9 +169,6 @@ let List = React.forwardRef<ListMethods, ListProps>(
|
||||
onScroll={scrollHandler}
|
||||
scrollsToTop={!activeLightbox}
|
||||
scrollEventThrottle={1}
|
||||
onViewableItemsChanged={onViewableItemsChanged}
|
||||
viewabilityConfig={viewabilityConfig}
|
||||
showsVerticalScrollIndicator={!isAndroid}
|
||||
style={style}
|
||||
// @ts-expect-error FlatList_INTERNAL ref type is wrong -sfn
|
||||
ref={ref}
|
||||
|
||||
@@ -69,7 +69,7 @@ let PostCtrls = ({
|
||||
style?: StyleProp<ViewStyle>
|
||||
onPressReply: () => void
|
||||
onPostReply?: (postUri: string | undefined) => void
|
||||
logContext: 'FeedItem' | 'PostThreadItem' | 'Post'
|
||||
logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo'
|
||||
threadgateRecord?: AppBskyFeedThreadgate.Record
|
||||
}): React.ReactNode => {
|
||||
const t = useTheme()
|
||||
|
||||
@@ -234,6 +234,7 @@ function HomeScreenReady({
|
||||
feedParams={homeFeedParams}
|
||||
renderEmptyState={renderFollowingEmptyState}
|
||||
renderEndOfFeed={FollowingEndOfFeed}
|
||||
feedInfo={feedInfo}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -247,6 +248,7 @@ function HomeScreenReady({
|
||||
feed={feed}
|
||||
renderEmptyState={renderCustomFeedEmptyState}
|
||||
savedFeedConfig={savedFeedConfig}
|
||||
feedInfo={feedInfo}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -12,7 +12,7 @@ import {useLingui} from '@lingui/react'
|
||||
|
||||
import {cleanError} from '#/lib/strings/errors'
|
||||
import {logger} from '#/logger'
|
||||
import {isWeb} from '#/platform/detection'
|
||||
import {isNative, isWeb} from '#/platform/detection'
|
||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||
import {useGetPopularFeedsQuery} from '#/state/queries/feed'
|
||||
import {usePreferencesQuery} from '#/state/queries/preferences'
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
import {UserAvatar} from '#/view/com/util/UserAvatar'
|
||||
import {ExploreRecommendations} from '#/screens/Search/components/ExploreRecommendations'
|
||||
import {ExploreTrendingTopics} from '#/screens/Search/components/ExploreTrendingTopics'
|
||||
import {ExploreTrendingVideos} from '#/screens/Search/components/ExploreTrendingVideos'
|
||||
import {atoms as a, useTheme, ViewStyleProp} from '#/alf'
|
||||
import {Button} from '#/components/Button'
|
||||
import * as FeedCard from '#/components/FeedCard'
|
||||
@@ -246,6 +247,10 @@ type ExploreScreenItems =
|
||||
type: 'trendingTopics'
|
||||
key: string
|
||||
}
|
||||
| {
|
||||
type: 'trendingVideos'
|
||||
key: string
|
||||
}
|
||||
| {
|
||||
type: 'recommendations'
|
||||
key: string
|
||||
@@ -343,6 +348,13 @@ export function Explore() {
|
||||
key: `trending-topics`,
|
||||
})
|
||||
|
||||
if (isNative) {
|
||||
i.push({
|
||||
type: 'trendingVideos',
|
||||
key: `trending-videos`,
|
||||
})
|
||||
}
|
||||
|
||||
i.push({
|
||||
type: 'recommendations',
|
||||
key: `recommendations`,
|
||||
@@ -514,6 +526,9 @@ export function Explore() {
|
||||
case 'trendingTopics': {
|
||||
return <ExploreTrendingTopics />
|
||||
}
|
||||
case 'trendingVideos': {
|
||||
return <ExploreTrendingVideos />
|
||||
}
|
||||
case 'recommendations': {
|
||||
return <ExploreRecommendations />
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user