diff options
Diffstat (limited to 'src/state/queries/notifications/feed.ts')
-rw-r--r-- | src/state/queries/notifications/feed.ts | 51 |
1 files changed, 40 insertions, 11 deletions
diff --git a/src/state/queries/notifications/feed.ts b/src/state/queries/notifications/feed.ts index a74670b5b..b6aa3d753 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,8 @@ export function useNotificationFeedQuery(opts?: {enabled?: boolean}) { const threadMutes = useMutedThreads() const unreads = useUnreadNotificationsApi() const enabled = opts?.enabled !== false + // state tracked across page fetches + const pageState = useRef({pageNum: 0, hasMarkedRead: false}) const query = useInfiniteQuery< FeedPage, @@ -60,17 +62,44 @@ export function useNotificationFeedQuery(opts?: {enabled?: boolean}) { staleTime: STALE.INFINITY, queryKey: RQKEY(), async queryFn({pageParam}: {pageParam: RQPageParam}) { - let page = await fetchPage({ - limit: PAGE_SIZE, - cursor: pageParam, - queryClient, - moderationOpts, - threadMutes, - }) + let page + if (!pageParam) { + // for the first page, we check the cached page held by the unread-checker first + page = unreads.getCachedUnreadPage() + // reset the page state + pageState.current = {pageNum: 0, hasMarkedRead: false} + } + if (!page) { + page = await fetchPage({ + limit: PAGE_SIZE, + cursor: pageParam, + queryClient, + moderationOpts, + threadMutes, + }) + } - // if the first page has an unread, mark all read - if (!pageParam && page.items[0] && !page.items[0].notification.isRead) { - unreads.markAllRead() + // NOTE + // this section checks to see if we need to mark notifs read + // we want to wait until we've seen a read notification because + // of a timing challenge; marking read on the first page would + // cause subsequent pages of unread notifs to incorrectly come + // back as "read". we use page 6 as an abort condition, which means + // after ~180 notifs we give up on tracking unread state correctly + // -prf + if (!pageState.current.hasMarkedRead) { + let hasMarkedRead = false + if ( + pageState.current.pageNum > 5 || + page.items.some(item => item.notification.isRead) + ) { + unreads.markAllRead() + hasMarkedRead = true + } + pageState.current = { + pageNum: pageState.current.pageNum + 1, + hasMarkedRead, + } } return page |