Skip to content

Commit

Permalink
Filter mute words from notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
estrattonbailey committed Oct 3, 2024
1 parent 939b071 commit 37e5154
Showing 1 changed file with 86 additions and 17 deletions.
103 changes: 86 additions & 17 deletions src/state/queries/notifications/feed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@
*/

import {useCallback, useEffect, useMemo, useRef} from 'react'
import {AppBskyActorDefs, AppBskyFeedDefs, AtUri} from '@atproto/api'
import {
AppBskyActorDefs,
AppBskyFeedDefs,
AppBskyFeedPost,
AtUri,
} from '@atproto/api'
import {
InfiniteData,
QueryClient,
Expand All @@ -26,6 +31,7 @@ import {
useQueryClient,
} from '@tanstack/react-query'

import {moderatePost_wrapped as moderatePost} from '#/lib/moderatePost_wrapped'
import {useAgent} from '#/state/session'
import {useThreadgateHiddenReplyUris} from '#/state/threadgate-hidden-replies'
import {useModerationOpts} from '../../preferences/moderation-opts'
Expand Down Expand Up @@ -67,9 +73,15 @@ export function useNotificationFeedQuery(opts?: {

const selectArgs = useMemo(() => {
return {
moderationOpts,
hiddenReplyUris,
}
}, [hiddenReplyUris])
}, [moderationOpts, hiddenReplyUris])
const lastRun = useRef<{
data: InfiniteData<FeedPage>
args: typeof selectArgs
result: InfiniteData<FeedPage>
} | null>(null)

const query = useInfiniteQuery<
FeedPage,
Expand Down Expand Up @@ -111,7 +123,38 @@ export function useNotificationFeedQuery(opts?: {
enabled,
select: useCallback(
(data: InfiniteData<FeedPage>) => {
const {hiddenReplyUris} = selectArgs
const {moderationOpts, hiddenReplyUris} = selectArgs

// Keep track of the last run and whether we can reuse
// some already selected pages from there.
let reusedPages = []
if (lastRun.current) {
const {
data: lastData,
args: lastArgs,
result: lastResult,
} = lastRun.current
let canReuse = true
for (let key in selectArgs) {
if (selectArgs.hasOwnProperty(key)) {
if ((selectArgs as any)[key] !== (lastArgs as any)[key]) {
// Can't do reuse anything if any input has changed.
canReuse = false
break
}
}
}
if (canReuse) {
for (let i = 0; i < data.pages.length; i++) {
if (data.pages[i] && lastData.pages[i] === data.pages[i]) {
reusedPages.push(lastResult.pages[i])
continue
}
// Stop as soon as pages stop matching up.
break
}
}
}

// override 'isRead' using the first page's returned seenAt
// we do this because the `markAllRead()` call above will
Expand All @@ -124,23 +167,49 @@ export function useNotificationFeedQuery(opts?: {
}
}

data = {
const result = {
...data,
pages: data.pages.map(page => {
return {
...page,
items: page.items.filter(item => {
const isHiddenReply =
item.type === 'reply' &&
item.subjectUri &&
hiddenReplyUris.has(item.subjectUri)
return !isHiddenReply
}),
}
}),
pages: [
...reusedPages,
...data.pages.slice(reusedPages.length).map(page => {
return {
...page,
items: page.items
.filter(item => {
const isHiddenReply =
item.type === 'reply' &&
item.subjectUri &&
hiddenReplyUris.has(item.subjectUri)
return !isHiddenReply
})
.filter(item => {
if (
item.type === 'reply' ||
item.type === 'mention' ||
item.type === 'quote'
) {
/*
* The `isPostView` check will fail here bc we don't have
* a `$type` field on the `subject`. But if the nested
* `record` is a post, we know it's a post view.
*/
if (AppBskyFeedPost.isRecord(item.subject?.record)) {
const mod = moderatePost(item.subject, moderationOpts!)
if (mod.ui('contentList').filter) {
return false
}
}
}
return true
}),
}
}),
],
}

return data
lastRun.current = {data, result, args: selectArgs}

return result
},
[selectArgs],
),
Expand Down

0 comments on commit 37e5154

Please sign in to comment.