diff --git a/flow-typed/Comment.js b/flow-typed/Comment.js index f62993f9e..ffda63876 100644 --- a/flow-typed/Comment.js +++ b/flow-typed/Comment.js @@ -60,9 +60,6 @@ declare type CommentsState = { fetchingModerationDelegators: boolean, blockingByUri: {}, unBlockingByUri: {}, - personalTimeoutMap: { [uri: string]: { blockedAt: string, bannedFor: number, banRemaining: number } }, - adminTimeoutMap: { [uri: string]: { blockedAt: string, bannedFor: number, banRemaining: number } }, - moderatorTimeoutMap: { [uri: string]: { blockedAt: string, bannedFor: number, banRemaining: number } }, togglingForDelegatorMap: {[string]: Array}, // {"blockedUri": ["delegatorUri1", ""delegatorUri2", ...]} settingsByChannelId: { [string]: PerChannelSettings }, // ChannelID -> settings fetchingSettings: boolean, @@ -192,43 +189,7 @@ declare type SuperListResponse = { has_hidden_comments: boolean, }; -declare type ModerationBlockParams = { - // Publisher, Moderator, or Commentron Admin - mod_channel_id: string, - mod_channel_name: string, - // Offender being blocked - blocked_channel_id: string, - blocked_channel_name: string, - // Creator that Moderator is delegated from. Used for delegated moderation - creator_channel_id?: string, - creator_channel_name?: string, - // Blocks identity from comment universally, requires Admin rights on commentron instance - block_all?: boolean, - time_out?: number, - // If true will delete all comments of the offender, requires Admin rights on commentron for universal delete - delete_all?: boolean, - // The usual signature stuff - signature: string, - signing_ts: string, -}; - -declare type ModerationBlockResponse = { - deleted_comment_ids: Array, - banned_channel_id: string, - all_blocked: boolean, - banned_from: string, -}; - -declare type BlockedListArgs = { - // Publisher, Moderator or Commentron Admin - mod_channel_id: string, - mod_channel_name: string, - // Creator that Moderator is delegated from. Used for delegated moderation - creator_channel_id?: string, - creator_channel_name?: string, - signature: string, - signing_ts: string, -}; +declare type ModerationBlockParams = {}; declare type ModerationAddDelegateParams = { mod_channel_id: string, diff --git a/package.json b/package.json index f9caeed7a..e7303aa87 100644 --- a/package.json +++ b/package.json @@ -54,9 +54,7 @@ "electron-notarize": "^1.0.0", "electron-updater": "^4.2.4", "express": "^4.17.1", - "humanize-duration": "^3.27.0", "if-env": "^1.0.4", - "parse-duration": "^1.0.0", "react-datetime-picker": "^3.2.1", "react-plastic": "^1.1.1", "react-top-loading-bar": "^2.0.1", diff --git a/static/app-strings.json b/static/app-strings.json index 381022242..9ce061707 100644 --- a/static/app-strings.json +++ b/static/app-strings.json @@ -1744,12 +1744,6 @@ "Moderator Block": "Moderator Block", "Block this channel on behalf of %creator%": "Block this channel on behalf of %creator%", "creator": "creator", - "Enter the timeout duration. Examples: %examples%": "Enter the timeout duration. Examples: %examples%", - "Wow, banned for more than 100 years?": "Wow, banned for more than 100 years?", - "Invalid duration.": "Invalid duration.", - "Permanent": "Permanent", - "Timeout --[time-based ban instead of permanent]--": "Timeout", - "(Remaining: %duration%) --[timeout ban duration]--": "(Remaining: %duration%)", "Create a channel to change this setting.": "Create a channel to change this setting.", "Invalid channel URL \"%url%\"": "Invalid channel URL \"%url%\"", "Delegation": "Delegation", diff --git a/ui/analytics.js b/ui/analytics.js index b36902941..495535dcc 100644 --- a/ui/analytics.js +++ b/ui/analytics.js @@ -120,6 +120,10 @@ async function sendAndResetWatchmanData() { return 'Can only be used with a user id'; } + if (!videoPlayer) { + return 'Video player not initialized'; + } + let timeSinceLastIntervalSend = new Date() - lastSentTime; lastSentTime = new Date(); diff --git a/ui/comments.js b/ui/comments.js index 315756401..58593895f 100644 --- a/ui/comments.js +++ b/ui/comments.js @@ -14,7 +14,7 @@ const Comments = { moderation_block: (params: ModerationBlockParams) => fetchCommentsApi('moderation.Block', params), moderation_unblock: (params: ModerationBlockParams) => fetchCommentsApi('moderation.UnBlock', params), - moderation_block_list: (params: BlockedListArgs) => fetchCommentsApi('moderation.BlockedList', params), + moderation_block_list: (params: ModerationBlockParams) => fetchCommentsApi('moderation.BlockedList', params), moderation_add_delegate: (params: ModerationAddDelegateParams) => fetchCommentsApi('moderation.AddDelegate', params), moderation_remove_delegate: (params: ModerationRemoveDelegateParams) => fetchCommentsApi('moderation.RemoveDelegate', params), diff --git a/ui/component/channelBlockButton/view.jsx b/ui/component/channelBlockButton/view.jsx index 7f10eeb35..dce36b899 100644 --- a/ui/component/channelBlockButton/view.jsx +++ b/ui/component/channelBlockButton/view.jsx @@ -12,7 +12,7 @@ type Props = { isBlockingOrUnBlocking: boolean, isToggling: boolean, doCommentModUnBlock: (string, boolean) => void, - doCommentModBlock: (string, ?Number, boolean) => void, + doCommentModBlock: (string, boolean) => void, doCommentModUnBlockAsAdmin: (string, string) => void, doCommentModBlockAsAdmin: (string, string) => void, doCommentModUnBlockAsModerator: (string, string, string) => void, @@ -42,7 +42,7 @@ function ChannelBlockButton(props: Props) { if (isBlocked) { doCommentModUnBlock(uri, false); } else { - doCommentModBlock(uri, undefined, false); + doCommentModBlock(uri, false); } break; diff --git a/ui/component/commentMenuList/index.js b/ui/component/commentMenuList/index.js index 9d8c4ce48..5ebdf41b5 100644 --- a/ui/component/commentMenuList/index.js +++ b/ui/component/commentMenuList/index.js @@ -1,13 +1,19 @@ import { connect } from 'react-redux'; import { makeSelectChannelPermUrlForClaimUri, makeSelectClaimIsMine, makeSelectClaimForUri } from 'lbry-redux'; -import { doCommentPin, doCommentModAddDelegate } from 'redux/actions/comments'; +import { + doCommentPin, + doCommentModBlock, + doCommentModBlockAsAdmin, + doCommentModBlockAsModerator, + doCommentModAddDelegate, +} from 'redux/actions/comments'; import { doChannelMute } from 'redux/actions/blocked'; // import { doSetActiveChannel } from 'redux/actions/app'; 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 +22,7 @@ const select = (state, props) => ({ contentChannelPermanentUrl: makeSelectChannelPermUrlForClaimUri(props.uri)(state), activeChannelClaim: selectActiveChannelClaim(state), playingUri: selectPlayingUri(state), + moderationDelegatorsById: selectModerationDelegatorsById(state), }); const perform = (dispatch) => ({ @@ -24,6 +31,10 @@ const perform = (dispatch) => ({ muteChannel: (channelUri) => dispatch(doChannelMute(channelUri)), pinComment: (commentId, claimId, remove) => dispatch(doCommentPin(commentId, claimId, remove)), // setActiveChannel: channelId => dispatch(doSetActiveChannel(channelId)), + commentModBlock: (commenterUri) => dispatch(doCommentModBlock(commenterUri)), + commentModBlockAsAdmin: (commenterUri, blockerId) => dispatch(doCommentModBlockAsAdmin(commenterUri, blockerId)), + commentModBlockAsModerator: (commenterUri, creatorId, blockerId) => + dispatch(doCommentModBlockAsModerator(commenterUri, creatorId, blockerId)), commentModAddDelegate: (modChanId, modChanName, creatorChannelClaim) => dispatch(doCommentModAddDelegate(modChanId, modChanName, creatorChannelClaim, true)), }); diff --git a/ui/component/commentMenuList/view.jsx b/ui/component/commentMenuList/view.jsx index d008c153d..0698652dd 100644 --- a/ui/component/commentMenuList/view.jsx +++ b/ui/component/commentMenuList/view.jsx @@ -8,7 +8,6 @@ import Icon from 'component/common/icon'; import { parseURI } from 'lbry-redux'; type Props = { - uri: ?string, authorUri: string, // full LBRY Channel URI: lbry://@channel#123... commentId: string, // sha256 digest identifying the comment isTopLevel: boolean, @@ -24,18 +23,21 @@ type Props = { contentChannelPermanentUrl: any, activeChannelClaim: ?ChannelClaim, playingUri: ?PlayingUri, + moderationDelegatorsById: { [string]: { global: boolean, delegators: { name: string, claimId: string } } }, // --- perform --- openModal: (id: string, {}) => void, clearPlayingUri: () => void, muteChannel: (string) => void, pinComment: (string, string, boolean) => Promise, + commentModBlock: (string) => void, + commentModBlockAsAdmin: (string, string) => void, + commentModBlockAsModerator: (string, string, string) => void, commentModAddDelegate: (string, string, ChannelClaim) => void, setQuickReply: (any) => void, }; function CommentMenuList(props: Props) { const { - uri, claim, authorUri, commentIsMine, @@ -48,16 +50,35 @@ function CommentMenuList(props: Props) { isTopLevel, isPinned, handleEditComment, + commentModBlock, + commentModBlockAsAdmin, + commentModBlockAsModerator, commentModAddDelegate, playingUri, disableEdit, disableRemove, + moderationDelegatorsById, openModal, supportAmount, setQuickReply, } = props; + const contentChannelClaim = !claim + ? null + : claim.value_type === 'channel' + ? claim + : claim.signing_channel && claim.is_channel_signature_valid + ? claim.signing_channel + : null; + + 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); @@ -77,7 +98,7 @@ function CommentMenuList(props: Props) { } function handleCommentBlock() { - openModal(MODALS.BLOCK_CHANNEL, { contentUri: uri, commenterUri: authorUri }); + commentModBlock(authorUri); } function handleCommentMute() { @@ -91,6 +112,18 @@ function CommentMenuList(props: Props) { } } + function blockCommentAsModerator() { + if (activeChannelClaim && contentChannelClaim) { + commentModBlockAsModerator(authorUri, contentChannelClaim.claim_id, activeChannelClaim.claim_id); + } + } + + function blockCommentAsAdmin() { + if (activeChannelClaim) { + commentModBlockAsAdmin(authorUri, activeChannelClaim.claim_id); + } + } + return ( {activeChannelIsCreator &&
{__('Creator tools')}
} @@ -164,6 +197,34 @@ function CommentMenuList(props: Props) { )} + {!commentIsMine && (activeChannelIsAdmin || activeChannelIsModerator) && ( +
{__('Moderator tools')}
+ )} + + {!commentIsMine && activeChannelIsAdmin && ( + +
+ + {__('Global Block')} +
+ {__('Block this channel as global admin')} +
+ )} + + {!commentIsMine && activeChannelIsModerator && ( + +
+ + {__('Moderator Block')} +
+ + {__('Block this channel on behalf of %creator%', { + creator: contentChannelClaim ? contentChannelClaim.name : __('creator'), + })} + +
+ )} + {activeChannelClaim && (
diff --git a/ui/constants/modal_types.js b/ui/constants/modal_types.js index 2355f3087..c43f04399 100644 --- a/ui/constants/modal_types.js +++ b/ui/constants/modal_types.js @@ -43,7 +43,6 @@ export const IMAGE_UPLOAD = 'image_upload'; export const MOBILE_SEARCH = 'mobile_search'; export const VIEW_IMAGE = 'view_image'; export const CONFIRM_REMOVE_BTC_SWAP_ADDRESS = 'confirm_remove_btc_swap_address'; -export const BLOCK_CHANNEL = 'block_channel'; export const COLLECTION_ADD = 'collection_add'; export const COLLECTION_DELETE = 'collection_delete'; export const CONFIRM_REMOVE_CARD = 'CONFIRM_REMOVE_CARD'; diff --git a/ui/modal/modalBlockChannel/index.js b/ui/modal/modalBlockChannel/index.js deleted file mode 100644 index cf2fbc6df..000000000 --- a/ui/modal/modalBlockChannel/index.js +++ /dev/null @@ -1,25 +0,0 @@ -import { connect } from 'react-redux'; -import { makeSelectClaimForUri } from 'lbry-redux'; -import { doHideModal } from 'redux/actions/app'; -import { doCommentModBlock, doCommentModBlockAsAdmin, doCommentModBlockAsModerator } from 'redux/actions/comments'; -import { selectActiveChannelClaim } from 'redux/selectors/app'; -import { selectModerationDelegatorsById } from 'redux/selectors/comments'; - -import ModalBlockChannel from './view'; - -const select = (state, props) => ({ - activeChannelClaim: selectActiveChannelClaim(state), - contentClaim: makeSelectClaimForUri(props.contentUri)(state), - moderationDelegatorsById: selectModerationDelegatorsById(state), -}); - -const perform = (dispatch) => ({ - closeModal: () => dispatch(doHideModal()), - commentModBlock: (commenterUri, timeoutHours) => dispatch(doCommentModBlock(commenterUri, timeoutHours)), - commentModBlockAsAdmin: (commenterUri, blockerId, timeoutHours) => - dispatch(doCommentModBlockAsAdmin(commenterUri, blockerId, timeoutHours)), - commentModBlockAsModerator: (commenterUri, creatorId, blockerId, timeoutHours) => - dispatch(doCommentModBlockAsModerator(commenterUri, creatorId, blockerId, timeoutHours)), -}); - -export default connect(select, perform)(ModalBlockChannel); diff --git a/ui/modal/modalBlockChannel/view.jsx b/ui/modal/modalBlockChannel/view.jsx deleted file mode 100644 index 454f1a370..000000000 --- a/ui/modal/modalBlockChannel/view.jsx +++ /dev/null @@ -1,304 +0,0 @@ -// @flow -import React from 'react'; -import classnames from 'classnames'; -import parseDuration from 'parse-duration'; -import Button from 'component/button'; -import ChannelThumbnail from 'component/channelThumbnail'; -import ClaimPreview from 'component/claimPreview'; -import Card from 'component/common/card'; -import { FormField } from 'component/common/form'; -import Icon from 'component/common/icon'; -import * as ICONS from 'constants/icons'; -import usePersistedState from 'effects/use-persisted-state'; -import { Modal } from 'modal/modal'; - -const TAB = { - PERSONAL: 'personal', - MODERATOR: 'moderator', - ADMIN: 'admin', -}; - -const BLOCK = { - PERMANENT: 'permanent', - TIMEOUT: 'timeout', -}; - -type Props = { - contentUri: string, - commenterUri: string, - // --- select --- - activeChannelClaim: ?ChannelClaim, - contentClaim: ?Claim, - moderationDelegatorsById: { [string]: { global: boolean, delegators: { name: string, claimId: string } } }, - // --- perform --- - closeModal: () => void, - commentModBlock: (string, ?number) => void, - commentModBlockAsAdmin: (string, string, ?number) => void, - commentModBlockAsModerator: (string, string, string, ?number) => void, -}; - -export default function ModalBlockChannel(props: Props) { - const { - commenterUri, - activeChannelClaim, - contentClaim, - moderationDelegatorsById, - closeModal, - commentModBlock, - commentModBlockAsAdmin, - commentModBlockAsModerator, - } = props; - - const contentChannelClaim = !contentClaim - ? null - : contentClaim.value_type === 'channel' - ? contentClaim - : contentClaim.signing_channel && contentClaim.is_channel_signature_valid - ? contentClaim.signing_channel - : null; - - const activeModeratorInfo = activeChannelClaim && moderationDelegatorsById[activeChannelClaim.claim_id]; - const activeChannelIsAdmin = activeChannelClaim && activeModeratorInfo && activeModeratorInfo.global; - const activeChannelIsModerator = - activeChannelClaim && - contentChannelClaim && - activeModeratorInfo && - Object.values(activeModeratorInfo.delegators).includes(contentChannelClaim.claim_id); - - const [tab, setTab] = usePersistedState('ModalBlockChannel:tab', TAB.PERSONAL); - const [blockType, setBlockType] = usePersistedState('ModalBlockChannel:blockType', BLOCK.PERMANENT); - const [timeoutInput, setTimeoutInput] = usePersistedState('ModalBlockChannel:timeoutInput', '10m'); - const [timeoutInputErr, setTimeoutInputErr] = React.useState(''); - const [timeoutSec, setTimeoutSec] = React.useState(-1); - - const isPersonalTheOnlyTab = !activeChannelIsModerator && !activeChannelIsAdmin; - const isTimeoutAvail = contentClaim && contentClaim.is_my_output; - const blockButtonDisabled = blockType === BLOCK.TIMEOUT && timeoutSec < 1; - - // ************************************************************************** - // ************************************************************************** - - // Check settings validity on mount. - React.useEffect(() => { - if ( - isPersonalTheOnlyTab || - (tab === TAB.MODERATOR && !activeChannelIsModerator) || - (tab === TAB.ADMIN && !activeChannelIsAdmin) - ) { - setTab(TAB.PERSONAL); - } - - if (!isTimeoutAvail && blockType === BLOCK.TIMEOUT) { - setBlockType(BLOCK.PERMANENT); - } - }, []); // eslint-disable-line react-hooks/exhaustive-deps - - // 'timeoutInput' to 'timeoutSec' conversion. - React.useEffect(() => { - const setInvalid = (errMsg: string) => { - if (timeoutSec !== -1) { - setTimeoutSec(-1); - } - if (!timeoutInputErr) { - setTimeoutInputErr(errMsg); - } - }; - - const setValid = (seconds) => { - if (seconds !== timeoutSec) { - setTimeoutSec(seconds); - } - if (timeoutInputErr) { - setTimeoutInputErr(''); - } - }; - - const ONE_HUNDRED_YEARS_IN_SECONDS = 3154000000; - const seconds = parseDuration(timeoutInput, 's'); - - if (Number.isInteger(seconds) && seconds > 0) { - if (seconds > ONE_HUNDRED_YEARS_IN_SECONDS) { - setInvalid('Wow, banned for more than 100 years?'); - } else { - setValid(seconds); - } - } else { - setInvalid('Invalid duration.'); - } - }, [timeoutInput, timeoutInputErr, timeoutSec]); - - // ************************************************************************** - // ************************************************************************** - - function getTabElem(value, label) { - return ( -
- - - } - /> - - ); -} diff --git a/ui/modal/modalRouter/view.jsx b/ui/modal/modalRouter/view.jsx index 856824f28..3f8e729f2 100644 --- a/ui/modal/modalRouter/view.jsx +++ b/ui/modal/modalRouter/view.jsx @@ -5,71 +5,32 @@ import { lazyImport } from 'util/lazyImport'; import * as MODALS from 'constants/modal_types'; import LoadingBarOneOff from 'component/loadingBarOneOff'; -const ModalAffirmPurchase = lazyImport(() => - import('modal/modalAffirmPurchase' /* webpackChunkName: "modalAffirmPurchase" */) -); -const ModalAutoGenerateThumbnail = lazyImport(() => - import('modal/modalAutoGenerateThumbnail' /* webpackChunkName: "modalAutoGenerateThumbnail" */) -); -const ModalAutoUpdateDownloaded = lazyImport(() => - import('modal/modalAutoUpdateDownloaded' /* webpackChunkName: "modalAutoUpdateDownloaded" */) -); -const ModalBlockChannel = lazyImport(() => - import('modal/modalBlockChannel' /* webpackChunkName: "modalBlockChannel" */) -); -const ModalClaimCollectionAdd = lazyImport(() => - import('modal/modalClaimCollectionAdd' /* webpackChunkName: "modalClaimCollectionAdd" */) -); -const ModalCommentAcknowledgement = lazyImport(() => - import('modal/modalCommentAcknowledgement' /* webpackChunkName: "modalCommentAcknowledgement" */) -); +const ModalAffirmPurchase = lazyImport(() => import('modal/modalAffirmPurchase' /* webpackChunkName: "modalAffirmPurchase" */)); +const ModalAutoGenerateThumbnail = lazyImport(() => import('modal/modalAutoGenerateThumbnail' /* webpackChunkName: "modalAutoGenerateThumbnail" */)); +const ModalAutoUpdateDownloaded = lazyImport(() => import('modal/modalAutoUpdateDownloaded' /* webpackChunkName: "modalAutoUpdateDownloaded" */)); +const ModalClaimCollectionAdd = lazyImport(() => import('modal/modalClaimCollectionAdd' /* webpackChunkName: "modalClaimCollectionAdd" */)); +const ModalCommentAcknowledgement = lazyImport(() => import('modal/modalCommentAcknowledgement' /* webpackChunkName: "modalCommentAcknowledgement" */)); const ModalConfirmAge = lazyImport(() => import('modal/modalConfirmAge' /* webpackChunkName: "modalConfirmAge" */)); -const ModalConfirmThumbnailUpload = lazyImport(() => - import('modal/modalConfirmThumbnailUpload' /* webpackChunkName: "modalConfirmThumbnailUpload" */) -); -const ModalConfirmTransaction = lazyImport(() => - import('modal/modalConfirmTransaction' /* webpackChunkName: "modalConfirmTransaction" */) -); -const ModalDeleteCollection = lazyImport(() => - import('modal/modalRemoveCollection' /* webpackChunkName: "modalRemoveCollection" */) -); +const ModalConfirmThumbnailUpload = lazyImport(() => import('modal/modalConfirmThumbnailUpload' /* webpackChunkName: "modalConfirmThumbnailUpload" */)); +const ModalConfirmTransaction = lazyImport(() => import('modal/modalConfirmTransaction' /* webpackChunkName: "modalConfirmTransaction" */)); +const ModalDeleteCollection = lazyImport(() => import('modal/modalRemoveCollection' /* webpackChunkName: "modalRemoveCollection" */)); const ModalDownloading = lazyImport(() => import('modal/modalDownloading' /* webpackChunkName: "modalDownloading" */)); const ModalError = lazyImport(() => import('modal/modalError' /* webpackChunkName: "modalError" */)); -const ModalFileSelection = lazyImport(() => - import('modal/modalFileSelection' /* webpackChunkName: "modalFileSelection" */) -); +const ModalFileSelection = lazyImport(() => import('modal/modalFileSelection' /* webpackChunkName: "modalFileSelection" */)); const ModalFileTimeout = lazyImport(() => import('modal/modalFileTimeout' /* webpackChunkName: "modalFileTimeout" */)); const ModalFirstReward = lazyImport(() => import('modal/modalFirstReward' /* webpackChunkName: "modalFirstReward" */)); -const ModalFirstSubscription = lazyImport(() => - import('modal/modalFirstSubscription' /* webpackChunkName: "modalFirstSubscription" */) -); +const ModalFirstSubscription = lazyImport(() => import('modal/modalFirstSubscription' /* webpackChunkName: "modalFirstSubscription" */)); const ModalImageUpload = lazyImport(() => import('modal/modalImageUpload' /* webpackChunkName: "modalImageUpload" */)); -const ModalMassTipsUnlock = lazyImport(() => - import('modal/modalMassTipUnlock' /* webpackChunkName: "modalMassTipUnlock" */) -); -const ModalMobileSearch = lazyImport(() => - import('modal/modalMobileSearch' /* webpackChunkName: "modalMobileSearch" */) -); -const ModalOpenExternalResource = lazyImport(() => - import('modal/modalOpenExternalResource' /* webpackChunkName: "modalOpenExternalResource" */) -); -const ModalPasswordUnsave = lazyImport(() => - import('modal/modalPasswordUnsave' /* webpackChunkName: "modalPasswordUnsave" */) -); -const ModalPhoneCollection = lazyImport(() => - import('modal/modalPhoneCollection' /* webpackChunkName: "modalPhoneCollection" */) -); +const ModalMassTipsUnlock = lazyImport(() => import('modal/modalMassTipUnlock' /* webpackChunkName: "modalMassTipUnlock" */)); +const ModalMobileSearch = lazyImport(() => import('modal/modalMobileSearch' /* webpackChunkName: "modalMobileSearch" */)); +const ModalOpenExternalResource = lazyImport(() => import('modal/modalOpenExternalResource' /* webpackChunkName: "modalOpenExternalResource" */)); +const ModalPasswordUnsave = lazyImport(() => import('modal/modalPasswordUnsave' /* webpackChunkName: "modalPasswordUnsave" */)); +const ModalPhoneCollection = lazyImport(() => import('modal/modalPhoneCollection' /* webpackChunkName: "modalPhoneCollection" */)); const ModalPublish = lazyImport(() => import('modal/modalPublish' /* webpackChunkName: "modalPublish" */)); -const ModalPublishPreview = lazyImport(() => - import('modal/modalPublishPreview' /* webpackChunkName: "modalPublishPreview" */) -); -const ModalRemoveBtcSwapAddress = lazyImport(() => - import('modal/modalRemoveBtcSwapAddress' /* webpackChunkName: "modalRemoveBtcSwapAddress" */) -); +const ModalPublishPreview = lazyImport(() => import('modal/modalPublishPreview' /* webpackChunkName: "modalPublishPreview" */)); +const ModalRemoveBtcSwapAddress = lazyImport(() => import('modal/modalRemoveBtcSwapAddress' /* webpackChunkName: "modalRemoveBtcSwapAddress" */)); const ModalRemoveCard = lazyImport(() => import('modal/modalRemoveCard' /* webpackChunkName: "modalRemoveCard" */)); -const ModalRemoveComment = lazyImport(() => - import('modal/modalRemoveComment' /* webpackChunkName: "modalRemoveComment" */) -); +const ModalRemoveComment = lazyImport(() => import('modal/modalRemoveComment' /* webpackChunkName: "modalRemoveComment" */)); const ModalRemoveFile = lazyImport(() => import('modal/modalRemoveFile' /* webpackChunkName: "modalRemoveFile" */)); const ModalRevokeClaim = lazyImport(() => import('modal/modalRevokeClaim' /* webpackChunkName: "modalRevokeClaim" */)); const ModalRewardCode = lazyImport(() => import('modal/modalRewardCode' /* webpackChunkName: "modalRewardCode" */)); @@ -77,27 +38,15 @@ const ModalSendTip = lazyImport(() => import('modal/modalSendTip' /* webpackChun const ModalSetReferrer = lazyImport(() => import('modal/modalSetReferrer' /* webpackChunkName: "modalSetReferrer" */)); const ModalSignOut = lazyImport(() => import('modal/modalSignOut' /* webpackChunkName: "modalSignOut" */)); const ModalSocialShare = lazyImport(() => import('modal/modalSocialShare' /* webpackChunkName: "modalSocialShare" */)); -const ModalSupportsLiquidate = lazyImport(() => - import('modal/modalSupportsLiquidate' /* webpackChunkName: "modalSupportsLiquidate" */) -); +const ModalSupportsLiquidate = lazyImport(() => import('modal/modalSupportsLiquidate' /* webpackChunkName: "modalSupportsLiquidate" */)); const ModalSyncEnable = lazyImport(() => import('modal/modalSyncEnable' /* webpackChunkName: "modalSyncEnable" */)); -const ModalTransactionFailed = lazyImport(() => - import('modal/modalTransactionFailed' /* webpackChunkName: "modalTransactionFailed" */) -); +const ModalTransactionFailed = lazyImport(() => import('modal/modalTransactionFailed' /* webpackChunkName: "modalTransactionFailed" */)); const ModalUpgrade = lazyImport(() => import('modal/modalUpgrade' /* webpackChunkName: "modalUpgrade" */)); const ModalViewImage = lazyImport(() => import('modal/modalViewImage' /* webpackChunkName: "modalViewImage" */)); -const ModalWalletDecrypt = lazyImport(() => - import('modal/modalWalletDecrypt' /* webpackChunkName: "modalWalletDecrypt" */) -); -const ModalWalletEncrypt = lazyImport(() => - import('modal/modalWalletEncrypt' /* webpackChunkName: "modalWalletEncrypt" */) -); -const ModalWalletUnlock = lazyImport(() => - import('modal/modalWalletUnlock' /* webpackChunkName: "modalWalletUnlock" */) -); -const ModalYoutubeWelcome = lazyImport(() => - import('modal/modalYoutubeWelcome' /* webpackChunkName: "modalYoutubeWelcome" */) -); +const ModalWalletDecrypt = lazyImport(() => import('modal/modalWalletDecrypt' /* webpackChunkName: "modalWalletDecrypt" */)); +const ModalWalletEncrypt = lazyImport(() => import('modal/modalWalletEncrypt' /* webpackChunkName: "modalWalletEncrypt" */)); +const ModalWalletUnlock = lazyImport(() => import('modal/modalWalletUnlock' /* webpackChunkName: "modalWalletUnlock" */)); +const ModalYoutubeWelcome = lazyImport(() => import('modal/modalYoutubeWelcome' /* webpackChunkName: "modalYoutubeWelcome" */)); type Props = { modal: { id: string, modalProps: {} }, @@ -200,8 +149,6 @@ function ModalRouter(props: Props) { return ModalMassTipsUnlock; case MODALS.CONFIRM_REMOVE_BTC_SWAP_ADDRESS: return ModalRemoveBtcSwapAddress; - case MODALS.BLOCK_CHANNEL: - return ModalBlockChannel; case MODALS.COLLECTION_ADD: return ModalClaimCollectionAdd; case MODALS.COLLECTION_DELETE: diff --git a/ui/page/listBlocked/index.js b/ui/page/listBlocked/index.js index 178b11aa9..e3e1d5c55 100644 --- a/ui/page/listBlocked/index.js +++ b/ui/page/listBlocked/index.js @@ -8,9 +8,6 @@ import { selectModeratorBlockListDelegatorsMap, selectFetchingModerationBlockList, selectModerationDelegatorsById, - selectAdminTimeoutMap, - selectModeratorTimeoutMap, - selectPersonalTimeoutMap, } from 'redux/selectors/comments'; import { selectMyChannelClaims } from 'lbry-redux'; import ListBlocked from './view'; @@ -20,9 +17,6 @@ const select = (state) => ({ personalBlockList: selectModerationBlockList(state), adminBlockList: selectAdminBlockList(state), moderatorBlockList: selectModeratorBlockList(state), - personalTimeoutMap: selectPersonalTimeoutMap(state), - adminTimeoutMap: selectAdminTimeoutMap(state), - moderatorTimeoutMap: selectModeratorTimeoutMap(state), moderatorBlockListDelegatorsMap: selectModeratorBlockListDelegatorsMap(state), delegatorsById: selectModerationDelegatorsById(state), myChannelClaims: selectMyChannelClaims(state), diff --git a/ui/page/listBlocked/view.jsx b/ui/page/listBlocked/view.jsx index 8036a8f1f..85f355947 100644 --- a/ui/page/listBlocked/view.jsx +++ b/ui/page/listBlocked/view.jsx @@ -3,8 +3,6 @@ import * as ICONS from 'constants/icons'; import { BLOCK_LEVEL } from 'constants/comment'; import React from 'react'; import classnames from 'classnames'; -import moment from 'moment'; -import humanizeDuration from 'humanize-duration'; import ClaimList from 'component/claimList'; import ClaimPreview from 'component/claimPreview'; import Page from 'component/page'; @@ -27,9 +25,6 @@ type Props = { personalBlockList: ?Array, adminBlockList: ?Array, moderatorBlockList: ?Array, - personalTimeoutMap: { [uri: string]: { blockedAt: string, bannedFor: number, banRemaining: number } }, - adminTimeoutMap: { [uri: string]: { blockedAt: string, bannedFor: number, banRemaining: number } }, - moderatorTimeoutMap: { [uri: string]: { blockedAt: string, bannedFor: number, banRemaining: number } }, moderatorBlockListDelegatorsMap: { [string]: Array }, fetchingModerationBlockList: boolean, fetchModBlockedList: () => void, @@ -44,9 +39,6 @@ function ListBlocked(props: Props) { personalBlockList, adminBlockList, moderatorBlockList, - personalTimeoutMap, - adminTimeoutMap, - moderatorTimeoutMap, moderatorBlockListDelegatorsMap, fetchingModerationBlockList, fetchModBlockedList, @@ -105,45 +97,17 @@ function ListBlocked(props: Props) { } function getButtons(view, uri) { - const getDurationStr = (durationNs) => { - const NANO_TO_MS = 1000000; - return humanizeDuration(durationNs / NANO_TO_MS, { round: true }); - }; - - const getBanInfoElem = (timeoutInfo) => { - return ( -
-
-
- {moment(timeoutInfo.blockedAt).format('MMMM Do, YYYY @ HH:mm')} -
- {getDurationStr(timeoutInfo.bannedFor)}{' '} - {__('(Remaining: %duration%) --[timeout ban duration]--', { - duration: getDurationStr(timeoutInfo.banRemaining), - })} -
-
-
- ); - }; - switch (view) { case VIEW.BLOCKED: return ( <> - {personalTimeoutMap[uri] && getBanInfoElem(personalTimeoutMap[uri])} ); case VIEW.ADMIN: - return ( - <> - - {adminTimeoutMap[uri] && getBanInfoElem(adminTimeoutMap[uri])} - - ); + return ; case VIEW.MODERATOR: const delegatorUrisForBlockedUri = localModeratorListDelegatorsMap && localModeratorListDelegatorsMap[uri]; @@ -157,7 +121,6 @@ function ListBlocked(props: Props) { - {moderatorTimeoutMap[uri] && getBanInfoElem(moderatorTimeoutMap[uri])} ); })} diff --git a/ui/recsys.js b/ui/recsys.js index f5d8ae106..6a92e2bd2 100644 --- a/ui/recsys.js +++ b/ui/recsys.js @@ -110,7 +110,7 @@ const recsys = { uid: userId, // selectUser claimId: claimId, pageLoadedAt: Date.now(), - recsysId: makeSelectRecommendedRecsysIdForClaimId(claimId)(state) || recsysId, + recsysId: null, recClaimIds: [], recClickedVideoIdx: [], events: [], diff --git a/ui/redux/actions/comments.js b/ui/redux/actions/comments.js index dc85ba754..a1ce7d175 100644 --- a/ui/redux/actions/comments.js +++ b/ui/redux/actions/comments.js @@ -738,7 +738,6 @@ function doCommentModToggleBlock( creatorId: string, blockerIds: Array, // [] = use all my channels blockLevel: string, - timeoutSec?: number, showLink: boolean = false ) { return async (dispatch: Dispatch, getState: GetState) => { @@ -845,7 +844,6 @@ function doCommentModToggleBlock( block_all: unblock ? undefined : blockLevel === BLOCK_LEVEL.ADMIN, global_un_block: unblock ? blockLevel === BLOCK_LEVEL.ADMIN : undefined, ...sharedModBlockParams, - time_out: unblock ? undefined : timeoutSec, }) ) ) @@ -922,13 +920,12 @@ function doCommentModToggleBlock( * Blocks the commenter for all channels that I own. * * @param commenterUri - * @param timeoutHours * @param showLink * @returns {function(Dispatch): *} */ -export function doCommentModBlock(commenterUri: string, timeoutHours?: number, showLink: boolean = true) { +export function doCommentModBlock(commenterUri: string, showLink: boolean = true) { return (dispatch: Dispatch) => { - return dispatch(doCommentModToggleBlock(false, commenterUri, '', [], BLOCK_LEVEL.SELF, timeoutHours, showLink)); + return dispatch(doCommentModToggleBlock(false, commenterUri, '', [], BLOCK_LEVEL.SELF, showLink)); }; } @@ -937,14 +934,11 @@ export function doCommentModBlock(commenterUri: string, timeoutHours?: number, s * * @param commenterUri * @param blockerId - * @param timeoutHours * @returns {function(Dispatch): *} */ -export function doCommentModBlockAsAdmin(commenterUri: string, blockerId: string, timeoutHours?: number) { +export function doCommentModBlockAsAdmin(commenterUri: string, blockerId: string) { return (dispatch: Dispatch) => { - return dispatch( - doCommentModToggleBlock(false, commenterUri, '', blockerId ? [blockerId] : [], BLOCK_LEVEL.ADMIN, timeoutHours) - ); + return dispatch(doCommentModToggleBlock(false, commenterUri, '', blockerId ? [blockerId] : [], BLOCK_LEVEL.ADMIN)); }; } @@ -955,25 +949,12 @@ export function doCommentModBlockAsAdmin(commenterUri: string, blockerId: string * @param commenterUri * @param creatorId * @param blockerId - * @param timeoutHours * @returns {function(Dispatch): *} */ -export function doCommentModBlockAsModerator( - commenterUri: string, - creatorId: string, - blockerId: string, - timeoutHours?: number -) { +export function doCommentModBlockAsModerator(commenterUri: string, creatorId: string, blockerId: string) { return (dispatch: Dispatch) => { return dispatch( - doCommentModToggleBlock( - false, - commenterUri, - creatorId, - blockerId ? [blockerId] : [], - BLOCK_LEVEL.MODERATOR, - timeoutHours - ) + doCommentModToggleBlock(false, commenterUri, creatorId, blockerId ? [blockerId] : [], BLOCK_LEVEL.MODERATOR) ); }; } @@ -987,7 +968,7 @@ export function doCommentModBlockAsModerator( */ export function doCommentModUnBlock(commenterUri: string, showLink: boolean = true) { return (dispatch: Dispatch) => { - return dispatch(doCommentModToggleBlock(true, commenterUri, '', [], BLOCK_LEVEL.SELF, undefined, showLink)); + return dispatch(doCommentModToggleBlock(true, commenterUri, '', [], BLOCK_LEVEL.SELF, showLink)); }; } @@ -1054,20 +1035,13 @@ export function doFetchModBlockedList() { let moderatorBlockList = []; let moderatorBlockListDelegatorsMap = {}; - // These should just be part of the block list above, but it is - // separated for now because there are too many clients that we need - // to update. - const personalTimeoutMap = {}; - const adminTimeoutMap = {}; - const moderatorTimeoutMap = {}; - const blockListsPerChannel = res.map((r) => r.value); blockListsPerChannel .sort((a, b) => { return 1; }) .forEach((channelBlockLists) => { - const storeList = (fetchedList, blockedList, timeoutMap, blockedByMap) => { + const storeList = (fetchedList, blockedList, blockedByMap) => { if (fetchedList) { fetchedList.forEach((blockedChannel) => { if (blockedChannel.blocked_channel_name) { @@ -1078,14 +1052,6 @@ export function doFetchModBlockedList() { if (!blockedList.find((blockedChannel) => isURIEqual(blockedChannel.channelUri, channelUri))) { blockedList.push({ channelUri, blockedAt: blockedChannel.blocked_at }); - - if (blockedChannel.banned_for) { - timeoutMap[channelUri] = { - blockedAt: blockedChannel.blocked_at, - bannedFor: blockedChannel.banned_for, - banRemaining: blockedChannel.ban_remaining, - }; - } } if (blockedByMap !== undefined) { @@ -1111,14 +1077,9 @@ export function doFetchModBlockedList() { const globally_blocked_channels = channelBlockLists && channelBlockLists.globally_blocked_channels; const delegated_blocked_channels = channelBlockLists && channelBlockLists.delegated_blocked_channels; - storeList(blocked_channels, personalBlockList, personalTimeoutMap); - storeList(globally_blocked_channels, adminBlockList, adminTimeoutMap); - storeList( - delegated_blocked_channels, - moderatorBlockList, - moderatorTimeoutMap, - moderatorBlockListDelegatorsMap - ); + storeList(blocked_channels, personalBlockList); + storeList(globally_blocked_channels, adminBlockList); + storeList(delegated_blocked_channels, moderatorBlockList, moderatorBlockListDelegatorsMap); }); dispatch({ @@ -1143,9 +1104,6 @@ export function doFetchModBlockedList() { .map((blockedChannel) => blockedChannel.channelUri) : null, moderatorBlockListDelegatorsMap: moderatorBlockListDelegatorsMap, - personalTimeoutMap, - adminTimeoutMap, - moderatorTimeoutMap, }, }); }) diff --git a/ui/redux/reducers/comments.js b/ui/redux/reducers/comments.js index 04c0bed8d..815025698 100644 --- a/ui/redux/reducers/comments.js +++ b/ui/redux/reducers/comments.js @@ -40,9 +40,6 @@ const defaultState: CommentsState = { fetchingModerationDelegators: false, blockingByUri: {}, unBlockingByUri: {}, - personalTimeoutMap: {}, - adminTimeoutMap: {}, - moderatorTimeoutMap: {}, togglingForDelegatorMap: {}, settingsByChannelId: {}, // ChannelId -> PerChannelSettings fetchingSettings: false, @@ -674,25 +671,14 @@ export default handleActions( fetchingModerationBlockList: true, }), [ACTIONS.COMMENT_MODERATION_BLOCK_LIST_COMPLETED]: (state: CommentsState, action: any) => { - const { - personalBlockList, - adminBlockList, - moderatorBlockList, - moderatorBlockListDelegatorsMap, - personalTimeoutMap, - adminTimeoutMap, - moderatorTimeoutMap, - } = action.data; + const { personalBlockList, adminBlockList, moderatorBlockList, moderatorBlockListDelegatorsMap } = action.data; return { ...state, moderationBlockList: personalBlockList, adminBlockList: adminBlockList, moderatorBlockList: moderatorBlockList, - moderatorBlockListDelegatorsMap, - personalTimeoutMap, - adminTimeoutMap, - moderatorTimeoutMap, + moderatorBlockListDelegatorsMap: moderatorBlockListDelegatorsMap, fetchingModerationBlockList: false, }; }, diff --git a/ui/redux/selectors/comments.js b/ui/redux/selectors/comments.js index 82365b9fa..e4c21ff54 100644 --- a/ui/redux/selectors/comments.js +++ b/ui/redux/selectors/comments.js @@ -45,10 +45,6 @@ export const selectModeratorBlockList = createSelector(selectState, (state) => state.moderatorBlockList ? state.moderatorBlockList.reverse() : [] ); -export const selectPersonalTimeoutMap = createSelector(selectState, (state) => state.personalTimeoutMap); -export const selectAdminTimeoutMap = createSelector(selectState, (state) => state.adminTimeoutMap); -export const selectModeratorTimeoutMap = createSelector(selectState, (state) => state.moderatorTimeoutMap); - export const selectModeratorBlockListDelegatorsMap = createSelector( selectState, (state) => state.moderatorBlockListDelegatorsMap @@ -214,7 +210,7 @@ export const makeSelectCommentsForUri = (uri: string) => (state, byClaimId, byUri) => { const claimId = byUri[uri]; const comments = byClaimId && byClaimId[claimId]; - return makeSelectFilteredComments(comments, claimId)(state); + return makeSelectFilteredComments(comments)(state); } ); @@ -226,7 +222,7 @@ export const makeSelectTopLevelCommentsForUri = (uri: string) => (state, byClaimId, byUri) => { const claimId = byUri[uri]; const comments = byClaimId && byClaimId[claimId]; - return makeSelectFilteredComments(comments, claimId)(state); + return makeSelectFilteredComments(comments)(state); } ); @@ -262,13 +258,7 @@ export const makeSelectRepliesForParentId = (id: string) => } ); -/** - * makeSelectFilteredComments - * - * @param comments List of comments to filter. - * @param claimId The claim that `comments` reside in. - */ -const makeSelectFilteredComments = (comments: Array, claimId?: string) => +const makeSelectFilteredComments = (comments: Array) => createSelector( selectClaimsById, selectMyActiveClaims, @@ -321,18 +311,12 @@ const makeSelectFilteredComments = (comments: Array, claimId?: string) } } - if (claimId) { - const claimIdIsMine = myClaims && myClaims.size > 0 && myClaims.has(claimId); - if (!claimIdIsMine) { - return !( - personalBlockList.includes(comment.channel_url) || - adminBlockList.includes(comment.channel_url) || - moderatorBlockList.includes(comment.channel_url) - ); - } - } - - return !mutedChannels.includes(comment.channel_url); + return !( + mutedChannels.includes(comment.channel_url) || + personalBlockList.includes(comment.channel_url) || + adminBlockList.includes(comment.channel_url) || + moderatorBlockList.includes(comment.channel_url) + ); }) : []; } diff --git a/ui/scss/component/_block-list.scss b/ui/scss/component/_block-list.scss index bf46aed68..4caf7d1a4 100644 --- a/ui/scss/component/_block-list.scss +++ b/ui/scss/component/_block-list.scss @@ -16,43 +16,3 @@ margin-top: var(--spacing-xxs); } } - -.block-modal--values { - margin-left: var(--spacing-s); - - .help { - font-style: italic; - font-size: var(--font-xsmall); - } -} - -.block-modal--finalize { - margin-top: var(--spacing-l); -} - -.block-modal--active-channel { - padding: var(--spacing-xs); - display: flex; - align-items: center; - - .channel-thumbnail { - margin-right: var(--spacing-xs); - height: 1.8rem; - width: 1.8rem; - } - - @media (min-width: $breakpoint-small) { - border-left: 1px solid var(--color-border); - padding-left: var(--spacing-m); - margin-left: calc(var(--spacing-l) * 2); - } -} - -.block-modal--active-channel-label { - @extend .help; - font-size: var(--font-xxsmall); - margin-top: 0; - max-width: 10rem; - white-space: pre-line; - margin-right: var(--spacing-s); -} diff --git a/yarn.lock b/yarn.lock index c65da973f..2b521ec43 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8558,11 +8558,6 @@ https-proxy-agent@^4.0.0: agent-base "5" debug "4" -humanize-duration@^3.27.0: - version "3.27.0" - resolved "https://registry.yarnpkg.com/humanize-duration/-/humanize-duration-3.27.0.tgz#3f781b7cf8022ad587f76b9839b60bc2b29636b2" - integrity sha512-qLo/08cNc3Tb0uD7jK0jAcU5cnqCM0n568918E7R2XhMr/+7F37p4EY062W/stg7tmzvknNn9b/1+UhVRzsYrQ== - humanize-plus@^1.8.1: version "1.8.2" resolved "https://registry.yarnpkg.com/humanize-plus/-/humanize-plus-1.8.2.tgz#a65b34459ad6367adbb3707a82a3c9f916167030" @@ -11921,11 +11916,6 @@ parse-asn1@^5.0.0: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" -parse-duration@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-duration/-/parse-duration-1.0.0.tgz#8605651745f61088f6fb14045c887526c291858c" - integrity sha512-X4kUkCTHU1N/kEbwK9FpUJ0UZQa90VzeczfS704frR30gljxDG0pSziws06XlK+CGRSo/1wtG1mFIdBFQTMQNw== - parse-entities@^1.0.2, parse-entities@^1.1.0: version "1.2.2" resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.2.2.tgz#c31bf0f653b6661354f8973559cb86dd1d5edf50"