about summary refs log tree commit diff
path: root/src/state/queries/notifications/feed.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/state/queries/notifications/feed.ts')
-rw-r--r--src/state/queries/notifications/feed.ts44
1 files changed, 18 insertions, 26 deletions
diff --git a/src/state/queries/notifications/feed.ts b/src/state/queries/notifications/feed.ts
index 1610fc0bf..82eda06ea 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, useRef} from 'react'
+import {useEffect} from 'react'
 import {AppBskyFeedDefs} from '@atproto/api'
 import {
   useInfiniteQuery,
@@ -49,8 +49,6 @@ 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,
@@ -66,8 +64,6 @@ export function useNotificationFeedQuery(opts?: {enabled?: boolean}) {
       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({
@@ -80,27 +76,9 @@ export function useNotificationFeedQuery(opts?: {enabled?: boolean}) {
         })
       }
 
-      // 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,
-        }
+      // if the first page has an unread, mark all read
+      if (!pageParam && page.items[0] && !page.items[0].notification.isRead) {
+        unreads.markAllRead()
       }
 
       return page
@@ -108,6 +86,20 @@ export function useNotificationFeedQuery(opts?: {enabled?: boolean}) {
     initialPageParam: undefined,
     getNextPageParam: lastPage => lastPage.cursor,
     enabled,
+    select(data: InfiniteData<FeedPage>) {
+      // override 'isRead' using the first page's returned seenAt
+      // we do this because the `markAllRead()` call above will
+      // mark subsequent pages as read prematurely
+      const seenAt = data.pages[0]?.seenAt || new Date()
+      for (const page of data.pages) {
+        for (const item of page.items) {
+          item.notification.isRead =
+            seenAt > new Date(item.notification.indexedAt)
+        }
+      }
+
+      return data
+    },
   })
 
   useEffect(() => {