about summary refs log tree commit diff
path: root/src/view/com/post-thread/PostThreadItem.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/com/post-thread/PostThreadItem.tsx')
-rw-r--r--src/view/com/post-thread/PostThreadItem.tsx160
1 files changed, 59 insertions, 101 deletions
diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx
index 826d0d161..6555bdf73 100644
--- a/src/view/com/post-thread/PostThreadItem.tsx
+++ b/src/view/com/post-thread/PostThreadItem.tsx
@@ -5,13 +5,13 @@ import {
   AppBskyFeedDefs,
   AppBskyFeedPost,
   RichText as RichTextAPI,
-  PostModeration,
+  ModerationDecision,
 } from '@atproto/api'
 import {moderatePost_wrapped as moderatePost} from '#/lib/moderatePost_wrapped'
 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
 import {PostThreadFollowBtn} from 'view/com/post-thread/PostThreadFollowBtn'
 import {Link, TextLink} from '../util/Link'
-import {RichText} from '../util/text/RichText'
+import {RichText} from '#/components/RichText'
 import {Text} from '../util/text/Text'
 import {PreviewableUserAvatar} from '../util/UserAvatar'
 import {s} from 'lib/styles'
@@ -19,15 +19,14 @@ import {niceDate} from 'lib/strings/time'
 import {sanitizeDisplayName} from 'lib/strings/display-names'
 import {sanitizeHandle} from 'lib/strings/handles'
 import {countLines, pluralize} from 'lib/strings/helpers'
-import {isEmbedByEmbedder} from 'lib/embeds'
 import {getTranslatorLink, isPostInLanguage} from '../../../locale/helpers'
 import {PostMeta} from '../util/PostMeta'
 import {PostEmbeds} from '../util/post-embeds'
 import {PostCtrls} from '../util/post-ctrls/PostCtrls'
-import {PostHider} from '../util/moderation/PostHider'
-import {ContentHider} from '../util/moderation/ContentHider'
-import {PostAlerts} from '../util/moderation/PostAlerts'
-import {PostSandboxWarning} from '../util/PostSandboxWarning'
+import {PostHider} from '../../../components/moderation/PostHider'
+import {ContentHider} from '../../../components/moderation/ContentHider'
+import {PostAlerts} from '../../../components/moderation/PostAlerts'
+import {LabelsOnMyPost} from '../../../components/moderation/LabelsOnMe'
 import {ErrorMessage} from '../util/error/ErrorMessage'
 import {usePalette} from 'lib/hooks/usePalette'
 import {formatCount} from '../util/numeric/format'
@@ -44,6 +43,8 @@ import {Shadow, usePostShadow, POST_TOMBSTONE} from '#/state/cache/post-shadow'
 import {ThreadPost} from '#/state/queries/post-thread'
 import {useSession} from 'state/session'
 import {WhoCanReply} from '../threadgate/WhoCanReply'
