about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/moderation.ts21
-rw-r--r--src/view/com/post-thread/PostThreadItem.tsx9
-rw-r--r--src/view/com/post/Post.tsx8
-rw-r--r--src/view/com/posts/FeedItem.tsx8
-rw-r--r--src/view/com/util/moderation/ContentHider.tsx23
-rw-r--r--src/view/com/util/post-embeds/index.tsx15
6 files changed, 74 insertions, 10 deletions
diff --git a/src/lib/moderation.ts b/src/lib/moderation.ts
index 6c08606ee..8ba99128b 100644
--- a/src/lib/moderation.ts
+++ b/src/lib/moderation.ts
@@ -1,4 +1,4 @@
-import {ModerationCause, ProfileModeration} from '@atproto/api'
+import {ModerationCause, ProfileModeration, PostModeration} from '@atproto/api'
 
 export interface ModerationCauseDescription {
   name: string
@@ -92,6 +92,25 @@ export function getProfileModerationCauses(
   }) as ModerationCause[]
 }
 
+export function isPostMediaBlurred(
+  decisions: PostModeration['decisions'],
+): boolean {
+  return decisions.post.blurMedia
+}
+
+export function isQuoteBlurred(
+  decisions: PostModeration['decisions'],
+): boolean {
+  return (
+    decisions.quote?.blur ||
+    decisions.quote?.blurMedia ||
+    decisions.quote?.filter ||
+    decisions.quotedAccount?.blur ||
+    decisions.quotedAccount?.filter ||
+    false
+  )
+}
+
 export function isCauseALabelOnUri(
   cause: ModerationCause | undefined,
   uri: string,
diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx
index 900adfa81..63119eedf 100644
--- a/src/view/com/post-thread/PostThreadItem.tsx
+++ b/src/view/com/post-thread/PostThreadItem.tsx
@@ -351,11 +351,14 @@ let PostThreadItemLoaded = ({
               {post.embed && (
                 <ContentHider
                   moderation={moderation.embed}
+                  moderationDecisions={moderation.decisions}
                   ignoreMute={isEmbedByEmbedder(post.embed, post.author.did)}
+                  ignoreQuoteDecisions
                   style={s.mb10}>
                   <PostEmbeds
                     embed={post.embed}
                     moderation={moderation.embed}
+                    moderationDecisions={moderation.decisions}
                   />
                 </ContentHider>
               )}
@@ -526,10 +529,14 @@ let PostThreadItemLoaded = ({
               {post.embed && (
                 <ContentHider
                   style={styles.contentHider}
-                  moderation={moderation.embed}>
+                  moderation={moderation.embed}
+                  moderationDecisions={moderation.decisions}
+                  ignoreMute={isEmbedByEmbedder(post.embed, post.author.did)}
+                  ignoreQuoteDecisions>
                   <PostEmbeds
                     embed={post.embed}
                     moderation={moderation.embed}
+                    moderationDecisions={moderation.decisions}
                   />
                 </ContentHider>
               )}
diff --git a/src/view/com/post/Post.tsx b/src/view/com/post/Post.tsx
index 2e8019e71..9b1bf7a49 100644
--- a/src/view/com/post/Post.tsx
+++ b/src/view/com/post/Post.tsx
@@ -196,8 +196,14 @@ function PostInner({
             {post.embed ? (
               <ContentHider
                 moderation={moderation.embed}
+                moderationDecisions={moderation.decisions}
+                ignoreQuoteDecisions
                 style={styles.contentHider}>
-                <PostEmbeds embed={post.embed} moderation={moderation.embed} />
+                <PostEmbeds
+                  embed={post.embed}
+                  moderation={moderation.embed}
+                  moderationDecisions={moderation.decisions}
+                />
               </ContentHider>
             ) : null}
           </ContentHider>
diff --git a/src/view/com/posts/FeedItem.tsx b/src/view/com/posts/FeedItem.tsx
index dfb0cfcf6..b6c509e92 100644
--- a/src/view/com/posts/FeedItem.tsx
+++ b/src/view/com/posts/FeedItem.tsx
@@ -320,9 +320,15 @@ let FeedItemInner = ({
               <ContentHider
                 testID="contentHider-embed"
                 moderation={moderation.embed}
+                moderationDecisions={moderation.decisions}
                 ignoreMute={isEmbedByEmbedder(post.embed, post.author.did)}
+                ignoreQuoteDecisions
                 style={styles.embed}>
-                <PostEmbeds embed={post.embed} moderation={moderation.embed} />
+                <PostEmbeds
+                  embed={post.embed}
+                  moderation={moderation.embed}
+                  moderationDecisions={moderation.decisions}
+                />
               </ContentHider>
             ) : null}
           </ContentHider>
diff --git a/src/view/com/util/moderation/ContentHider.tsx b/src/view/com/util/moderation/ContentHider.tsx
index c5c887685..20749e33c 100644
--- a/src/view/com/util/moderation/ContentHider.tsx
+++ b/src/view/com/util/moderation/ContentHider.tsx
@@ -2,25 +2,30 @@ import React from 'react'
 import {Pressable, StyleProp, StyleSheet, View, ViewStyle} from 'react-native'
 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
 import {usePalette} from 'lib/hooks/usePalette'
-import {ModerationUI} from '@atproto/api'
+import {ModerationUI, PostModeration} from '@atproto/api'
 import {Text} from '../text/Text'
 import {ShieldExclamation} from 'lib/icons'
 import {describeModerationCause} from 'lib/moderation'
 import {useLingui} from '@lingui/react'
 import {msg} from '@lingui/macro'
 import {useModalControls} from '#/state/modals'
+import {isPostMediaBlurred} from 'lib/moderation'
 
 export function ContentHider({
   testID,
   moderation,
+  moderationDecisions,
   ignoreMute,
+  ignoreQuoteDecisions,
   style,
   childContainerStyle,
   children,
 }: React.PropsWithChildren<{
   testID?: string
   moderation: ModerationUI
+  moderationDecisions?: PostModeration['decisions']
   ignoreMute?: boolean
+  ignoreQuoteDecisions?: boolean
   style?: StyleProp<ViewStyle>
   childContainerStyle?: StyleProp<ViewStyle>
 }>) {
@@ -29,7 +34,11 @@ export function ContentHider({
   const [override, setOverride] = React.useState(false)
   const {openModal} = useModalControls()
 
-  if (!moderation.blur || (ignoreMute && moderation.cause?.type === 'muted')) {
+  if (
+    !moderation.blur ||
+    (ignoreMute && moderation.cause?.type === 'muted') ||
+    shouldIgnoreQuote(moderationDecisions, ignoreQuoteDecisions)
+  ) {
     return (
       <View testID={testID} style={[styles.outer, style]}>
         {children}
@@ -99,6 +108,16 @@ export function ContentHider({
   )
 }
 
+function shouldIgnoreQuote(
+  decisions: PostModeration['decisions'] | undefined,
+  ignore: boolean | undefined,
+): boolean {
+  if (!decisions || !ignore) {
+    return false
+  }
+  return !isPostMediaBlurred(decisions)
+}
+
 const styles = StyleSheet.create({
   outer: {
     overflow: 'hidden',
diff --git a/src/view/com/util/post-embeds/index.tsx b/src/view/com/util/post-embeds/index.tsx
index ca3bf1104..5c16a3b3e 100644
--- a/src/view/com/util/post-embeds/index.tsx
+++ b/src/view/com/util/post-embeds/index.tsx
@@ -16,6 +16,7 @@ import {
   AppBskyFeedDefs,
   AppBskyGraphDefs,
   ModerationUI,
+  PostModeration,
 } from '@atproto/api'
 import {Link} from '../Link'
 import {ImageLayoutGrid} from '../images/ImageLayoutGrid'
@@ -28,8 +29,9 @@ import {getYoutubeVideoId} from 'lib/strings/url-helpers'
 import {MaybeQuoteEmbed} from './QuoteEmbed'
 import {AutoSizedImage} from '../images/AutoSizedImage'
 import {ListEmbed} from './ListEmbed'
-import {isCauseALabelOnUri} from 'lib/moderation'
+import {isCauseALabelOnUri, isQuoteBlurred} from 'lib/moderation'
 import {FeedSourceCard} from 'view/com/feeds/FeedSourceCard'
+import {ContentHider} from '../moderation/ContentHider'
 
 type Embed =
   | AppBskyEmbedRecord.View
@@ -41,10 +43,12 @@ type Embed =
 export function PostEmbeds({
   embed,
   moderation,
+  moderationDecisions,
   style,
 }: {
   embed?: Embed
   moderation: ModerationUI
+  moderationDecisions?: PostModeration['decisions']
   style?: StyleProp<ViewStyle>
 }) {
   const pal = usePalette('default')
@@ -55,14 +59,17 @@ export function PostEmbeds({
   // =
   if (AppBskyEmbedRecordWithMedia.isView(embed)) {
     const isModOnQuote =
-      AppBskyEmbedRecord.isViewRecord(embed.record.record) &&
-      isCauseALabelOnUri(moderation.cause, embed.record.record.uri)
+      (AppBskyEmbedRecord.isViewRecord(embed.record.record) &&
+        isCauseALabelOnUri(moderation.cause, embed.record.record.uri)) ||
+      (moderationDecisions && isQuoteBlurred(moderationDecisions))
     const mediaModeration = isModOnQuote ? {} : moderation
     const quoteModeration = isModOnQuote ? moderation : {}
     return (
       <View style={[styles.stackContainer, style]}>
         <PostEmbeds embed={embed.media} moderation={mediaModeration} />
-        <MaybeQuoteEmbed embed={embed.record} moderation={quoteModeration} />
+        <ContentHider moderation={quoteModeration}>
+          <MaybeQuoteEmbed embed={embed.record} moderation={quoteModeration} />
+        </ContentHider>
       </View>
     )
   }