From 74986a8b3aca960acf6d33d0976815fdceba3e3d Mon Sep 17 00:00:00 2001 From: infinite-persistence Date: Wed, 4 Aug 2021 23:01:31 +0800 Subject: [PATCH] Comments: simplify blocked replies display Previously, we decide when to display "Show More" based on the current fetched reply count vs. total replies in Commentron. It was already troublesome as `comment.List` and `comment.replies` give different values (one includes blocked content, while another does not). Now, we are further filtering the list with Commentron blocklists (personal, admin, moderator), so it is not feasible to run the logic based on reply count. ## Solution - Keep track of number of remaining pages instead and use that to determine when to display "Show More". - While it doesn't solve the "Show N replies" mismatch (YT has this problem too), it prevents the button from lingering. - In the event that all replies are blocked, just show an empty space (same as YT). I didn't like the previous version that cluttered the space with "comment(s) blocked". --- flow-typed/Comment.js | 2 +- ui/component/comment/index.js | 7 ++++++- ui/component/comment/view.jsx | 3 +++ ui/component/commentsReplies/index.js | 7 +------ ui/component/commentsReplies/view.jsx | 26 ++++---------------------- ui/redux/reducers/comments.js | 22 ++++------------------ ui/redux/selectors/comments.js | 4 ++-- 7 files changed, 21 insertions(+), 50 deletions(-) diff --git a/flow-typed/Comment.js b/flow-typed/Comment.js index 412052a39..ffda63876 100644 --- a/flow-typed/Comment.js +++ b/flow-typed/Comment.js @@ -35,7 +35,7 @@ declare type CommentsState = { byId: { [string]: Array }, // ClaimID -> list of fetched comment IDs. totalCommentsById: {}, // ClaimId -> ultimate total (including replies) in commentron. repliesByParentId: { [string]: Array }, // 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 }, // 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. diff --git a/ui/component/comment/index.js b/ui/component/comment/index.js index 26e604e64..901b8cd3b 100644 --- a/ui/component/comment/index.js +++ b/ui/component/comment/index.js @@ -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), }; }; diff --git a/ui/component/comment/view.jsx b/ui/component/comment/view.jsx index 6d3c6dc62..bc8222db7 100644 --- a/ui/component/comment/view.jsx +++ b/ui/component/comment/view.jsx @@ -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 }, @@ -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} /> )} diff --git a/ui/component/commentsReplies/index.js b/ui/component/commentsReplies/index.js index 0bb4aba85..8008d5535 100644 --- a/ui/component/commentsReplies/index.js +++ b/ui/component/commentsReplies/index.js @@ -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), diff --git a/ui/component/commentsReplies/view.jsx b/ui/component/commentsReplies/view.jsx index 6e78e7dac..42d0e451a 100644 --- a/ui/component/commentsReplies/view.jsx +++ b/ui/component/commentsReplies/view.jsx @@ -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, - 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 && ( -
  • -
    -
    - -
    -
    -
    - --- -
    -
    - {__('Comment(s) blocked.')} -
    -
    -
    -
  • - )} )} - {isExpanded && fetchedReplies && displayedComments.length < totalReplies && ( + {isExpanded && fetchedReplies && hasMore && (
    diff --git a/ui/redux/reducers/comments.js b/ui/redux/reducers/comments.js index ac344c8c7..815025698 100644 --- a/ui/redux/reducers/comments.js +++ b/ui/redux/reducers/comments.js @@ -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, }; }, diff --git a/ui/redux/selectors/comments.js b/ui/redux/selectors/comments.js index 1fe9be599..e4c21ff54 100644 --- a/ui/redux/selectors/comments.js +++ b/ui/redux/selectors/comments.js @@ -322,9 +322,9 @@ const makeSelectFilteredComments = (comments: Array) => } ); -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) =>