diff --git a/src/state/queries/notifications/util.ts b/src/state/queries/notifications/util.ts index e4ec246505..97fc57dc18 100644 --- a/src/state/queries/notifications/util.ts +++ b/src/state/queries/notifications/util.ts @@ -87,17 +87,20 @@ export async function fetchPage({ // internal methods // = -function shouldFilterNotif( +export function shouldFilterNotif( notif: AppBskyNotificationListNotifications.Notification, moderationOpts: ModerationOpts | undefined, ): boolean { if (!moderationOpts) { return false } + if (notif.author.viewer?.following) { + return false + } return moderateNotification(notif, moderationOpts).ui('contentList').filter } -function groupNotifications( +export function groupNotifications( notifs: AppBskyNotificationListNotifications.Notification[], ): FeedNotification[] { const groupedNotifs: FeedNotification[] = [] diff --git a/src/view/screens/DebugMod.tsx b/src/view/screens/DebugMod.tsx index 48683cc561..a4d46dbb1f 100644 --- a/src/view/screens/DebugMod.tsx +++ b/src/view/screens/DebugMod.tsx @@ -18,6 +18,11 @@ import { } from '@atproto/api' import {moderationOptsOverrideContext} from '#/state/queries/preferences' import {useSession} from '#/state/session' +import {FeedNotification} from '#/state/queries/notifications/types' +import { + groupNotifications, + shouldFilterNotif, +} from '#/state/queries/notifications/util' import {atoms as a, useTheme} from '#/alf' import {CenteredView, ScrollView} from '#/view/com/util/Views' @@ -35,6 +40,7 @@ import {ScreenHider} from '../com/util/moderation/ScreenHider' import {ProfileHeader} from '../com/profile/ProfileHeader' import {ProfileCard} from '../com/profile/ProfileCard' import {FeedItem} from '../com/posts/FeedItem' +import {FeedItem as NotifFeedItem} from '../com/notifications/FeedItem' import {PostThreadItem} from '../com/post-thread/PostThreadItem' const LABEL_VALUES: (keyof typeof LABELS)[] = Object.keys( @@ -74,6 +80,7 @@ export const DebugModScreen = ({}: NativeStackScreenProps< scenario[0] === 'label' && scenarioSwitches.includes('noAdult') const isLoggedOut = scenario[0] === 'label' && scenarioSwitches.includes('loggedOut') + const isFollowing = scenarioSwitches.includes('following') const did = isTargetMe && currentAccount ? currentAccount.did : 'did:web:bob.test' @@ -102,6 +109,9 @@ export const DebugModScreen = ({}: NativeStackScreenProps< ] : undefined, viewer: mock.actorViewerState({ + following: isFollowing + ? `at://${currentAccount?.did || ''}/app.bsky.graph.follow/1234` + : undefined, muted: scenario[0] === 'mute', mutedByList: undefined, blockedBy: undefined, @@ -117,7 +127,7 @@ export const DebugModScreen = ({}: NativeStackScreenProps< mockedProfile.banner = 'https://bsky.social/about/images/social-card-default-gradient.png' return mockedProfile - }, [scenario, target, label, isSelfLabel, did]) + }, [scenario, target, label, isSelfLabel, did, isFollowing, currentAccount]) const post = React.useMemo(() => { return mock.postView({ @@ -131,7 +141,7 @@ export const DebugModScreen = ({}: NativeStackScreenProps< mock.label({ src: isSelfLabel ? did : undefined, val: label[0], - uri: `at:/${did}/app.bsky.feed.post/fake`, + uri: `at://${did}/app.bsky.feed.post/fake`, }), ] : undefined, @@ -168,6 +178,51 @@ export const DebugModScreen = ({}: NativeStackScreenProps< }) }, [scenario, label, target, profile, isSelfLabel, did]) + const replyNotif = React.useMemo(() => { + const notif = mock.replyNotification({ + record: mock.post({ + text: "This is the body of the post. It's where the text goes. You get the idea.", + reply: { + parent: { + uri: `at://${did}/app.bsky.feed.post/fake-parent`, + cid: 'bafyreiclp443lavogvhj3d2ob2cxbfuscni2k5jk7bebjzg7khl3esabwq', + }, + root: { + uri: `at://${did}/app.bsky.feed.post/fake-parent`, + cid: 'bafyreiclp443lavogvhj3d2ob2cxbfuscni2k5jk7bebjzg7khl3esabwq', + }, + }, + }), + author: profile, + labels: + scenario[0] === 'label' && target[0] === 'post' + ? [ + mock.label({ + src: isSelfLabel ? did : undefined, + val: label[0], + uri: `at://${did}/app.bsky.feed.post/fake`, + }), + ] + : undefined, + }) + const [item] = groupNotifications([notif]) + item.subject = mock.postView({ + record: notif.record as AppBskyFeedPost.Record, + author: profile, + labels: notif.labels, + }) + return item + }, [scenario, label, target, profile, isSelfLabel, did]) + + const followNotif = React.useMemo(() => { + const notif = mock.followNotification({ + author: profile, + subjectDid: currentAccount?.did || '', + }) + const [item] = groupNotifications([notif]) + return item + }, [profile, currentAccount]) + const modOpts = React.useMemo(() => { return { ...MOCK_MOD_OPTS, @@ -218,11 +273,15 @@ export const DebugModScreen = ({}: NativeStackScreenProps< type="checkbox" values={scenarioSwitches} onChange={setScenarioSwitches}> - + Target is me + + + Following target + Self label @@ -318,20 +377,6 @@ export const DebugModScreen = ({}: NativeStackScreenProps< - - - - - - - - @@ -348,14 +393,14 @@ export const DebugModScreen = ({}: NativeStackScreenProps< -

TODO

+ {(target[0] === 'account' || target[0] === 'profile') && ( <> -

TODO

+ @@ -373,9 +418,23 @@ export const DebugModScreen = ({}: NativeStackScreenProps< moderation={profileModeration} moderationOpts={modOpts} /> + + )} + + + + + + @@ -525,6 +584,24 @@ function MockPostThreadItem({ ) } +function MockNotifItem({ + notif, + moderationOpts, +}: { + notif: FeedNotification + moderationOpts: ModerationOpts +}) { + const t = useTheme() + if (shouldFilterNotif(notif.notification, moderationOpts)) { + return ( +

+ Filtered from the feed +

+ ) + } + return +} + function MockAccountCard({ profile, moderation,