about summary refs log tree commit diff
path: root/src/state/queries/notifications
diff options
context:
space:
mode:
Diffstat (limited to 'src/state/queries/notifications')
-rw-r--r--src/state/queries/notifications/feed.ts20
-rw-r--r--src/state/queries/notifications/unread.tsx10
-rw-r--r--src/state/queries/notifications/util.ts59
3 files changed, 65 insertions, 24 deletions
diff --git a/src/state/queries/notifications/feed.ts b/src/state/queries/notifications/feed.ts
index d652f493d..b91db9237 100644
--- a/src/state/queries/notifications/feed.ts
+++ b/src/state/queries/notifications/feed.ts
@@ -67,18 +67,20 @@ export function useNotificationFeedQuery(opts?: {enabled?: boolean}) {
         page = unreads.getCachedUnreadPage()
       }
       if (!page) {
-        page = await fetchPage({
-          limit: PAGE_SIZE,
-          cursor: pageParam,
-          queryClient,
-          moderationOpts,
-          threadMutes,
-          fetchAdditionalData: true,
-        })
+        page = (
+          await fetchPage({
+            limit: PAGE_SIZE,
+            cursor: pageParam,
+            queryClient,
+            moderationOpts,
+            threadMutes,
+            fetchAdditionalData: true,
+          })
+        ).page
       }
 
       // if the first page has an unread, mark all read
-      if (!pageParam && page.items[0] && !page.items[0].notification.isRead) {
+      if (!pageParam) {
         unreads.markAllRead()
       }
 
diff --git a/src/state/queries/notifications/unread.tsx b/src/state/queries/notifications/unread.tsx
index a96b56225..e7a0631ec 100644
--- a/src/state/queries/notifications/unread.tsx
+++ b/src/state/queries/notifications/unread.tsx
@@ -127,7 +127,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
           }
 
           // count
-          const page = await fetchPage({
+          const {page, indexedAt: lastIndexed} = await fetchPage({
             cursor: undefined,
             limit: 40,
             queryClient,
@@ -151,12 +151,14 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
 
           // track last sync
           const now = new Date()
-          const lastIndexed =
-            page.items[0] && new Date(page.items[0].notification.indexedAt)
+          const lastIndexedDate = lastIndexed
+            ? new Date(lastIndexed)
+            : undefined
           cacheRef.current = {
             usableInFeed: !!invalidate, // will be used immediately
             data: page,
-            syncedAt: !lastIndexed || now > lastIndexed ? now : lastIndexed,
+            syncedAt:
+              !lastIndexedDate || now > lastIndexedDate ? now : lastIndexedDate,
             unreadCount,
           }
 
diff --git a/src/state/queries/notifications/util.ts b/src/state/queries/notifications/util.ts
index 411a0f791..1c85d2b6d 100644
--- a/src/state/queries/notifications/util.ts
+++ b/src/state/queries/notifications/util.ts
@@ -6,6 +6,7 @@ import {
   AppBskyFeedPost,
   AppBskyFeedRepost,
   AppBskyFeedLike,
+  AppBskyEmbedRecord,
 } from '@atproto/api'
 import {moderatePost_wrapped as moderatePost} from '#/lib/moderatePost_wrapped'
 import chunk from 'lodash.chunk'
@@ -35,11 +36,12 @@ export async function fetchPage({
   moderationOpts: ModerationOpts | undefined
   threadMutes: string[]
   fetchAdditionalData: boolean
-}): Promise<FeedPage> {
+}): Promise<{page: FeedPage; indexedAt: string | undefined}> {
   const res = await getAgent().listNotifications({
     limit,
     cursor,
   })
+  const indexedAt = res.data.notifications[0]?.indexedAt
 
   // filter out notifs by mod rules
   const notifs = res.data.notifications.filter(
@@ -74,9 +76,12 @@ export async function fetchPage({
   }
 
   return {
-    cursor: res.data.cursor,
-    seenAt,
-    items: notifsGrouped,
+    page: {
+      cursor: res.data.cursor,
+      seenAt,
+      items: notifsGrouped,
+    },
+    indexedAt,
   }
 }
 
@@ -110,8 +115,6 @@ function shouldFilterNotif(
       return true
     }
   }
-  // TODO: thread muting is not being applied
-  // (this requires fetching the post)
   return false
 }
 
@@ -221,10 +224,44 @@ function getSubjectUri(
   }
 }
 
-function isThreadMuted(notif: FeedNotification, mutes: string[]): boolean {
-  if (!notif.subject) {
-    return false
+export function isThreadMuted(notif: FeedNotification, threadMutes: string[]) {
+  // If there's a subject we want to use that. This will always work on the notifications tab
+  if (notif.subject) {
+    const record = notif.subject.record as AppBskyFeedPost.Record
+    // Check for a quote record
+    if (
+      (record.reply && threadMutes.includes(record.reply.root.uri)) ||
+      (notif.subject.uri && threadMutes.includes(notif.subject.uri))
+    ) {
+      return true
+    } else if (
+      AppBskyEmbedRecord.isMain(record.embed) &&
+      threadMutes.includes(record.embed.record.uri)
+    ) {
+      return true
+    }
+  } else {
+    // Otherwise we just do the best that we can
+    const record = notif.notification.record
+    if (AppBskyFeedPost.isRecord(record)) {
+      if (record.reply && threadMutes.includes(record.reply.root.uri)) {
+        // We can always filter replies
+        return true
+      } else if (
+        AppBskyEmbedRecord.isMain(record.embed) &&
+        threadMutes.includes(record.embed.record.uri)
+      ) {
+        // We can also filter quotes if the quoted post is the root
+        return true
+      }
+    } else if (
+      AppBskyFeedRepost.isRecord(record) &&
+      threadMutes.includes(record.subject.uri)
+    ) {
+      // Finally we can filter reposts, again if the post is the root
+      return true
+    }
   }
-  const record = notif.subject.record as AppBskyFeedPost.Record // assured in fetchSubjects()
-  return mutes.includes(record.reply?.root.uri || notif.subject.uri)
+
+  return false
 }