Separate caches

This commit is contained in:
Dan Abramov
2025-01-19 20:10:28 +00:00
parent 47f9ae1b3f
commit 0bd92c1bd0
9 changed files with 103 additions and 14 deletions
@@ -1,14 +1,16 @@
import React from 'react'
import React, {useEffect} from 'react'
import {ScrollView, View} from 'react-native'
import {AppBskyEmbedVideo, AtUri} from '@atproto/api'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useQueryClient} from '@tanstack/react-query'
import {VIDEO_FEED_URI} from '#/lib/constants'
import {makeCustomFeedLink} from '#/lib/routes/links'
import {logEvent} from '#/lib/statsig/statsig'
import {useTrendingSettingsApi} from '#/state/preferences/trending'
import {usePostFeedQuery} from '#/state/queries/post-feed'
import {RQKEY} from '#/state/queries/post-feed'
import {BlockDrawerGesture} from '#/view/shell/BlockDrawerGesture'
import {atoms as a, useGutters, useTheme} from '#/alf'
import {Button, ButtonIcon} from '#/components/Button'
@@ -25,11 +27,32 @@ import {
const CARD_WIDTH = 100
const FEED_DESC = `feedgen|${VIDEO_FEED_URI}`
const FEED_PARAMS: {
feedCacheKey: 'discover'
} = {
feedCacheKey: 'discover',
}
export function TrendingVideos() {
const t = useTheme()
const {_} = useLingui()
const gutters = useGutters([0, 'base'])
const {data, isLoading, error} = usePostFeedQuery(`feedgen|${VIDEO_FEED_URI}`)
const {data, isLoading, error} = usePostFeedQuery(FEED_DESC, FEED_PARAMS)
// Refetch on unmount if nothing else is using this query.
const queryClient = useQueryClient()
useEffect(() => {
return () => {
const query = queryClient
.getQueryCache()
.find({queryKey: RQKEY(FEED_DESC, FEED_PARAMS)})
if (query && query.getObserversCount() <= 1) {
query.fetch()
}
}
}, [queryClient])
const {setTrendingVideoDisabled} = useTrendingSettingsApi()
const trendingPrompt = Prompt.usePromptControl()
@@ -138,7 +161,7 @@ function VideoCards({
}, [data])
const href = React.useMemo(() => {
const urip = new AtUri(VIDEO_FEED_URI)
return makeCustomFeedLink(urip.host, urip.rkey)
return makeCustomFeedLink(urip.host, urip.rkey, undefined, 'discover')
}, [])
return (
@@ -151,6 +174,7 @@ function VideoCards({
sourceContext={{
type: 'feedgen',
uri: VIDEO_FEED_URI,
feedCacheKey: 'discover',
}}
onInteract={() => {
logEvent('videoCard:click', {
+6 -2
View File
@@ -19,9 +19,13 @@ export function makeProfileLink(
export function makeCustomFeedLink(
did: string,
rkey: string,
...segments: string[]
segment?: string | undefined,
feedCacheKey?: 'discover' | 'explore' | undefined,
) {
return [`/profile`, did, 'feed', rkey, ...segments].join('/')
return (
[`/profile`, did, 'feed', rkey, ...(segment ? [segment] : [])].join('/') +
(feedCacheKey ? `?feedCacheKey=${encodeURIComponent(feedCacheKey)}` : '')
)
}
export function makeListLink(did: string, rkey: string, ...segments: string[]) {
+5 -1
View File
@@ -22,7 +22,11 @@ export type CommonNavigatorParams = {
PostLikedBy: {name: string; rkey: string}
PostRepostedBy: {name: string; rkey: string}
PostQuotes: {name: string; rkey: string}
ProfileFeed: {name: string; rkey: string}
ProfileFeed: {
name: string
rkey: string
feedCacheKey?: 'discover' | 'explore' | undefined
}
ProfileFeedLikedBy: {name: string; rkey: string}
ProfileLabelerLikedBy: {name: string}
Debug: undefined
+21 -3
View File
@@ -21,7 +21,7 @@ import {isNative} from '#/platform/detection'
import {listenSoftReset} from '#/state/events'
import {FeedFeedbackProvider, useFeedFeedback} from '#/state/feed-feedback'
import {FeedSourceFeedInfo, useFeedSourceInfoQuery} from '#/state/queries/feed'
import {FeedDescriptor} from '#/state/queries/post-feed'
import {FeedDescriptor, FeedParams} from '#/state/queries/post-feed'
import {RQKEY as FEED_RQKEY} from '#/state/queries/post-feed'
import {
usePreferencesQuery,
@@ -49,6 +49,11 @@ type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFeed'>
export function ProfileFeedScreen(props: Props) {
const {rkey, name: handleOrDid} = props.route.params
const feedParams: FeedParams | undefined = props.route.params.feedCacheKey
? {
feedCacheKey: props.route.params.feedCacheKey,
}
: undefined
const pal = usePalette('default')
const {_} = useLingui()
const navigation = useNavigation<NavigationProp>()
@@ -99,7 +104,10 @@ export function ProfileFeedScreen(props: Props) {
return resolvedUri ? (
<Layout.Screen>
<ProfileFeedScreenIntermediate feedUri={resolvedUri.uri} />
<ProfileFeedScreenIntermediate
feedUri={resolvedUri.uri}
feedParams={feedParams}
/>
</Layout.Screen>
) : (
<Layout.Screen>
@@ -111,7 +119,13 @@ export function ProfileFeedScreen(props: Props) {
)
}
function ProfileFeedScreenIntermediate({feedUri}: {feedUri: string}) {
function ProfileFeedScreenIntermediate({
feedUri,
feedParams,
}: {
feedUri: string
feedParams: FeedParams | undefined
}) {
const {data: preferences} = usePreferencesQuery()
const {data: info} = useFeedSourceInfoQuery({uri: feedUri})
@@ -128,15 +142,18 @@ function ProfileFeedScreenIntermediate({feedUri}: {feedUri: string}) {
<ProfileFeedScreenInner
preferences={preferences}
feedInfo={info as FeedSourceFeedInfo}
feedParams={feedParams}
/>
)
}
export function ProfileFeedScreenInner({
feedInfo,
feedParams,
}: {
preferences: UsePreferencesQueryResponse
feedInfo: FeedSourceFeedInfo
feedParams: FeedParams | undefined
}) {
const {_} = useLingui()
const {hasSession} = useSession()
@@ -190,6 +207,7 @@ export function ProfileFeedScreenInner({
<FeedFeedbackProvider value={feedFeedback}>
<PostFeed
feed={feed}
feedParams={feedParams}
pollInterval={60e3}
disablePoll={hasNew}
onHasNew={setHasNew}
@@ -3,13 +3,15 @@ import {ScrollView, View} from 'react-native'
import {AppBskyEmbedVideo, AtUri} from '@atproto/api'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useFocusEffect} from '@react-navigation/native'
import {useQueryClient} from '@tanstack/react-query'
import {VIDEO_FEED_URI} from '#/lib/constants'
import {makeCustomFeedLink} from '#/lib/routes/links'
import {logEvent} from '#/lib/statsig/statsig'
import {isWeb} from '#/platform/detection'
import {useSavedFeeds} from '#/state/queries/feed'
import {usePostFeedQuery} from '#/state/queries/post-feed'
import {RQKEY, usePostFeedQuery} from '#/state/queries/post-feed'
import {useAddSavedFeedsMutation} from '#/state/queries/preferences'
import {BlockDrawerGesture} from '#/view/shell/BlockDrawerGesture'
import {atoms as a, tokens, useGutters, useTheme} from '#/alf'
@@ -27,11 +29,31 @@ import {
const CARD_WIDTH = 100
const FEED_DESC = `feedgen|${VIDEO_FEED_URI}`
const FEED_PARAMS: {
feedCacheKey: 'explore'
} = {
feedCacheKey: 'explore',
}
export function ExploreTrendingVideos() {
const t = useTheme()
const {_} = useLingui()
const gutters = useGutters([0, 'base'])
const {data, isLoading, error} = usePostFeedQuery(`feedgen|${VIDEO_FEED_URI}`)
const {data, isLoading, error} = usePostFeedQuery(FEED_DESC, FEED_PARAMS)
// Refetch on tab change if nothing else is using this query.
const queryClient = useQueryClient()
useFocusEffect(() => {
return () => {
const query = queryClient
.getQueryCache()
.find({queryKey: RQKEY(FEED_DESC, FEED_PARAMS)})
if (query && query.getObserversCount() <= 1) {
query.fetch()
}
}
})
const {data: saved} = useSavedFeeds()
const isSavedAlready = React.useMemo(() => {
@@ -179,7 +201,7 @@ function VideoCards({
}, [data])
const href = React.useMemo(() => {
const urip = new AtUri(VIDEO_FEED_URI)
return makeCustomFeedLink(urip.host, urip.rkey)
return makeCustomFeedLink(urip.host, urip.rkey, undefined, 'explore')
}, [])
return (
@@ -192,6 +214,7 @@ function VideoCards({
sourceContext={{
type: 'feedgen',
uri: VIDEO_FEED_URI,
feedCacheKey: 'explore',
}}
onInteract={() => {
logEvent('videoCard:click', {
+8 -1
View File
@@ -190,7 +190,14 @@ function Feed() {
}, [params])
const feedFeedback = useFeedFeedback(feedDesc, hasSession)
const {data, error, hasNextPage, isFetchingNextPage, fetchNextPage} =
usePostFeedQuery(feedDesc)
usePostFeedQuery(
feedDesc,
params.type === 'feedgen' && params.feedCacheKey !== undefined
? {
feedCacheKey: params.feedCacheKey,
}
: undefined,
)
const videos = useMemo(() => {
let vids =
+6 -1
View File
@@ -4,7 +4,12 @@ import {AuthorFilter} from '#/state/queries/post-feed'
* Kind of like `FeedDescriptor` but not
*/
export type VideoFeedSourceContext =
| {type: 'feedgen'; uri: string; initialPostUri?: string}
| {
type: 'feedgen'
uri: string
initialPostUri?: string
feedCacheKey?: 'discover' | 'explore' | undefined
}
| {
type: 'author'
did: string
+1
View File
@@ -61,6 +61,7 @@ export type FeedDescriptor =
export interface FeedParams {
mergeFeedEnabled?: boolean
mergeFeedSources?: string[]
feedCacheKey?: 'discover' | 'explore' | undefined
}
type RQPageParam = {cursor: string | undefined; api: FeedAPI} | undefined
+3
View File
@@ -208,6 +208,7 @@ let PostFeed = ({
return isNative && gate('yolo')
}, [gate])
const feedCacheKey = feedParams?.feedCacheKey
const opts = React.useMemo(
() => ({enabled, ignoreFilterFor}),
[enabled, ignoreFilterFor],
@@ -654,6 +655,7 @@ let PostFeed = ({
sourceContext={{
type: 'feedgen',
uri: row.sourceFeedUri,
feedCacheKey: feedCacheKey,
}}
/>
)
@@ -670,6 +672,7 @@ let PostFeed = ({
_,
onPressRetryLoadMore,
feedUri,
feedCacheKey,
],
)