diff options
Diffstat (limited to 'src/state/queries')
-rw-r--r-- | src/state/queries/feed.ts | 45 | ||||
-rw-r--r-- | src/state/queries/notifications/feed.ts | 29 | ||||
-rw-r--r-- | src/state/queries/post-feed.ts | 35 | ||||
-rw-r--r-- | src/state/queries/profile.ts | 4 |
4 files changed, 38 insertions, 75 deletions
diff --git a/src/state/queries/feed.ts b/src/state/queries/feed.ts index e431643e7..c9d81bc17 100644 --- a/src/state/queries/feed.ts +++ b/src/state/queries/feed.ts @@ -161,51 +161,6 @@ export function useFeedSourceInfoQuery({uri}: {uri: string}) { }) } -export const isFeedPublicQueryKey = ({uri}: {uri: string}) => [ - 'isFeedPublic', - uri, -] - -export function useIsFeedPublicQuery({uri}: {uri: string}) { - return useQuery({ - queryKey: isFeedPublicQueryKey({uri}), - queryFn: async ({queryKey}) => { - const [, uri] = queryKey - try { - const res = await getAgent().app.bsky.feed.getFeed({ - feed: uri, - limit: 1, - }) - return { - isPublic: Boolean(res.data.feed), - error: undefined, - } - } catch (e: any) { - /** - * This should be an `XRPCError`, but I can't safely import from - * `@atproto/xrpc` due to a depdency on node's `crypto` module. - * - * @see https://github.com/bluesky-social/atproto/blob/c17971a2d8e424cc7f10c071d97c07c08aa319cf/packages/xrpc/src/client.ts#L126 - */ - if (e?.status === 401) { - return { - isPublic: false, - error: e, - } - } - - /* - * Non-401 response means something else went wrong on the server - */ - return { - isPublic: true, - error: e, - } - } - }, - }) -} - export const useGetPopularFeedsQueryKey = ['getPopularFeeds'] export function useGetPopularFeedsQuery() { diff --git a/src/state/queries/notifications/feed.ts b/src/state/queries/notifications/feed.ts index dc206df79..d652f493d 100644 --- a/src/state/queries/notifications/feed.ts +++ b/src/state/queries/notifications/feed.ts @@ -16,7 +16,7 @@ * 3. Don't call this query's `refetch()` if you're trying to sync latest; call `checkUnread()` instead. */ -import {useEffect} from 'react' +import {useEffect, useRef} from 'react' import {AppBskyFeedDefs} from '@atproto/api' import { useInfiniteQuery, @@ -49,6 +49,7 @@ export function useNotificationFeedQuery(opts?: {enabled?: boolean}) { const threadMutes = useMutedThreads() const unreads = useUnreadNotificationsApi() const enabled = opts?.enabled !== false + const lastPageCountRef = useRef(0) const query = useInfiniteQuery< FeedPage, @@ -104,24 +105,26 @@ export function useNotificationFeedQuery(opts?: {enabled?: boolean}) { 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 - let numEmpties = 0 for (const page of data?.pages || []) { - if (!page.items.length) { - numEmpties++ - } count += page.items.length } - - if ( - !isFetching && - hasNextPage && - count < PAGE_SIZE && - numEmpties < 3 && - (data?.pages.length || 0) < 6 - ) { + if (count < PAGE_SIZE && (data?.pages.length || 0) < 6) { query.fetchNextPage() + lastPageCountRef.current = data?.pages?.length || 0 } }, [query]) diff --git a/src/state/queries/post-feed.ts b/src/state/queries/post-feed.ts index 423de4ae8..b91af372f 100644 --- a/src/state/queries/post-feed.ts +++ b/src/state/queries/post-feed.ts @@ -1,4 +1,4 @@ -import React, {useCallback, useEffect} from 'react' +import React, {useCallback, useEffect, useRef} from 'react' import { AppBskyFeedDefs, AppBskyFeedPost, @@ -78,6 +78,7 @@ export interface FeedPageUnselected { api: FeedAPI cursor: string | undefined feed: AppBskyFeedDefs.FeedViewPost[] + fetchedAt: number } export interface FeedPage { @@ -85,6 +86,7 @@ export interface FeedPage { tuner: FeedTuner | NoopFeedTuner cursor: string | undefined slices: FeedPostSlice[] + fetchedAt: number } const PAGE_SIZE = 30 @@ -98,11 +100,12 @@ export function usePostFeedQuery( const feedTuners = useFeedTuners(feedDesc) const moderationOpts = useModerationOpts() const enabled = opts?.enabled !== false && Boolean(moderationOpts) - const lastRun = React.useRef<{ + const lastRun = useRef<{ data: InfiniteData<FeedPageUnselected> args: typeof selectArgs result: InfiniteData<FeedPage> } | null>(null) + const lastPageCountRef = useRef(0) // Make sure this doesn't invalidate unless really needed. const selectArgs = React.useMemo( @@ -152,6 +155,7 @@ export function usePostFeedQuery( api, cursor: res.cursor, feed: res.feed, + fetchedAt: Date.now(), } }, initialPageParam: undefined, @@ -214,6 +218,7 @@ export function usePostFeedQuery( api: page.api, tuner, cursor: page.cursor, + fetchedAt: page.fetchedAt, slices: tuner .tune(page.feed) .map(slice => { @@ -279,26 +284,28 @@ export function usePostFeedQuery( 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 - let numEmpties = 0 for (const page of data?.pages || []) { - if (page.slices.length === 0) { - numEmpties++ - } for (const slice of page.slices) { count += slice.items.length } } - - if ( - !isFetching && - hasNextPage && - count < PAGE_SIZE && - numEmpties < 3 && - (data?.pages.length || 0) < 6 - ) { + if (count < PAGE_SIZE && (data?.pages.length || 0) < 6) { query.fetchNextPage() + lastPageCountRef.current = data?.pages?.length || 0 } }, [query]) diff --git a/src/state/queries/profile.ts b/src/state/queries/profile.ts index 5fd0b4e34..40ba0653c 100644 --- a/src/state/queries/profile.ts +++ b/src/state/queries/profile.ts @@ -35,9 +35,7 @@ export function useProfileQuery({did}: {did: string | undefined}) { // if you remove it, the UI infinite-loops // -prf staleTime: isCurrentAccount ? STALE.SECONDS.THIRTY : STALE.MINUTES.FIVE, - refetchInterval: isCurrentAccount - ? STALE.SECONDS.THIRTY - : STALE.MINUTES.FIVE, + refetchInterval: STALE.MINUTES.FIVE, queryKey: RQKEY(did || ''), queryFn: async () => { const res = await getAgent().getProfile({actor: did || ''}) |