diff --git a/src/app/components/cards/Comment.jsx b/src/app/components/cards/Comment.jsx index 0de43f9a6b1f762c3a007bab6122fdf07f594255..6e827b46970d2b3253a40f0983107a5605ef56c5 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> - · - {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> + · + {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 51e3dbb0a57728cfe901a4b06b75648d8c86e0b2..2a73b0a09fa00e3bfc187da4de2341c8b5d18708 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 d3afa4643990579307d6f6a1ca57e9a376564c28..ef08822d0b95bf3ac6a8e28ad24957fa39c4319f 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 c2f5bbf521f0503bc128312c3530533b5b2ce3d6..075b06cbebf48fc0becdb0942b6c9680a849efc0 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 28de6f2b41871f08737f0bbe14fad26ac46e46e2..676c9296bb75ff03c6eeeb04d3ad630d794f208d 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;