+import {LoadingPlaceholder} from '../util/LoadingPlaceholder'
+import {atoms as a} from '#/alf'
 
 export function PostThreadItem({
   post,
@@ -93,6 +94,8 @@ export function PostThreadItem({
   if (richText && moderation) {
     return (
       <PostThreadItemLoaded
+        // Safeguard from clobbering per-post state below:
+        key={postShadowed.uri}
         post={postShadowed}
         prevPost={prevPost}
         nextPost={nextPost}
@@ -144,7 +147,7 @@ let PostThreadItemLoaded = ({
   post: Shadow<AppBskyFeedDefs.PostView>
   record: AppBskyFeedPost.Record
   richText: RichTextAPI
-  moderation: PostModeration
+  moderation: ModerationDecision
   treeView: boolean
   depth: number
   prevPost: ThreadPost | undefined
@@ -164,8 +167,6 @@ let PostThreadItemLoaded = ({
     () => countLines(richText?.text) >= MAX_POST_LINES,
   )
   const {currentAccount} = useSession()
-  const hasEngagement = post.likeCount || post.repostCount
-
   const rootUri = record.reply?.root?.uri || post.uri
   const postHref = React.useMemo(() => {
     const urip = new AtUri(post.uri)
@@ -174,7 +175,6 @@ let PostThreadItemLoaded = ({
   const itemTitle = _(msg`Post by ${post.author.handle}`)
   const authorHref = makeProfileLink(post.author)
   const authorTitle = post.author.handle
-  const isAuthorMuted = post.author.viewer?.muted
   const likesHref = React.useMemo(() => {
     const urip = new AtUri(post.uri)
     return makeProfileLink(post.author, 'post', urip.rkey, 'liked-by')
@@ -205,11 +205,7 @@ let PostThreadItemLoaded = ({
         uri: post.uri,
         cid: post.cid,
         text: record.text,
-        author: {
-          handle: post.author.handle,
-          displayName: post.author.displayName,
-          avatar: post.author.avatar,
-        },
+        author: post.author,
         embed: post.embed,
         moderation,
       },
@@ -248,7 +244,6 @@ let PostThreadItemLoaded = ({
           testID={`postThreadItem-by-${post.author.handle}`}
           style={[styles.outer, styles.outerHighlighted, pal.border, pal.view]}
           accessible={false}>
-          <PostSandboxWarning />
           <View style={[styles.layout]}>
             <View style={[styles.layoutAvi, {paddingBottom: 8}]}>
               <PreviewableUserAvatar
@@ -256,7 +251,8 @@ let PostThreadItemLoaded = ({
                 did={post.author.did}
                 handle={post.author.handle}
                 avatar={post.author.avatar}
-                moderation={moderation.avatar}
+                moderation={moderation.ui('avatar')}
+                type={post.author.associated?.labeler ? 'labeler' : 'user'}
               />
             </View>
             <View style={styles.layoutContent}>
@@ -271,35 +267,12 @@ let PostThreadItemLoaded = ({
                     {sanitizeDisplayName(
                       post.author.displayName ||
                         sanitizeHandle(post.author.handle),
+                      moderation.ui('displayName'),
                     )}
                   </Text>
                 </Link>
               </View>
               <View style={styles.meta}>
-                {isAuthorMuted && (
-                  <View
-                    style={[
-                      pal.viewLight,
-                      {
-                        flexDirection: 'row',
-                        alignItems: 'center',
-                        gap: 4,
-                        borderRadius: 6,
-                        paddingHorizontal: 6,
-                        paddingVertical: 2,
-                        marginRight: 4,
-                      },
-                    ]}>
-                    <FontAwesomeIcon
-                      icon={['far', 'eye-slash']}
-                      size={12}
-                      color={pal.colors.textLight}
-                    />
-                    <Text type="sm-medium" style={pal.textLight}>
-                      Muted
-                    </Text>
-                  </View>
-                )}
                 <Link style={s.flex1} href={authorHref} title={authorTitle}>
                   <Text type="md" style={[pal.textLight]} numberOfLines={1}>
                     {sanitizeHandle(post.author.handle, '@')}
@@ -312,15 +285,16 @@ let PostThreadItemLoaded = ({
             )}
           </View>
           <View style={[s.pl10, s.pr10, s.pb10]}>
+            <LabelsOnMyPost post={post} />
             <ContentHider
-              moderation={moderation.content}
+              modui={moderation.ui('contentView')}
               ignoreMute
               style={styles.contentHider}
               childContainerStyle={styles.contentHiderChild}>
               <PostAlerts
-                moderation={moderation.content}
+                modui={moderation.ui('contentView')}
                 includeMute
-                style={styles.alert}
+                style={[a.pt_2xs, a.pb_sm]}
               />
               {richText?.text ? (
                 <View
@@ -329,27 +303,18 @@ let PostThreadItemLoaded = ({
                     styles.postTextLargeContainer,
                   ]}>
                   <RichText
-                    type="post-text-lg"
-                    richText={richText}
-                    lineHeight={1.3}
-                    style={s.flex1}
+                    enableTags
                     selectable
+                    value={richText}
+                    style={[a.flex_1, a.text_xl]}
+                    authorHandle={post.author.handle}
                   />
                 </View>
               ) : undefined}
               {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>
+                <View style={[a.pb_sm]}>
+                  <PostEmbeds embed={post.embed} moderation={moderation} />
+                </View>
               )}
             </ContentHider>
             <ExpandedPostDetails
@@ -357,9 +322,16 @@ let PostThreadItemLoaded = ({
               translatorUrl={translatorUrl}
               needsTranslation={needsTranslation}
             />
-            {hasEngagement ? (
+            {post.repostCount !== 0 || post.likeCount !== 0 ? (
+              // Show this section unless we're *sure* it has no engagement.
               <View style={[styles.expandedInfo, pal.border]}>
-                {post.repostCount ? (
+                {post.repostCount == null && post.likeCount == null && (
+                  // If we're still loading and not sure, assume this post has engagement.
+                  // This lets us avoid a layout shift for the common case (embedded post with likes/reposts).
+                  // TODO: embeds should include metrics to avoid us having to guess.
+                  <LoadingPlaceholder width={50} height={20} />
+                )}
+                {post.repostCount != null && post.repostCount !== 0 ? (
                   <Link
                     style={styles.expandedInfoItem}
                     href={repostsHref}
@@ -374,10 +346,8 @@ let PostThreadItemLoaded = ({
                       {pluralize(post.repostCount, 'repost')}
                     </Text>
                   </Link>
-                ) : (
-                  <></>
-                )}
-                {post.likeCount ? (
+                ) : null}
+                {post.likeCount != null && post.likeCount !== 0 ? (
                   <Link
                     style={styles.expandedInfoItem}
                     href={likesHref}
@@ -392,13 +362,9 @@ let PostThreadItemLoaded = ({
                       {pluralize(post.likeCount, 'like')}
                     </Text>
                   </Link>
-                ) : (
-                  <></>
-                )}
+                ) : null}
               </View>
-            ) : (
-              <></>
-            )}
+            ) : null}
             <View style={[s.pl10, s.pr10, s.pb5]}>
               <PostCtrls
                 big
@@ -406,6 +372,7 @@ let PostThreadItemLoaded = ({
                 record={record}
                 richText={richText}
                 onPressReply={onPressReply}
+                logContext="PostThreadItem"
               />
             </View>
           </View>
@@ -431,15 +398,13 @@ let PostThreadItemLoaded = ({
             testID={`postThreadItem-by-${post.author.handle}`}
             href={postHref}
             style={[pal.view]}
-            moderation={moderation.content}
+            modui={moderation.ui('contentList')}
             iconSize={isThreadedChild ? 26 : 38}
             iconStyles={
               isThreadedChild
                 ? {marginRight: 4}
                 : {marginLeft: 2, marginRight: 2}
             }>
-            <PostSandboxWarning />
-
             <View
               style={{
                 flexDirection: 'row',
@@ -454,7 +419,7 @@ let PostThreadItemLoaded = ({
                       styles.replyLine,
                       {
                         flexGrow: 1,
-                        backgroundColor: pal.colors.border,
+                        backgroundColor: pal.colors.replyLine,
                         marginBottom: 4,
                       },
                     ]}
@@ -483,7 +448,8 @@ let PostThreadItemLoaded = ({
                     did={post.author.did}
                     handle={post.author.handle}
                     avatar={post.author.avatar}
-                    moderation={moderation.avatar}
+                    moderation={moderation.ui('avatar')}
+                    type={post.author.associated?.labeler ? 'labeler' : 'user'}
                   />
 
                   {showChildReplyLine && (
@@ -492,7 +458,7 @@ let PostThreadItemLoaded = ({
                         styles.replyLine,
                         {
                           flexGrow: 1,
-                          backgroundColor: pal.colors.border,
+                          backgroundColor: pal.colors.replyLine,
                           marginTop: 4,
                         },
                       ]}
@@ -509,28 +475,30 @@ let PostThreadItemLoaded = ({
                 }>
                 <PostMeta
                   author={post.author}
+                  moderation={moderation}
                   authorHasWarning={!!post.author.labels?.length}
                   timestamp={post.indexedAt}
                   postHref={postHref}
                   showAvatar={isThreadedChild}
-                  avatarModeration={moderation.avatar}
+                  avatarModeration={moderation.ui('avatar')}
                   avatarSize={28}
                   displayNameType="md-bold"
                   displayNameStyle={isThreadedChild && s.ml2}
                   style={isThreadedChild && s.mb2}
                 />
+                <LabelsOnMyPost post={post} />
                 <PostAlerts
-                  moderation={moderation.content}
-                  style={styles.alert}
+                  modui={moderation.ui('contentList')}
+                  style={[a.pt_xs, a.pb_sm]}
                 />
                 {richText?.text ? (
                   <View style={styles.postTextContainer}>
                     <RichText
-                      type="post-text"
-                      richText={richText}
-                      style={[pal.text, s.flex1]}
-                      lineHeight={1.3}
+                      enableTags
+                      value={richText}
+                      style={[a.flex_1, a.text_md]}
                       numberOfLines={limitLines ? MAX_POST_LINES : undefined}
+                      authorHandle={post.author.handle}
                     />
                   </View>
                 ) : undefined}
@@ -543,24 +511,16 @@ let PostThreadItemLoaded = ({
                   />
                 ) : undefined}
                 {post.embed && (
-                  <ContentHider
-                    style={styles.contentHider}
-                    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>
+                  <View style={[a.pb_xs]}>
+                    <PostEmbeds embed={post.embed} moderation={moderation} />
+                  </View>
                 )}
                 <PostCtrls
                   post={post}
                   record={record}
                   richText={richText}
                   onPressReply={onPressReply}
+                  logContext="PostThreadItem"
                 />
               </View>
             </View>
@@ -578,7 +538,7 @@ let PostThreadItemLoaded = ({
                 title={itemTitle}
                 noFeedback>
                 <Text type="sm-medium" style={pal.textLight}>
-                  More
+                  <Trans>More</Trans>
                 </Text>
                 <FontAwesomeIcon
                   icon="angle-right"
@@ -621,7 +581,6 @@ function PostOuterWrapper({
     return (
       <View
         style={[
-          pal.view,
           pal.border,
           styles.cursor,
           {
@@ -649,7 +608,6 @@ function PostOuterWrapper({
     <View
       style={[
         styles.outer,
-        pal.view,
         pal.border,
         showParentReplyLine && hasPrecedingItem && styles.noTopBorder,
         styles.cursor,