#6878 Hide comments based on own blocklist
This commit is contained in:
commit
749862c333
7 changed files with 95 additions and 175 deletions
2
flow-typed/Comment.js
vendored
2
flow-typed/Comment.js
vendored
|
@ -35,7 +35,7 @@ declare type CommentsState = {
|
|||
byId: { [string]: Array<string> }, // ClaimID -> list of fetched comment IDs.
|
||||
totalCommentsById: {}, // ClaimId -> ultimate total (including replies) in commentron.
|
||||
repliesByParentId: { [string]: Array<string> }, // ParentCommentID -> list of fetched replies.
|
||||
totalRepliesByParentId: {}, // ParentCommentID -> total replies in commentron.
|
||||
repliesTotalPagesByParentId: {}, // ParentCommentID -> total number of reply pages for a parentId in commentron.
|
||||
topLevelCommentsById: { [string]: Array<string> }, // ClaimID -> list of fetched top level comments.
|
||||
topLevelTotalPagesById: { [string]: number }, // ClaimID -> total number of top-level pages in commentron. Based on COMMENT_PAGE_SIZE_TOP_LEVEL.
|
||||
topLevelTotalCommentsById: { [string]: number }, // ClaimID -> total top level comments in commentron.
|
||||
|
|
|
@ -10,7 +10,11 @@ import { makeSelectChannelIsMuted } from 'redux/selectors/blocked';
|
|||
import { doToast } from 'redux/actions/notifications';
|
||||
import { doSetPlayingUri } from 'redux/actions/content';
|
||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||
import { selectLinkedCommentAncestors, makeSelectOthersReactionsForComment } from 'redux/selectors/comments';
|
||||
import {
|
||||
selectLinkedCommentAncestors,
|
||||
makeSelectOthersReactionsForComment,
|
||||
makeSelectTotalReplyPagesForParentId,
|
||||
} from 'redux/selectors/comments';
|
||||
import { selectActiveChannelClaim } from 'redux/selectors/app';
|
||||
import { selectPlayingUri } from 'redux/selectors/content';
|
||||
import Comment from './view';
|
||||
|
@ -31,6 +35,7 @@ const select = (state, props) => {
|
|||
playingUri: selectPlayingUri(state),
|
||||
stakedLevel: makeSelectStakedLevelForChannelUri(props.authorUri)(state),
|
||||
linkedCommentAncestors: selectLinkedCommentAncestors(state),
|
||||
totalReplyPages: makeSelectTotalReplyPagesForParentId(props.commentId)(state),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ type Props = {
|
|||
commentIsMine: boolean, // if this comment was signed by an owned channel
|
||||
updateComment: (string, string) => void,
|
||||
fetchReplies: (string, string, number, number, number) => void,
|
||||
totalReplyPages: number,
|
||||
commentModBlock: (string) => void,
|
||||
linkedCommentId?: string,
|
||||
linkedCommentAncestors: { [string]: Array<string> },
|
||||
|
@ -82,6 +83,7 @@ function Comment(props: Props) {
|
|||
commentId,
|
||||
updateComment,
|
||||
fetchReplies,
|
||||
totalReplyPages,
|
||||
linkedCommentId,
|
||||
linkedCommentAncestors,
|
||||
commentingEnabled,
|
||||
|
@ -417,6 +419,7 @@ function Comment(props: Props) {
|
|||
linkedCommentId={linkedCommentId}
|
||||
numDirectReplies={numDirectReplies}
|
||||
onShowMore={() => setPage(page + 1)}
|
||||
hasMore={page < totalReplyPages}
|
||||
/>
|
||||
)}
|
||||
</li>
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { makeSelectClaimIsMine, selectMyChannelClaims } from 'lbry-redux';
|
||||
import {
|
||||
selectIsFetchingCommentsByParentId,
|
||||
makeSelectRepliesForParentId,
|
||||
makeSelectTotalRepliesForParentId,
|
||||
} from 'redux/selectors/comments';
|
||||
import { selectIsFetchingCommentsByParentId, makeSelectRepliesForParentId } from 'redux/selectors/comments';
|
||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||
import CommentsReplies from './view';
|
||||
|
||||
const select = (state, props) => ({
|
||||
fetchedReplies: makeSelectRepliesForParentId(props.parentId)(state),
|
||||
totalReplies: makeSelectTotalRepliesForParentId(props.parentId)(state),
|
||||
claimIsMine: makeSelectClaimIsMine(props.uri)(state),
|
||||
commentingEnabled: IS_WEB ? Boolean(selectUserVerifiedEmail(state)) : true,
|
||||
myChannels: selectMyChannelClaims(state),
|
||||
|
|
|
@ -4,11 +4,9 @@ import React from 'react';
|
|||
import Comment from 'component/comment';
|
||||
import Button from 'component/button';
|
||||
import Spinner from 'component/spinner';
|
||||
import ChannelThumbnail from 'component/channelThumbnail';
|
||||
|
||||
type Props = {
|
||||
fetchedReplies: Array<any>,
|
||||
totalReplies: number,
|
||||
uri: string,
|
||||
parentId: string,
|
||||
claimIsMine: boolean,
|
||||
|
@ -16,9 +14,10 @@ type Props = {
|
|||
linkedCommentId?: string,
|
||||
commentingEnabled: boolean,
|
||||
threadDepth: number,
|
||||
numDirectReplies: number,
|
||||
numDirectReplies: number, // Total replies for parentId as reported by 'comment[replies]'. Includes blocked items.
|
||||
isFetchingByParentId: { [string]: boolean },
|
||||
onShowMore?: () => void,
|
||||
hasMore: boolean,
|
||||
};
|
||||
|
||||
function CommentsReplies(props: Props) {
|
||||
|
@ -26,7 +25,6 @@ function CommentsReplies(props: Props) {
|
|||
uri,
|
||||
parentId,
|
||||
fetchedReplies,
|
||||
totalReplies,
|
||||
claimIsMine,
|
||||
myChannels,
|
||||
linkedCommentId,
|
||||
|
@ -35,6 +33,7 @@ function CommentsReplies(props: Props) {
|
|||
numDirectReplies,
|
||||
isFetchingByParentId,
|
||||
onShowMore,
|
||||
hasMore,
|
||||
} = props;
|
||||
|
||||
const [isExpanded, setExpanded] = React.useState(true);
|
||||
|
@ -102,28 +101,11 @@ function CommentsReplies(props: Props) {
|
|||
/>
|
||||
);
|
||||
})}
|
||||
{!isFetchingByParentId[parentId] && totalReplies < numDirectReplies && (
|
||||
<li className="comment comment--reply">
|
||||
<div className="comment__content">
|
||||
<div className="comment__thumbnail-wrapper">
|
||||
<ChannelThumbnail xsmall className="comment__author-thumbnail" />
|
||||
</div>
|
||||
<div className="comment__body-container comment--blocked">
|
||||
<div className="comment__meta">
|
||||
<em>---</em>
|
||||
</div>
|
||||
<div>
|
||||
<em>{__('Comment(s) blocked.')}</em>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{isExpanded && fetchedReplies && displayedComments.length < totalReplies && (
|
||||
{isExpanded && fetchedReplies && hasMore && (
|
||||
<div className="comment__actions--nested">
|
||||
<Button button="link" label={__('Show more')} onClick={showMore} className="button--uri-indicator" />
|
||||
</div>
|
||||
|
|
|
@ -9,7 +9,7 @@ const defaultState: CommentsState = {
|
|||
byId: {}, // ClaimID -> list of fetched comment IDs.
|
||||
totalCommentsById: {}, // ClaimId -> ultimate total (including replies) in commentron.
|
||||
repliesByParentId: {}, // ParentCommentID -> list of fetched replies.
|
||||
totalRepliesByParentId: {}, // ParentCommentID -> total replies in commentron.
|
||||
repliesTotalPagesByParentId: {}, // ParentCommentID -> total number of reply pages for a parentId in commentron.
|
||||
topLevelCommentsById: {}, // ClaimID -> list of fetched top level comments.
|
||||
topLevelTotalPagesById: {}, // ClaimID -> total number of top-level pages in commentron. Based on COMMENT_PAGE_SIZE_TOP_LEVEL.
|
||||
topLevelTotalCommentsById: {}, // ClaimID -> total top level comments in commentron.
|
||||
|
@ -79,7 +79,6 @@ export default handleActions(
|
|||
const totalCommentsById = Object.assign({}, state.totalCommentsById);
|
||||
const topLevelCommentsById = Object.assign({}, state.topLevelCommentsById); // was byId {ClaimId -> [commentIds...]}
|
||||
const repliesByParentId = Object.assign({}, state.repliesByParentId); // {ParentCommentID -> [commentIds...] } list of reply comments
|
||||
const totalRepliesByParentId = Object.assign({}, state.totalRepliesByParentId);
|
||||
const commentsByUri = Object.assign({}, state.commentsByUri);
|
||||
const comments = byId[claimId] || [];
|
||||
const newCommentIds = comments.slice();
|
||||
|
@ -104,12 +103,6 @@ export default handleActions(
|
|||
repliesByParentId[comment.parent_id].unshift(comment.comment_id);
|
||||
}
|
||||
|
||||
if (!totalRepliesByParentId[comment.parent_id]) {
|
||||
totalRepliesByParentId[comment.parent_id] = 1;
|
||||
} else {
|
||||
totalRepliesByParentId[comment.parent_id] += 1;
|
||||
}
|
||||
|
||||
// Update the parent's "replies" value
|
||||
if (commentById[comment.parent_id]) {
|
||||
commentById[comment.parent_id].replies = (commentById[comment.parent_id].replies || 0) + 1;
|
||||
|
@ -128,7 +121,6 @@ export default handleActions(
|
|||
...state,
|
||||
topLevelCommentsById,
|
||||
repliesByParentId,
|
||||
totalRepliesByParentId,
|
||||
commentById,
|
||||
byId,
|
||||
totalCommentsById,
|
||||
|
@ -262,7 +254,7 @@ export default handleActions(
|
|||
const repliesByParentId = Object.assign({}, state.repliesByParentId);
|
||||
const totalCommentsById = Object.assign({}, state.totalCommentsById);
|
||||
const pinnedCommentsById = Object.assign({}, state.pinnedCommentsById);
|
||||
const totalRepliesByParentId = Object.assign({}, state.totalRepliesByParentId);
|
||||
const repliesTotalPagesByParentId = Object.assign({}, state.repliesTotalPagesByParentId);
|
||||
const isLoadingByParentId = Object.assign({}, state.isLoadingByParentId);
|
||||
const settingsByChannelId = Object.assign({}, state.settingsByChannelId);
|
||||
|
||||
|
@ -277,7 +269,7 @@ export default handleActions(
|
|||
|
||||
if (!disabled) {
|
||||
if (parentId) {
|
||||
totalRepliesByParentId[parentId] = totalFilteredItems;
|
||||
repliesTotalPagesByParentId[parentId] = totalPages;
|
||||
} else {
|
||||
totalCommentsById[claimId] = totalItems;
|
||||
topLevelTotalCommentsById[claimId] = totalFilteredItems;
|
||||
|
@ -330,7 +322,7 @@ export default handleActions(
|
|||
repliesByParentId,
|
||||
totalCommentsById,
|
||||
pinnedCommentsById,
|
||||
totalRepliesByParentId,
|
||||
repliesTotalPagesByParentId,
|
||||
byId,
|
||||
commentById,
|
||||
commentsByUri,
|
||||
|
@ -548,7 +540,6 @@ export default handleActions(
|
|||
const commentById = Object.assign({}, state.commentById);
|
||||
const byId = Object.assign({}, state.byId);
|
||||
const repliesByParentId = Object.assign({}, state.repliesByParentId); // {ParentCommentID -> [commentIds...] } list of reply comments
|
||||
const totalRepliesByParentId = Object.assign({}, state.totalRepliesByParentId);
|
||||
const totalCommentsById = Object.assign({}, state.totalCommentsById);
|
||||
|
||||
const comment = commentById[comment_id];
|
||||
|
@ -571,10 +562,6 @@ export default handleActions(
|
|||
if (commentById[comment.parent_id]) {
|
||||
commentById[comment.parent_id].replies = Math.max(0, (commentById[comment.parent_id].replies || 0) - 1);
|
||||
}
|
||||
|
||||
if (totalRepliesByParentId[comment.parent_id]) {
|
||||
totalRepliesByParentId[comment.parent_id] = Math.max(0, totalRepliesByParentId[comment.parent_id] - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -590,7 +577,6 @@ export default handleActions(
|
|||
byId,
|
||||
totalCommentsById,
|
||||
repliesByParentId,
|
||||
totalRepliesByParentId,
|
||||
isLoading: false,
|
||||
};
|
||||
},
|
||||
|
|
|
@ -204,18 +204,82 @@ export const selectFetchingBlockedWords = createSelector(selectState, (state) =>
|
|||
|
||||
export const makeSelectCommentsForUri = (uri: string) =>
|
||||
createSelector(
|
||||
(state) => state,
|
||||
selectCommentsByClaimId,
|
||||
selectCommentsByUri,
|
||||
(state, byClaimId, byUri) => {
|
||||
const claimId = byUri[uri];
|
||||
const comments = byClaimId && byClaimId[claimId];
|
||||
return makeSelectFilteredComments(comments)(state);
|
||||
}
|
||||
);
|
||||
|
||||
export const makeSelectTopLevelCommentsForUri = (uri: string) =>
|
||||
createSelector(
|
||||
(state) => state,
|
||||
selectTopLevelCommentsByClaimId,
|
||||
selectCommentsByUri,
|
||||
(state, byClaimId, byUri) => {
|
||||
const claimId = byUri[uri];
|
||||
const comments = byClaimId && byClaimId[claimId];
|
||||
return makeSelectFilteredComments(comments)(state);
|
||||
}
|
||||
);
|
||||
|
||||
export const makeSelectTopLevelTotalCommentsForUri = (uri: string) =>
|
||||
createSelector(selectState, selectCommentsByUri, (state, byUri) => {
|
||||
const claimId = byUri[uri];
|
||||
return state.topLevelTotalCommentsById[claimId] || 0;
|
||||
});
|
||||
|
||||
export const makeSelectTopLevelTotalPagesForUri = (uri: string) =>
|
||||
createSelector(selectState, selectCommentsByUri, (state, byUri) => {
|
||||
const claimId = byUri[uri];
|
||||
return state.topLevelTotalPagesById[claimId] || 0;
|
||||
});
|
||||
|
||||
export const makeSelectRepliesForParentId = (id: string) =>
|
||||
createSelector(
|
||||
(state) => state,
|
||||
selectCommentsById,
|
||||
(state, commentsById) => {
|
||||
// const claimId = byUri[uri]; // just parentId (id)
|
||||
const replyIdsByParentId = state.comments.repliesByParentId;
|
||||
const replyIdsForParent = replyIdsByParentId[id] || [];
|
||||
if (!replyIdsForParent.length) return null;
|
||||
|
||||
const comments = [];
|
||||
replyIdsForParent.forEach((cid) => {
|
||||
comments.push(commentsById[cid]);
|
||||
});
|
||||
// const comments = byParentId && byParentId[id];
|
||||
|
||||
return makeSelectFilteredComments(comments)(state);
|
||||
}
|
||||
);
|
||||
|
||||
const makeSelectFilteredComments = (comments: Array<Comment>) =>
|
||||
createSelector(
|
||||
selectClaimsById,
|
||||
selectMyActiveClaims,
|
||||
selectMutedChannels,
|
||||
selectModerationBlockList,
|
||||
selectAdminBlockList,
|
||||
selectModeratorBlockList,
|
||||
selectBlacklistedOutpointMap,
|
||||
selectFilteredOutpointMap,
|
||||
selectShowMatureContent,
|
||||
(byClaimId, byUri, claimsById, myClaims, blockedChannels, blacklistedMap, filteredMap, showMatureContent) => {
|
||||
const claimId = byUri[uri];
|
||||
const comments = byClaimId && byClaimId[claimId];
|
||||
|
||||
(
|
||||
claimsById,
|
||||
myClaims,
|
||||
mutedChannels,
|
||||
personalBlockList,
|
||||
adminBlockList,
|
||||
moderatorBlockList,
|
||||
blacklistedMap,
|
||||
filteredMap,
|
||||
showMatureContent
|
||||
) => {
|
||||
return comments
|
||||
? comments.filter((comment) => {
|
||||
if (!comment) {
|
||||
|
@ -247,135 +311,20 @@ export const makeSelectCommentsForUri = (uri: string) =>
|
|||
}
|
||||
}
|
||||
|
||||
return !blockedChannels.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)
|
||||
);
|
||||
})
|
||||
: [];
|
||||
}
|
||||
);
|
||||
|
||||
export const makeSelectTopLevelCommentsForUri = (uri: string) =>
|
||||
createSelector(
|
||||
selectTopLevelCommentsByClaimId,
|
||||
selectCommentsByUri,
|
||||
selectClaimsById,
|
||||
selectMyActiveClaims,
|
||||
selectMutedChannels,
|
||||
selectBlacklistedOutpointMap,
|
||||
selectFilteredOutpointMap,
|
||||
selectShowMatureContent,
|
||||
(byClaimId, byUri, claimsById, myClaims, blockedChannels, blacklistedMap, filteredMap, showMatureContent) => {
|
||||
const claimId = byUri[uri];
|
||||
const comments = byClaimId && byClaimId[claimId];
|
||||
|
||||
return comments
|
||||
? comments.filter((comment) => {
|
||||
if (!comment) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const channelClaim = claimsById[comment.channel_id];
|
||||
|
||||
// Return comment if `channelClaim` doesn't exist so the component knows to resolve the author
|
||||
if (channelClaim) {
|
||||
if (myClaims && myClaims.size > 0) {
|
||||
const claimIsMine = channelClaim.is_my_output || myClaims.has(channelClaim.claim_id);
|
||||
if (claimIsMine) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const outpoint = `${channelClaim.txid}:${channelClaim.nout}`;
|
||||
if (blacklistedMap[outpoint] || filteredMap[outpoint]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!showMatureContent) {
|
||||
const claimIsMature = isClaimNsfw(channelClaim);
|
||||
if (claimIsMature) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !blockedChannels.includes(comment.channel_url);
|
||||
})
|
||||
: [];
|
||||
}
|
||||
);
|
||||
|
||||
export const makeSelectTopLevelTotalCommentsForUri = (uri: string) =>
|
||||
createSelector(selectState, selectCommentsByUri, (state, byUri) => {
|
||||
const claimId = byUri[uri];
|
||||
return state.topLevelTotalCommentsById[claimId] || 0;
|
||||
});
|
||||
|
||||
export const makeSelectTopLevelTotalPagesForUri = (uri: string) =>
|
||||
createSelector(selectState, selectCommentsByUri, (state, byUri) => {
|
||||
const claimId = byUri[uri];
|
||||
return state.topLevelTotalPagesById[claimId] || 0;
|
||||
});
|
||||
|
||||
export const makeSelectRepliesForParentId = (id: string) =>
|
||||
createSelector(
|
||||
selectState, // no selectRepliesByParentId
|
||||
selectCommentsById,
|
||||
selectClaimsById,
|
||||
selectMyActiveClaims,
|
||||
selectMutedChannels,
|
||||
selectBlacklistedOutpointMap,
|
||||
selectFilteredOutpointMap,
|
||||
selectShowMatureContent,
|
||||
(state, commentsById, claimsById, myClaims, blockedChannels, blacklistedMap, filteredMap, showMatureContent) => {
|
||||
// const claimId = byUri[uri]; // just parentId (id)
|
||||
const replyIdsByParentId = state.repliesByParentId;
|
||||
const replyIdsForParent = replyIdsByParentId[id] || [];
|
||||
if (!replyIdsForParent.length) return null;
|
||||
|
||||
const comments = [];
|
||||
replyIdsForParent.forEach((cid) => {
|
||||
comments.push(commentsById[cid]);
|
||||
});
|
||||
// const comments = byParentId && byParentId[id];
|
||||
|
||||
return comments
|
||||
? comments.filter((comment) => {
|
||||
if (!comment) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const channelClaim = claimsById[comment.channel_id];
|
||||
|
||||
// Return comment if `channelClaim` doesn't exist so the component knows to resolve the author
|
||||
if (channelClaim) {
|
||||
if (myClaims && myClaims.size > 0) {
|
||||
const claimIsMine = channelClaim.is_my_output || myClaims.has(channelClaim.claim_id);
|
||||
if (claimIsMine) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const outpoint = `${channelClaim.txid}:${channelClaim.nout}`;
|
||||
if (blacklistedMap[outpoint] || filteredMap[outpoint]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!showMatureContent) {
|
||||
const claimIsMature = isClaimNsfw(channelClaim);
|
||||
if (claimIsMature) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !blockedChannels.includes(comment.channel_url);
|
||||
})
|
||||
: [];
|
||||
}
|
||||
);
|
||||
|
||||
export const makeSelectTotalRepliesForParentId = (parentId: string) =>
|
||||
export const makeSelectTotalReplyPagesForParentId = (parentId: string) =>
|
||||
createSelector(selectState, (state) => {
|
||||
return state.totalRepliesByParentId[parentId] || 0;
|
||||
return state.repliesTotalPagesByParentId[parentId] || 0;
|
||||
});
|
||||
|
||||
export const makeSelectTotalCommentsCountForUri = (uri: string) =>
|
||||
|
|
Loading…
Reference in a new issue