Livestream: stop pinned comments from appearing as latest #6888
6 changed files with 101 additions and 74 deletions
|
@ -15,6 +15,7 @@ import {
|
|||
selectMyReactionsByCommentId,
|
||||
makeSelectCommentIdsForUri,
|
||||
selectSettingsByChannelId,
|
||||
makeSelectPinnedCommentsForUri,
|
||||
} from 'redux/selectors/comments';
|
||||
import { doCommentReset, doCommentList, doCommentById, doCommentReactList } from 'redux/actions/comments';
|
||||
import { selectActiveChannelClaim } from 'redux/selectors/app';
|
||||
|
@ -25,6 +26,7 @@ const select = (state, props) => {
|
|||
return {
|
||||
myChannels: selectMyChannelClaims(state),
|
||||
allCommentIds: makeSelectCommentIdsForUri(props.uri)(state),
|
||||
pinnedComments: makeSelectPinnedCommentsForUri(props.uri)(state),
|
||||
topLevelComments: makeSelectTopLevelCommentsForUri(props.uri)(state),
|
||||
topLevelTotalPages: makeSelectTopLevelTotalPagesForUri(props.uri)(state),
|
||||
totalComments: makeSelectTotalCommentsCountForUri(props.uri)(state),
|
||||
|
|
|
@ -28,6 +28,7 @@ function scaleToDevicePixelRatio(value) {
|
|||
|
||||
type Props = {
|
||||
allCommentIds: any,
|
||||
pinnedComments: Array<Comment>,
|
||||
topLevelComments: Array<Comment>,
|
||||
topLevelTotalPages: number,
|
||||
fetchTopLevelComments: (string, number, number, number) => void,
|
||||
|
@ -57,6 +58,7 @@ function CommentList(props: Props) {
|
|||
fetchReacts,
|
||||
resetComments,
|
||||
uri,
|
||||
pinnedComments,
|
||||
topLevelComments,
|
||||
topLevelTotalPages,
|
||||
claim,
|
||||
|
@ -111,6 +113,34 @@ function CommentList(props: Props) {
|
|||
}
|
||||
}
|
||||
|
||||
function getCommentElems(comments) {
|
||||
return comments.map((comment) => {
|
||||
return (
|
||||
<CommentView
|
||||
isTopLevel
|
||||
threadDepth={3}
|
||||
key={comment.comment_id}
|
||||
uri={uri}
|
||||
authorUri={comment.channel_url}
|
||||
author={comment.channel_name}
|
||||
claimId={comment.claim_id}
|
||||
commentId={comment.comment_id}
|
||||
message={comment.comment}
|
||||
timePosted={comment.timestamp * 1000}
|
||||
claimIsMine={claimIsMine}
|
||||
commentIsMine={comment.channel_id && isMyComment(comment.channel_id)}
|
||||
linkedCommentId={linkedCommentId}
|
||||
isPinned={comment.is_pinned}
|
||||
supportAmount={comment.support_amount}
|
||||
numDirectReplies={comment.replies}
|
||||
isModerator={comment.is_moderator}
|
||||
isGlobalMod={comment.is_global_mod}
|
||||
isFiat={comment.is_fiat}
|
||||
/>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Reset comments
|
||||
useEffect(() => {
|
||||
if (page === 0) {
|
||||
|
@ -223,8 +253,6 @@ function CommentList(props: Props) {
|
|||
topLevelTotalPages,
|
||||
]);
|
||||
|
||||
const displayedComments = readyToDisplayComments ? topLevelComments : [];
|
||||
|
||||
return (
|
||||
<Card
|
||||
title={
|
||||
|
@ -295,33 +323,8 @@ function CommentList(props: Props) {
|
|||
})}
|
||||
ref={commentRef}
|
||||
>
|
||||
{topLevelComments &&
|
||||
displayedComments &&
|
||||
displayedComments.map((comment) => {
|
||||
return (
|
||||
<CommentView
|
||||
isTopLevel
|
||||
threadDepth={3}
|
||||
key={comment.comment_id}
|
||||
uri={uri}
|
||||
authorUri={comment.channel_url}
|
||||
author={comment.channel_name}
|
||||
claimId={comment.claim_id}
|
||||
commentId={comment.comment_id}
|
||||
message={comment.comment}
|
||||
timePosted={comment.timestamp * 1000}
|
||||
claimIsMine={claimIsMine}
|
||||
commentIsMine={comment.channel_id && isMyComment(comment.channel_id)}
|
||||
linkedCommentId={linkedCommentId}
|
||||
isPinned={comment.is_pinned}
|
||||
supportAmount={comment.support_amount}
|
||||
numDirectReplies={comment.replies}
|
||||
isModerator={comment.is_moderator}
|
||||
isGlobalMod={comment.is_global_mod}
|
||||
isFiat={comment.is_fiat}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{readyToDisplayComments && pinnedComments && getCommentElems(pinnedComments)}
|
||||
{readyToDisplayComments && topLevelComments && getCommentElems(topLevelComments)}
|
||||
</ul>
|
||||
|
||||
{isMobile && (
|
||||
|
|
|
@ -3,22 +3,22 @@ import { makeSelectClaimForUri, selectMyChannelClaims } from 'lbry-redux';
|
|||
import { doCommentSocketConnect, doCommentSocketDisconnect } from 'redux/actions/websocket';
|
||||
import { doCommentList, doSuperChatList } from 'redux/actions/comments';
|
||||
import {
|
||||
selectPinnedCommentsById,
|
||||
makeSelectTopLevelCommentsForUri,
|
||||
selectIsFetchingComments,
|
||||
makeSelectSuperChatsForUri,
|
||||
makeSelectSuperChatTotalAmountForUri,
|
||||
makeSelectPinnedCommentsForUri,
|
||||
} from 'redux/selectors/comments';
|
||||
import LivestreamComments from './view';
|
||||
|
||||
const select = (state, props) => ({
|
||||
claim: makeSelectClaimForUri(props.uri)(state),
|
||||
comments: makeSelectTopLevelCommentsForUri(props.uri)(state).slice(0, 75),
|
||||
pinnedComments: makeSelectPinnedCommentsForUri(props.uri)(state),
|
||||
fetchingComments: selectIsFetchingComments(state),
|
||||
superChats: makeSelectSuperChatsForUri(props.uri)(state),
|
||||
superChatsTotalAmount: makeSelectSuperChatTotalAmountForUri(props.uri)(state),
|
||||
myChannels: selectMyChannelClaims(state),
|
||||
pinnedCommentsById: selectPinnedCommentsById(state),
|
||||
});
|
||||
|
||||
export default connect(select, {
|
||||
|
|
|
@ -19,11 +19,11 @@ type Props = {
|
|||
doCommentSocketDisconnect: (string) => void,
|
||||
doCommentList: (string, string, number, number) => void,
|
||||
comments: Array<Comment>,
|
||||
pinnedComments: Array<Comment>,
|
||||
fetchingComments: boolean,
|
||||
doSuperChatList: (string) => void,
|
||||
superChats: Array<Comment>,
|
||||
myChannels: ?Array<ChannelClaim>,
|
||||
pinnedCommentsById: { [claimId: string]: Array<string> },
|
||||
};
|
||||
|
||||
const VIEW_MODE_CHAT = 'view_chat';
|
||||
|
@ -39,12 +39,12 @@ export default function LivestreamComments(props: Props) {
|
|||
doCommentSocketConnect,
|
||||
doCommentSocketDisconnect,
|
||||
comments: commentsByChronologicalOrder,
|
||||
pinnedComments,
|
||||
doCommentList,
|
||||
fetchingComments,
|
||||
doSuperChatList,
|
||||
myChannels,
|
||||
superChats: superChatsByTipAmount,
|
||||
pinnedCommentsById,
|
||||
} = props;
|
||||
|
||||
let superChatsFiatAmount, superChatsTotalAmount;
|
||||
|
@ -60,11 +60,7 @@ export default function LivestreamComments(props: Props) {
|
|||
const discussionElement = document.querySelector('.livestream__comments');
|
||||
const commentElement = document.querySelector('.livestream-comment');
|
||||
|
||||
let pinnedComment;
|
||||
const pinnedCommentIds = (claimId && pinnedCommentsById[claimId]) || [];
|
||||
if (pinnedCommentIds.length > 0) {
|
||||
pinnedComment = commentsByChronologicalOrder.find((c) => c.comment_id === pinnedCommentIds[0]);
|
||||
}
|
||||
const pinnedComment = pinnedComments.length > 0 ? pinnedComments[0] : null;
|
||||
|
||||
React.useEffect(() => {
|
||||
if (claimId) {
|
||||
|
|
|
@ -301,9 +301,10 @@ export default handleActions(
|
|||
for (let i = 0; i < comments.length; ++i) {
|
||||
const comment = comments[i];
|
||||
commonUpdateAction(comment, commentById, commentIds, i);
|
||||
pushToArrayInObject(topLevelCommentsById, claimId, comment.comment_id);
|
||||
if (comment.is_pinned) {
|
||||
pushToArrayInObject(pinnedCommentsById, claimId, comment.comment_id);
|
||||
} else {
|
||||
pushToArrayInObject(topLevelCommentsById, claimId, comment.comment_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -615,45 +616,50 @@ export default handleActions(
|
|||
const topLevelCommentsById = Object.assign({}, state.topLevelCommentsById);
|
||||
const pinnedCommentsById = Object.assign({}, state.pinnedCommentsById);
|
||||
|
||||
if (pinnedComment && topLevelCommentsById[claimId]) {
|
||||
const index = topLevelCommentsById[claimId].indexOf(pinnedComment.comment_id);
|
||||
if (index > -1) {
|
||||
topLevelCommentsById[claimId].splice(index, 1);
|
||||
|
||||
if (pinnedCommentsById[claimId]) {
|
||||
// Remove here so that the 'unshift' below will be a unique entry.
|
||||
pinnedCommentsById[claimId] = pinnedCommentsById[claimId].filter((x) => x !== pinnedComment.comment_id);
|
||||
} else {
|
||||
pinnedCommentsById[claimId] = [];
|
||||
if (pinnedComment) {
|
||||
if (topLevelCommentsById[claimId]) {
|
||||
const index = topLevelCommentsById[claimId].indexOf(pinnedComment.comment_id);
|
||||
if (index > -1) {
|
||||
topLevelCommentsById[claimId].splice(index, 1);
|
||||
}
|
||||
} else {
|
||||
topLevelCommentsById[claimId] = [];
|
||||
}
|
||||
|
||||
if (unpin) {
|
||||
// Without the sort score, I have no idea where to put it. Just
|
||||
// dump it at the bottom. Users can refresh if they want it back to
|
||||
// the correct sorted position.
|
||||
topLevelCommentsById[claimId].push(pinnedComment.comment_id);
|
||||
} else {
|
||||
topLevelCommentsById[claimId].unshift(pinnedComment.comment_id);
|
||||
pinnedCommentsById[claimId].unshift(pinnedComment.comment_id);
|
||||
if (pinnedCommentsById[claimId]) {
|
||||
const index = pinnedCommentsById[claimId].indexOf(pinnedComment.comment_id);
|
||||
if (index > -1) {
|
||||
pinnedCommentsById[claimId].splice(index, 1);
|
||||
}
|
||||
} else {
|
||||
pinnedCommentsById[claimId] = [];
|
||||
}
|
||||
|
||||
if (commentById[pinnedComment.comment_id]) {
|
||||
// Commentron's `comment.Pin` response places the creator's credentials
|
||||
// in the 'channel_*' fields, which doesn't make sense. Maybe it is to
|
||||
// show who signed/pinned it, but even if so, it shouldn't overload
|
||||
// these variables which are already used by existing comment data structure.
|
||||
// Ensure we don't override the existing/correct values, but fallback
|
||||
// to whatever was given.
|
||||
const { channel_id, channel_name, channel_url } = commentById[pinnedComment.comment_id];
|
||||
commentById[pinnedComment.comment_id] = {
|
||||
...pinnedComment,
|
||||
channel_id: channel_id || pinnedComment.channel_id,
|
||||
channel_name: channel_name || pinnedComment.channel_name,
|
||||
channel_url: channel_url || pinnedComment.channel_url,
|
||||
};
|
||||
} else {
|
||||
commentById[pinnedComment.comment_id] = pinnedComment;
|
||||
}
|
||||
if (unpin) {
|
||||
// Without the sort score, I have no idea where to put it. Just
|
||||
// dump it at the top. Users can refresh if they want it back to
|
||||
// the correct sorted position.
|
||||
topLevelCommentsById[claimId].unshift(pinnedComment.comment_id);
|
||||
} else {
|
||||
pinnedCommentsById[claimId].unshift(pinnedComment.comment_id);
|
||||
}
|
||||
|
||||
if (commentById[pinnedComment.comment_id]) {
|
||||
// Commentron's `comment.Pin` response places the creator's credentials
|
||||
// in the 'channel_*' fields, which doesn't make sense. Maybe it is to
|
||||
// show who signed/pinned it, but even if so, it shouldn't overload
|
||||
// these variables which are already used by existing comment data structure.
|
||||
// Ensure we don't override the existing/correct values, but fallback
|
||||
// to whatever was given.
|
||||
const { channel_id, channel_name, channel_url } = commentById[pinnedComment.comment_id];
|
||||
commentById[pinnedComment.comment_id] = {
|
||||
...pinnedComment,
|
||||
channel_id: channel_id || pinnedComment.channel_id,
|
||||
channel_name: channel_name || pinnedComment.channel_name,
|
||||
channel_url: channel_url || pinnedComment.channel_url,
|
||||
};
|
||||
} else {
|
||||
commentById[pinnedComment.comment_id] = pinnedComment;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,27 @@ export const selectIsFetchingCommentsByParentId = createSelector(selectState, (s
|
|||
export const selectIsPostingComment = createSelector(selectState, (state) => state.isCommenting);
|
||||
export const selectIsFetchingReacts = createSelector(selectState, (state) => state.isFetchingReacts);
|
||||
export const selectOthersReactsById = createSelector(selectState, (state) => state.othersReactsByCommentId);
|
||||
|
||||
export const selectPinnedCommentsById = createSelector(selectState, (state) => state.pinnedCommentsById);
|
||||
export const makeSelectPinnedCommentsForUri = (uri: string) =>
|
||||
createSelector(
|
||||
selectCommentsByUri,
|
||||
selectCommentsById,
|
||||
selectPinnedCommentsById,
|
||||
(byUri, byId, pinnedCommentsById) => {
|
||||
const claimId = byUri[uri];
|
||||
const pinnedCommentIds = pinnedCommentsById && pinnedCommentsById[claimId];
|
||||
const pinnedComments = [];
|
||||
|
||||
if (pinnedCommentIds) {
|
||||
pinnedCommentIds.forEach((commentId) => {
|
||||
pinnedComments.push(byId[commentId]);
|
||||
});
|
||||
}
|
||||
|
||||
return pinnedComments;
|
||||
}
|
||||
);
|
||||
|
||||
export const selectModerationBlockList = createSelector(selectState, (state) =>
|
||||
state.moderationBlockList ? state.moderationBlockList.reverse() : []
|
||||
|
|
Loading…
Add table
Reference in a new issue