From 980a9c7bb9f46e61839062111aaa1ec05f5724a4 Mon Sep 17 00:00:00 2001
From: NGUYEN DINH Quoc-Huy <quochuy@gmail.com>
Date: Wed, 13 Apr 2022 00:34:40 +1000
Subject: [PATCH] - gray out negative rshares comment and don't render the
 markdown - update reason message for hiding or graying a comment - hide
 embeds if negative rshares or blacklisted

---
 src/app/components/cards/Comment.jsx        | 75 ++++++++++++++-------
 src/app/components/cards/MarkdownViewer.jsx | 18 +++--
 src/app/components/cards/PostFull.jsx       |  3 +-
 src/app/locales/en.json                     |  5 +-
 src/app/utils/SanitizeConfig.js             |  6 ++
 5 files changed, 74 insertions(+), 33 deletions(-)

diff --git a/src/app/components/cards/Comment.jsx b/src/app/components/cards/Comment.jsx
index 0de43f9a6..6e827b469 100644
--- a/src/app/components/cards/Comment.jsx
+++ b/src/app/components/cards/Comment.jsx
@@ -79,7 +79,9 @@ class CommentImpl extends PureComponent {
 
     constructor() {
         super();
-        this.state = { collapsed: false, hide_body: false, highlight: false };
+        this.state = {
+            collapsed: false, hide_body: false, highlight: false, low_rating: false,
+        };
         this.revealBody = this.revealBody.bind(this);
         //this.shouldComponentUpdate = shouldComponentUpdate(this, 'Comment');
         this.onShowReply = () => {
@@ -131,8 +133,11 @@ class CommentImpl extends PureComponent {
     _checkHide(props) {
         const { post } = props;
         if (post) {
-            const hide = false && post.getIn(['stats', 'hide']);
+            const notOwn = this.props.username !== post.get('author');
+            const hide = post.getIn(['stats', 'hide']);
             const gray = post.getIn(['stats', 'gray']);
+            const hide_body = notOwn && (hide || gray);
+            const low_rating = post.get('net_rshares') < 0;
 
             if (hide) {
                 // trigger parent component to show 'reveal comments' button
@@ -140,8 +145,7 @@ class CommentImpl extends PureComponent {
                 if (onHide) onHide();
             }
 
-            const notOwn = this.props.username !== post.get('author');
-            this.setState({ hide, hide_body: notOwn && (hide || gray) });
+            this.setState({ hide, hide_body, low_rating });
         }
     }
 
@@ -209,7 +213,8 @@ class CommentImpl extends PureComponent {
         } = this.props;
 
         const {
-            PostReplyEditor, PostEditEditor, showReply, showEdit, hide, hide_body
+            PostReplyEditor, PostEditEditor, showReply, showEdit, hide, hide_body,
+            low_rating,
         } = this.state;
 
         if (!showNegativeComments && (hide || ignored)) return null;
@@ -217,8 +222,10 @@ class CommentImpl extends PureComponent {
         const Editor = showReply ? PostReplyEditor : PostEditEditor;
 
         const author = post.get('author');
+        const isMutedInCommunity = post.get('author_role') === 'muted';
+        const negativeReputation = post.get('author_reputation') < 0;
         const comment = post.toJS();
-        const gray = comment.stats.gray || ImageUserBlockList.includes(author);
+        const gray = comment.stats.gray || ImageUserBlockList.includes(author) || low_rating;
 
         const allowReply = Role.canComment(community, viewer_role);
         const canEdit = username && username === author;
@@ -230,6 +237,7 @@ class CommentImpl extends PureComponent {
         let body = null;
         let controls = null;
         if (!this.state.collapsed && !hide_body) {
+            // If gray don't render Markdown
             body = gray ? (
                 <pre style={{ opacity: 0.5, whiteSpace: 'pre-wrap' }}>{comment.body}</pre>
             ) : (
@@ -327,6 +335,24 @@ class CommentImpl extends PureComponent {
             );
         }
 
+        let reasonForGray;
+        if (!this.state.collapsed && !hide_body && (ignored || gray)) {
+            switch (true) {
+                case isMutedInCommunity:
+                    reasonForGray = tt('g.muted_by_community');
+                    break;
+
+                case negativeReputation:
+                    reasonForGray = tt('g.low_reputation');
+                    break;
+
+                case low_rating:
+                default:
+                    reasonForGray = tt('g.low_rating');
+                    break;
+            }
+        }
+
         return (
             // eslint-disable-next-line jsx-a11y/no-static-element-interactions
             <div
@@ -363,24 +389,25 @@ class CommentImpl extends PureComponent {
                             <Icon name="link" className="chain-rotated" />
                         </Link>
                         {(this.state.collapsed || hide_body) && <Voting post={post} showList={false} />}
-                        {this.state.collapsed
-                            && comment.children > 0 && (
-                                <span>
-                                    {tt('g.reply_count', {
-                                        count: comment.children,
-                                    })}
-                                </span>
-                            )}
-                        {!this.state.collapsed
-                            && hide_body && <a role="link" tabIndex={0} onClick={this.revealBody}>{tt('g.reveal_comment')}</a>}
-                        {!this.state.collapsed
-                            && !hide_body
-                            && (ignored || gray) && (
-                                <span>
-                                    &middot;&nbsp;
-                                    {tt('g.will_be_hidden_due_to_low_rating')}
-                                </span>
-                            )}
+                        {this.state.collapsed && comment.children > 0 && (
+                            <span>
+                                {tt('g.reply_count', {
+                                    count: comment.children,
+                                })}
+                            </span>
+                        )}
+                        {!this.state.collapsed && hide_body && (
+                            <a role="link" tabIndex={0} onClick={this.revealBody}>
+                                {tt('g.reveal_comment')}
+                                ...
+                            </a>
+                        )}
+                        {reasonForGray && (
+                            <span>
+                                &middot;&nbsp;
+                                {reasonForGray}
+                            </span>
+                        )}
                     </div>
                     <div className="Comment__body entry-content">{showEdit ? renderedEditor : body}</div>
                     <div className="Comment__footer">{controls}</div>
diff --git a/src/app/components/cards/MarkdownViewer.jsx b/src/app/components/cards/MarkdownViewer.jsx
index 51e3dbb0a..2a73b0a09 100644
--- a/src/app/components/cards/MarkdownViewer.jsx
+++ b/src/app/components/cards/MarkdownViewer.jsx
@@ -126,13 +126,17 @@ class MarkdownViewer extends Component {
         for (let section of cleanText.split('~~~ embed:')) {
             const embedMd = EmbeddedPlayerGenerateMd(section, idx, large);
             if (embedMd) {
-                const { section: newSection, markdown } = embedMd;
-                section = newSection;
-                sections.push(markdown);
-
-                if (section === '') {
-                    // eslint-disable-next-line no-continue
-                    continue;
+                if (!noLink) {
+                    const { section: newSection, markdown } = embedMd;
+                    section = newSection;
+                    sections.push(markdown);
+
+                    if (section === '') {
+                        // eslint-disable-next-line no-continue
+                        continue;
+                    }
+                } else {
+                    section = `<i>${noLinkText}</i>`;
                 }
             }
 
diff --git a/src/app/components/cards/PostFull.jsx b/src/app/components/cards/PostFull.jsx
index d3afa4643..ef08822d0 100644
--- a/src/app/components/cards/PostFull.jsx
+++ b/src/app/components/cards/PostFull.jsx
@@ -430,6 +430,7 @@ class PostFull extends React.Component {
         const canDelete = username === author && allowDelete(post);
         const isGray = post.getIn(['stats', 'gray']);
         const isMuted = muteList.has(post.get('author')) && !showMutedList;
+        const isLowRating = post.get('net_rshares') < 0;
 
         const isPinned = post.getIn(['stats', 'is_pinned'], false);
 
@@ -488,7 +489,7 @@ class PostFull extends React.Component {
         if (bShowLoading) {
             contentBody = <LoadingIndicator type="circle-strong" />;
         } else {
-            const noLink = isGray || authorIsBlocked;
+            const noLink = isGray || authorIsBlocked || isLowRating;
             const noLinkText = tt('g.no_link_text');
             const noImage = isGray;
             const noImageText = tt('g.no_image_text');
diff --git a/src/app/locales/en.json b/src/app/locales/en.json
index c2f5bbf52..075b06cbe 100644
--- a/src/app/locales/en.json
+++ b/src/app/locales/en.json
@@ -118,9 +118,12 @@
         "reputation": "Reputation",
         "reveal_comment": "Reveal Comment",
         "will_be_hidden_due_to_low_rating": "Will be hidden due to low rating",
+        "muted_by_community": "This author is muted in this community",
+        "low_reputation": "This author has low reputation",
+        "low_rating": "This comment has low rating",
         "images_links_disabled_due_to_low_rating": "Due to low rating, images and links from this post will be disabled.",
         "no_image_text": "(Image not shown due to low ratings)",
-        "no_link_text": "(Link not shown due to low ratings or blacklist)",
+        "no_link_text": "(Link not shown due to low ratings)",
         "request": "request",
         "required": "Required",
         "rewards": "Rewards",
diff --git a/src/app/utils/SanitizeConfig.js b/src/app/utils/SanitizeConfig.js
index 28de6f2b4..676c9296b 100644
--- a/src/app/utils/SanitizeConfig.js
+++ b/src/app/utils/SanitizeConfig.js
@@ -58,6 +58,12 @@ export default (
     allowedSchemes: ['http', 'https', 'steem', 'esteem'],
     transformTags: {
         iframe: (tagName, attribs) => {
+            if (noLink) {
+                return {
+                    tagName: 'i',
+                    text: noLinkText,
+                };
+            }
             const srcAtty = attribs.src;
             const widthAtty = attribs.width;
             const heightAtty = attribs.height;
-- 
GitLab