diff --git a/static/app-strings.json b/static/app-strings.json index 095953ba2..2e5e62543 100644 --- a/static/app-strings.json +++ b/static/app-strings.json @@ -1718,6 +1718,10 @@ "Level %current_level%": "Level %current_level%", "Creator tools": "Creator tools", "Prevent this channel from interacting with you.": "Prevent this channel from interacting with you.", + "Choose a permanent or temporary ban.": "Choose a permanent or temporary ban.", + "Personal | Moderator | Admin": "Personal | Moderator | Admin", + "Personal | Moderator": "Personal | Moderator", + "Personal | Admin": "Personal | Admin", "Hide this channel for you only.": "Hide this channel for you only.", "Interacting as %channelName%": "Interacting as %channelName%", "Page Not Found": "Page Not Found", diff --git a/ui/component/commentMenuList/index.js b/ui/component/commentMenuList/index.js index 9d8c4ce48..b03992d37 100644 --- a/ui/component/commentMenuList/index.js +++ b/ui/component/commentMenuList/index.js @@ -7,7 +7,7 @@ import { doOpenModal } from 'redux/actions/app'; import { doSetPlayingUri } from 'redux/actions/content'; import { selectActiveChannelClaim } from 'redux/selectors/app'; import { selectPlayingUri } from 'redux/selectors/content'; - +import { selectModerationDelegatorsById } from 'redux/selectors/comments'; import CommentMenuList from './view'; const select = (state, props) => ({ @@ -16,6 +16,7 @@ const select = (state, props) => ({ contentChannelPermanentUrl: makeSelectChannelPermUrlForClaimUri(props.uri)(state), activeChannelClaim: selectActiveChannelClaim(state), playingUri: selectPlayingUri(state), + moderationDelegatorsById: selectModerationDelegatorsById(state), }); const perform = (dispatch) => ({ diff --git a/ui/component/commentMenuList/view.jsx b/ui/component/commentMenuList/view.jsx index d008c153d..8cc902340 100644 --- a/ui/component/commentMenuList/view.jsx +++ b/ui/component/commentMenuList/view.jsx @@ -6,6 +6,7 @@ import { MenuList, MenuItem } from '@reach/menu-button'; import ChannelThumbnail from 'component/channelThumbnail'; import Icon from 'component/common/icon'; import { parseURI } from 'lbry-redux'; +import { getChannelFromClaim } from 'util/claim'; type Props = { uri: ?string, @@ -24,6 +25,7 @@ type Props = { contentChannelPermanentUrl: any, activeChannelClaim: ?ChannelClaim, playingUri: ?PlayingUri, + moderationDelegatorsById: { [string]: { global: boolean, delegators: { name: string, claimId: string } } }, // --- perform --- openModal: (id: string, {}) => void, clearPlayingUri: () => void, @@ -50,6 +52,7 @@ function CommentMenuList(props: Props) { handleEditComment, commentModAddDelegate, playingUri, + moderationDelegatorsById, disableEdit, disableRemove, openModal, @@ -57,7 +60,15 @@ function CommentMenuList(props: Props) { setQuickReply, } = props; + const contentChannelClaim = getChannelFromClaim(claim); + const activeModeratorInfo = activeChannelClaim && moderationDelegatorsById[activeChannelClaim.claim_id]; const activeChannelIsCreator = activeChannelClaim && activeChannelClaim.permanent_url === contentChannelPermanentUrl; + const activeChannelIsAdmin = activeChannelClaim && activeModeratorInfo && activeModeratorInfo.global; + const activeChannelIsModerator = + activeChannelClaim && + contentChannelClaim && + activeModeratorInfo && + Object.values(activeModeratorInfo.delegators).includes(contentChannelClaim.claim_id); function handlePinComment(commentId, claimId, remove) { pinComment(commentId, claimId, remove); @@ -91,6 +102,59 @@ function CommentMenuList(props: Props) { } } + function getBlockOptionElem() { + const isPersonalBlockTheOnlyOption = !activeChannelIsModerator && !activeChannelIsAdmin; + const isTimeoutBlockAvailable = (claim && claim.is_my_output) || activeChannelIsModerator; + const personalPermanentBlockOnly = isPersonalBlockTheOnlyOption && !isTimeoutBlockAvailable; + + function getSubtitle() { + if (personalPermanentBlockOnly) { + return { + line1: __('Prevent this channel from interacting with you.'), + line2: null, + }; + } else { + if (activeChannelIsModerator && activeChannelIsAdmin) { + return { + line1: __('Personal | Moderator | Admin'), + line2: __('Choose a permanent or temporary ban.'), + }; + } else if (activeChannelIsModerator && !activeChannelIsAdmin) { + return { + line1: __('Personal | Moderator'), + line2: __('Choose a permanent or temporary ban.'), + }; + } else if (!activeChannelIsModerator && activeChannelIsAdmin) { + return { + line1: __('Personal | Admin'), + line2: __('Choose a permanent or temporary ban.'), + }; + } else { + return { + line1: null, + line2: __('Choose a permanent or temporary ban.'), + }; + } + } + } + + const subtitle = getSubtitle(); + return ( + <> +
+ + {__('Block')} +
+ {subtitle.line1 && {subtitle.line1}} + {subtitle.line2 && ( + + {subtitle.line2} {!personalPermanentBlockOnly && } + + )} + + ); + } + return ( {activeChannelIsCreator &&
{__('Creator tools')}
} @@ -142,13 +206,7 @@ function CommentMenuList(props: Props) { {!commentIsMine && ( -
- - {__('Block')} -
- {activeChannelIsCreator && ( - {__('Prevent this channel from interacting with you.')} - )} + {getBlockOptionElem()}
)} diff --git a/ui/modal/modalBlockChannel/view.jsx b/ui/modal/modalBlockChannel/view.jsx index e3d3b58d3..0e8a2434f 100644 --- a/ui/modal/modalBlockChannel/view.jsx +++ b/ui/modal/modalBlockChannel/view.jsx @@ -11,6 +11,7 @@ import Icon from 'component/common/icon'; import * as ICONS from 'constants/icons'; import usePersistedState from 'effects/use-persisted-state'; import { Modal } from 'modal/modal'; +import { getChannelFromClaim } from 'util/claim'; const TAB = { PERSONAL: 'personal', @@ -49,14 +50,7 @@ export default function ModalBlockChannel(props: Props) { commentModBlockAsModerator, } = props; - const contentChannelClaim = !contentClaim - ? null - : contentClaim.value_type === 'channel' - ? contentClaim - : contentClaim.signing_channel && contentClaim.is_channel_signature_valid - ? contentClaim.signing_channel - : null; - + const contentChannelClaim = getChannelFromClaim(contentClaim); const activeModeratorInfo = activeChannelClaim && moderationDelegatorsById[activeChannelClaim.claim_id]; const activeChannelIsAdmin = activeChannelClaim && activeModeratorInfo && activeModeratorInfo.global; const activeChannelIsModerator = diff --git a/ui/scss/component/_comments.scss b/ui/scss/component/_comments.scss index 5126c74c5..d63cbab57 100644 --- a/ui/scss/component/_comments.scss +++ b/ui/scss/component/_comments.scss @@ -353,6 +353,10 @@ $thumbnailWidthSmall: 1rem; padding-left: calc(18px + var(--spacing-s)); max-width: 15rem; white-space: pre-line; + + .icon { + vertical-align: top; + } } .comment__actions { diff --git a/ui/util/claim.js b/ui/util/claim.js index caefb9e21..157a1a52f 100644 --- a/ui/util/claim.js +++ b/ui/util/claim.js @@ -9,3 +9,13 @@ export function getChannelIdFromClaim(claim: ?Claim) { } } } + +export function getChannelFromClaim(claim: ?Claim) { + return !claim + ? null + : claim.value_type === 'channel' + ? claim + : claim.signing_channel && claim.is_channel_signature_valid + ? claim.signing_channel + : null; +}