diff --git a/package.json b/package.json index 28e330809a..1133898ffa 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "icons:optimize": "svgo -f ./assets/icons" }, "dependencies": { - "@atproto/api": "^0.13.21", + "@atproto/api": "^0.13.28", "@braintree/sanitize-url": "^6.0.2", "@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet", "@emoji-mart/react": "^1.1.1", diff --git a/src/state/queries/feed.ts b/src/state/queries/feed.ts index e5ce19a9ad..500cfea548 100644 --- a/src/state/queries/feed.ts +++ b/src/state/queries/feed.ts @@ -48,6 +48,7 @@ export type FeedSourceFeedInfo = { creatorHandle: string likeCount: number | undefined likeUri: string | undefined + contentMode: AppBskyFeedDefs.GeneratorView['contentMode'] } export type FeedSourceListInfo = { @@ -65,6 +66,7 @@ export type FeedSourceListInfo = { description: RichText creatorDid: string creatorHandle: string + contentMode: undefined } export type FeedSourceInfo = FeedSourceFeedInfo | FeedSourceListInfo @@ -111,6 +113,7 @@ export function hydrateFeedGenerator( creatorHandle: view.creator.handle, likeCount: view.likeCount, likeUri: view.viewer?.like, + contentMode: view.contentMode, } } @@ -141,6 +144,7 @@ export function hydrateList(view: AppBskyGraphDefs.ListView): FeedSourceInfo { displayName: view.name ? sanitizeDisplayName(view.name) : `User List by ${sanitizeHandle(view.creator.handle, '@')}`, + contentMode: undefined, } } @@ -399,6 +403,7 @@ const PWI_DISCOVER_FEED_STUB: SavedFeedSourceInfo = { id: 'pwi-discover', ...DISCOVER_SAVED_FEED, }, + contentMode: undefined, } const pinnedFeedInfosQueryKeyRoot = 'pinnedFeedsInfos' @@ -485,6 +490,7 @@ export function usePinnedFeedsInfos() { likeCount: 0, likeUri: '', savedFeed: pinnedItem, + contentMode: undefined, }) } } diff --git a/src/view/com/feeds/FeedPage.tsx b/src/view/com/feeds/FeedPage.tsx index 10ed60212c..7cc1b8ad46 100644 --- a/src/view/com/feeds/FeedPage.tsx +++ b/src/view/com/feeds/FeedPage.tsx @@ -1,20 +1,23 @@ 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_URI} from '#/lib/constants' import {ComposeIcon2} from '#/lib/icons' import {getRootNavigation, getTabState, TabState} from '#/lib/routes/helpers' import {AllNavigatorParams} from '#/lib/routes/types' import {logEvent} from '#/lib/statsig/statsig' +import {useGate} from '#/lib/statsig/statsig' import {s} from '#/lib/styles' 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 +42,7 @@ export function FeedPage({ renderEmptyState, renderEndOfFeed, savedFeedConfig, + feedInfo, }: { testID?: string feed: FeedDescriptor @@ -48,6 +52,7 @@ export function FeedPage({ renderEmptyState: () => JSX.Element renderEndOfFeed?: () => JSX.Element savedFeedConfig?: AppBskyActorDefs.SavedFeed + feedInfo: SavedFeedSourceInfo }) { const {hasSession} = useSession() const {_} = useLingui() @@ -61,6 +66,15 @@ export function FeedPage({ const scrollElRef = React.useRef(null) const [hasNew, setHasNew] = React.useState(false) const setHomeBadge = useSetHomeBadge() + const gate = useGate() + const isVideoFeed = React.useMemo(() => { + const isBskyVideoFeed = [VIDEO_FEED_URI].includes(feedInfo.uri) + const feedIsVideoMode = + feedInfo.contentMode === AppBskyFeedDefs.CONTENTMODEVIDEO + const isFeatureEnabled = gate('yolo') + const _isVideoFeed = isBskyVideoFeed || feedIsVideoMode + return isFeatureEnabled && isNative && _isVideoFeed + }, [gate, feedInfo]) React.useEffect(() => { if (isPageFocused) { @@ -134,6 +148,7 @@ export function FeedPage({ renderEndOfFeed={renderEndOfFeed} headerOffset={headerOffset} savedFeedConfig={savedFeedConfig} + isVideoFeed={isVideoFeed} /> diff --git a/src/view/com/posts/PostFeed.tsx b/src/view/com/posts/PostFeed.tsx index c5b587bf76..341dea3e54 100644 --- a/src/view/com/posts/PostFeed.tsx +++ b/src/view/com/posts/PostFeed.tsx @@ -17,7 +17,6 @@ import {useQueryClient} from '@tanstack/react-query' import { DISCOVER_FEED_URI, KNOWN_SHUTDOWN_FEEDS, - VIDEO_FEED_URI, } from '#/lib/constants' import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender' import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' @@ -169,6 +168,7 @@ let PostFeed = ({ extraData, savedFeedConfig, initialNumToRender: initialNumToRenderOverride, + isVideoFeed = false, }: { feed: FeedDescriptor feedParams?: FeedParams @@ -190,6 +190,7 @@ let PostFeed = ({ extraData?: any savedFeedConfig?: AppBskyActorDefs.SavedFeed initialNumToRender?: number + isVideoFeed?: boolean }): React.ReactNode => { const theme = useTheme() const {_} = useLingui() @@ -206,9 +207,6 @@ let PostFeed = ({ 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( () => ({enabled, ignoreFilterFor}), @@ -349,7 +347,7 @@ let PostFeed = ({ } else if (data) { let sliceIndex = -1 - if (isVideoFeedAndIsEnabled) { + if (isVideoFeed) { const videos: { item: FeedPostSliceItem feedContext: string | undefined @@ -486,7 +484,7 @@ let PostFeed = ({ }) } } else { - if (isVideoFeedAndIsEnabled) { + if (isVideoFeed) { arr.push({ type: 'videoGridRowPlaceholder', key: 'videoGridRowPlaceholder', @@ -515,7 +513,7 @@ let PostFeed = ({ trendingVideoDisabled, gtTablet, gtMobile, - isVideoFeedAndIsEnabled, + isVideoFeed, areVideoFeedsEnabled, ]) diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx index 59b2967308..9043e2fdf6 100644 --- a/src/view/screens/Home.tsx +++ b/src/view/screens/Home.tsx @@ -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} /> ) }) diff --git a/yarn.lock b/yarn.lock index eb77184f91..1dba53850e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -72,15 +72,15 @@ tlds "^1.234.0" zod "^3.23.8" -"@atproto/api@^0.13.21": - version "0.13.21" - resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.21.tgz#8ee27a07e5a024b5bf32408d9bd623dd598ad1cc" - integrity sha512-iOxSj2YS3Fx9IPz1NivKrSsdYPNbBgpnUH7+WhKYAMvDFDUe2PZe7taau8wsUjJAu/H3S0Mk2TDh5e/7tCRwHA== +"@atproto/api@^0.13.28": + version "0.13.28" + resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.28.tgz#b36d4ad9485724ec030e7292599f048ab62a9fcc" + integrity sha512-qBuEI5aNe2/KjmtmtLMilnpZc+FRAsAM3/5nFOQPEudUk388ctNsmKdz2Nti4OvCebn+50EB6V3lju596CTUNA== dependencies: - "@atproto/common-web" "^0.3.1" - "@atproto/lexicon" "^0.4.4" + "@atproto/common-web" "^0.3.2" + "@atproto/lexicon" "^0.4.5" "@atproto/syntax" "^0.3.1" - "@atproto/xrpc" "^0.6.5" + "@atproto/xrpc" "^0.6.6" await-lock "^2.2.2" multiformats "^9.9.0" tlds "^1.234.0" @@ -169,6 +169,16 @@ uint8arrays "3.0.0" zod "^3.23.8" +"@atproto/common-web@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@atproto/common-web/-/common-web-0.3.2.tgz#4cf78ad4d24fed801882f3d35afc39bceccdff51" + integrity sha512-Vx0JtL1/CssJbFAb0UOdvTrkbUautsDfHNOXNTcX2vyPIxH9xOameSqLLunM1hZnOQbJwyjmQCt6TV+bhnanDg== + dependencies: + graphemer "^1.4.0" + multiformats "^9.9.0" + uint8arrays "3.0.0" + zod "^3.23.8" + "@atproto/common@0.1.0": version "0.1.0" resolved "https://registry.yarnpkg.com/@atproto/common/-/common-0.1.0.tgz#4216a8fef5b985ab62ac21252a0f8ca0f4a0f210" @@ -283,6 +293,17 @@ multiformats "^9.9.0" zod "^3.23.8" +"@atproto/lexicon@^0.4.5": + version "0.4.5" + resolved "https://registry.yarnpkg.com/@atproto/lexicon/-/lexicon-0.4.5.tgz#4fcf3731193c674286e9e8d677bbab5dd530b817" + integrity sha512-fljWqMGKn+XWtTprBcS3F1hGBREnQYh6qYHv2sjENucc7REms1gtmZXSerB9N6pVeHVNOnXiILdukeAcic5OEw== + dependencies: + "@atproto/common-web" "^0.3.2" + "@atproto/syntax" "^0.3.1" + iso-datestring-validator "^2.2.2" + multiformats "^9.9.0" + zod "^3.23.8" + "@atproto/oauth-provider@^0.2.10": version "0.2.10" resolved "https://registry.yarnpkg.com/@atproto/oauth-provider/-/oauth-provider-0.2.10.tgz#f9820d7f82c33d3b74e81a75873f50e1e654b901" @@ -452,6 +473,14 @@ "@atproto/lexicon" "^0.4.4" zod "^3.23.8" +"@atproto/xrpc@^0.6.6": + version "0.6.6" + resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.6.6.tgz#28f58270ef4a8056f7f718bd52512e74bcd3702f" + integrity sha512-umXEYVMo9/pyIBoKmIAIi64RXDW9tSXY+wqztlQ6I2GZtjLfNZqmAWU+wADk3SxUe54mvjxxGyA4TtyGtDMfhA== + dependencies: + "@atproto/lexicon" "^0.4.5" + zod "^3.23.8" + "@aws-crypto/crc32@3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@aws-crypto/crc32/-/crc32-3.0.0.tgz#07300eca214409c33e3ff769cd5697b57fdd38fa"