Reuse overfetching for popular feeds, add in existing filtering (#4501)

zio/stable
Eric Bailey 2024-06-14 11:56:29 -05:00 committed by GitHub
parent bdeac28d74
commit 4c0f037880
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 101 additions and 45 deletions

View File

@ -1,3 +1,4 @@
import {useCallback, useEffect, useMemo, useRef} from 'react'
import { import {
AppBskyActorDefs, AppBskyActorDefs,
AppBskyFeedDefs, AppBskyFeedDefs,
@ -171,28 +172,117 @@ export function useFeedSourceInfoQuery({uri}: {uri: string}) {
}) })
} }
export const useGetPopularFeedsQueryKey = ['getPopularFeeds'] // HACK
// the protocol doesn't yet tell us which feeds are personalized
// this list is used to filter out feed recommendations from logged out users
// for the ones we know need it
// -prf
export const KNOWN_AUTHED_ONLY_FEEDS = [
'at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/with-friends', // popular with friends, by bsky.app
'at://did:plc:tenurhgjptubkk5zf5qhi3og/app.bsky.feed.generator/mutuals', // mutuals, by skyfeed
'at://did:plc:tenurhgjptubkk5zf5qhi3og/app.bsky.feed.generator/only-posts', // only posts, by skyfeed
'at://did:plc:wzsilnxf24ehtmmc3gssy5bu/app.bsky.feed.generator/mentions', // mentions, by flicknow
'at://did:plc:q6gjnaw2blty4crticxkmujt/app.bsky.feed.generator/bangers', // my bangers, by jaz
'at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/mutuals', // mutuals, by bluesky
'at://did:plc:q6gjnaw2blty4crticxkmujt/app.bsky.feed.generator/my-followers', // followers, by jaz
'at://did:plc:vpkhqolt662uhesyj6nxm7ys/app.bsky.feed.generator/followpics', // the gram, by why
]
export function useGetPopularFeedsQuery() { type GetPopularFeedsOptions = {limit?: number}
export function createGetPopularFeedsQueryKey(...args: any[]) {
return ['getPopularFeeds', ...args]
}
export function useGetPopularFeedsQuery(options?: GetPopularFeedsOptions) {
const {hasSession} = useSession()
const agent = useAgent() const agent = useAgent()
return useInfiniteQuery< const limit = options?.limit || 10
const {data: preferences} = usePreferencesQuery()
// Make sure this doesn't invalidate unless really needed.
const selectArgs = useMemo(
() => ({
hasSession,
savedFeeds: preferences?.savedFeeds || [],
}),
[hasSession, preferences?.savedFeeds],
)
const lastPageCountRef = useRef(0)
const query = useInfiniteQuery<
AppBskyUnspeccedGetPopularFeedGenerators.OutputSchema, AppBskyUnspeccedGetPopularFeedGenerators.OutputSchema,
Error, Error,
InfiniteData<AppBskyUnspeccedGetPopularFeedGenerators.OutputSchema>, InfiniteData<AppBskyUnspeccedGetPopularFeedGenerators.OutputSchema>,
QueryKey, QueryKey,
string | undefined string | undefined
>({ >({
queryKey: useGetPopularFeedsQueryKey, queryKey: createGetPopularFeedsQueryKey(options),
queryFn: async ({pageParam}) => { queryFn: async ({pageParam}) => {
const res = await agent.app.bsky.unspecced.getPopularFeedGenerators({ const res = await agent.app.bsky.unspecced.getPopularFeedGenerators({
limit: 10, limit,
cursor: pageParam, cursor: pageParam,
}) })
return res.data return res.data
}, },
initialPageParam: undefined, initialPageParam: undefined,
getNextPageParam: lastPage => lastPage.cursor, getNextPageParam: lastPage => lastPage.cursor,
select: useCallback(
(
data: InfiniteData<AppBskyUnspeccedGetPopularFeedGenerators.OutputSchema>,
) => {
const {savedFeeds, hasSession: hasSessionInner} = selectArgs
data?.pages.map(page => {
page.feeds = page.feeds.filter(feed => {
if (
!hasSessionInner &&
KNOWN_AUTHED_ONLY_FEEDS.includes(feed.uri)
) {
return false
}
const alreadySaved = Boolean(
savedFeeds?.find(f => {
return f.value === feed.uri
}),
)
return !alreadySaved
})
return page
})
return data
},
[selectArgs /* Don't change. Everything needs to go into selectArgs. */],
),
}) })
useEffect(() => {
const {isFetching, hasNextPage, data} = query
if (isFetching || !hasNextPage) {
return
}
// avoid double-fires of fetchNextPage()
if (
lastPageCountRef.current !== 0 &&
lastPageCountRef.current === data?.pages?.length
) {
return
}
// fetch next page if we haven't gotten a full page of content
let count = 0
for (const page of data?.pages || []) {
count += page.feeds.length
}
if (count < limit && (data?.pages.length || 0) < 6) {
query.fetchNextPage()
lastPageCountRef.current = data?.pages?.length || 0
}
}, [query, limit])
return query
} }
export function useSearchPopularFeedsMutation() { export function useSearchPopularFeedsMutation() {

View File

@ -104,22 +104,6 @@ type FlatlistSlice =
key: string key: string
} }
// HACK
// the protocol doesn't yet tell us which feeds are personalized
// this list is used to filter out feed recommendations from logged out users
// for the ones we know need it
// -prf
const KNOWN_AUTHED_ONLY_FEEDS = [
'at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/with-friends', // popular with friends, by bsky.app
'at://did:plc:tenurhgjptubkk5zf5qhi3og/app.bsky.feed.generator/mutuals', // mutuals, by skyfeed
'at://did:plc:tenurhgjptubkk5zf5qhi3og/app.bsky.feed.generator/only-posts', // only posts, by skyfeed
'at://did:plc:wzsilnxf24ehtmmc3gssy5bu/app.bsky.feed.generator/mentions', // mentions, by flicknow
'at://did:plc:q6gjnaw2blty4crticxkmujt/app.bsky.feed.generator/bangers', // my bangers, by jaz
'at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/mutuals', // mutuals, by bluesky
'at://did:plc:q6gjnaw2blty4crticxkmujt/app.bsky.feed.generator/my-followers', // followers, by jaz
'at://did:plc:vpkhqolt662uhesyj6nxm7ys/app.bsky.feed.generator/followpics', // the gram, by why
]
export function FeedsScreen(_props: Props) { export function FeedsScreen(_props: Props) {
const pal = usePalette('default') const pal = usePalette('default')
const {openComposer} = useComposerControls() const {openComposer} = useComposerControls()
@ -327,10 +311,7 @@ export function FeedsScreen(_props: Props) {
type: 'popularFeedsLoading', type: 'popularFeedsLoading',
}) })
} else { } else {
if ( if (!popularFeeds?.pages) {
!popularFeeds?.pages ||
popularFeeds?.pages[0]?.feeds?.length === 0
) {
slices.push({ slices.push({
key: 'popularFeedsNoResults', key: 'popularFeedsNoResults',
type: 'popularFeedsNoResults', type: 'popularFeedsNoResults',
@ -338,26 +319,11 @@ export function FeedsScreen(_props: Props) {
} else { } else {
for (const page of popularFeeds.pages || []) { for (const page of popularFeeds.pages || []) {
slices = slices.concat( slices = slices.concat(
page.feeds page.feeds.map(feed => ({
.filter(feed => { key: `popularFeed:${feed.uri}`,
if ( type: 'popularFeed',
!hasSession && feedUri: feed.uri,
KNOWN_AUTHED_ONLY_FEEDS.includes(feed.uri) })),
) {
return false
}
const alreadySaved = Boolean(
preferences?.savedFeeds?.find(f => {
return f.value === feed.uri
}),
)
return !alreadySaved
})
.map(feed => ({
key: `popularFeed:${feed.uri}`,
type: 'popularFeed',
feedUri: feed.uri,
})),
) )
} }