Batch-resolve channels on doCommentList fetch
This commit is contained in:
parent
7c304702d6
commit
96e7fda26a
7 changed files with 79 additions and 164 deletions
2
flow-typed/Comment.js
vendored
2
flow-typed/Comment.js
vendored
|
@ -148,7 +148,7 @@ declare type CommentListParams = {
|
||||||
channel_name?: string, // signing channel name of claim (enables 'commentsEnabled' check)
|
channel_name?: string, // signing channel name of claim (enables 'commentsEnabled' check)
|
||||||
channel_id?: string, // signing channel claim id of claim (enables 'commentsEnabled' check)
|
channel_id?: string, // signing channel claim id of claim (enables 'commentsEnabled' check)
|
||||||
author_claim_id?: string, // filters comments to just this author
|
author_claim_id?: string, // filters comments to just this author
|
||||||
parent_id?: string, // filters comments to those under this thread
|
parent_id?: ?string, // filters comments to those under this thread
|
||||||
top_level?: boolean, // filters to only top level comments
|
top_level?: boolean, // filters to only top level comments
|
||||||
hidden?: boolean, // if true, will show hidden comments as well
|
hidden?: boolean, // if true, will show hidden comments as well
|
||||||
sort_by?: number, // @see: ui/constants/comments.js::SORT_BY
|
sort_by?: number, // @see: ui/constants/comments.js::SORT_BY
|
||||||
|
|
|
@ -1,11 +1,5 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doResolveUris } from 'redux/actions/claims';
|
import { selectClaimForUri, selectClaimIsMine, selectFetchingMyChannels } from 'redux/selectors/claims';
|
||||||
import {
|
|
||||||
selectClaimForUri,
|
|
||||||
makeSelectClaimForUri,
|
|
||||||
selectClaimIsMine,
|
|
||||||
selectFetchingMyChannels,
|
|
||||||
} from 'redux/selectors/claims';
|
|
||||||
import {
|
import {
|
||||||
selectTopLevelCommentsForUri,
|
selectTopLevelCommentsForUri,
|
||||||
makeSelectTopLevelTotalPagesForUri,
|
makeSelectTopLevelTotalPagesForUri,
|
||||||
|
@ -28,25 +22,16 @@ const select = (state, props) => {
|
||||||
const { uri } = props;
|
const { uri } = props;
|
||||||
|
|
||||||
const claim = selectClaimForUri(state, uri);
|
const claim = selectClaimForUri(state, uri);
|
||||||
const channelId = getChannelIdFromClaim(claim);
|
|
||||||
|
|
||||||
const activeChannelClaim = selectActiveChannelClaim(state);
|
const activeChannelClaim = selectActiveChannelClaim(state);
|
||||||
const topLevelComments = selectTopLevelCommentsForUri(state, uri);
|
|
||||||
|
|
||||||
const resolvedComments =
|
|
||||||
topLevelComments && topLevelComments.length > 0
|
|
||||||
? topLevelComments.filter(({ channel_url }) => makeSelectClaimForUri(channel_url)(state) !== undefined)
|
|
||||||
: [];
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
topLevelComments,
|
topLevelComments: selectTopLevelCommentsForUri(state, uri),
|
||||||
resolvedComments,
|
|
||||||
allCommentIds: selectCommentIdsForUri(state, uri),
|
allCommentIds: selectCommentIdsForUri(state, uri),
|
||||||
pinnedComments: selectPinnedCommentsForUri(state, uri),
|
pinnedComments: selectPinnedCommentsForUri(state, uri),
|
||||||
topLevelTotalPages: makeSelectTopLevelTotalPagesForUri(uri)(state),
|
topLevelTotalPages: makeSelectTopLevelTotalPagesForUri(uri)(state),
|
||||||
totalComments: makeSelectTotalCommentsCountForUri(uri)(state),
|
totalComments: makeSelectTotalCommentsCountForUri(uri)(state),
|
||||||
claimId: claim && claim.claim_id,
|
claimId: claim && claim.claim_id,
|
||||||
channelId,
|
channelId: getChannelIdFromClaim(claim),
|
||||||
claimIsMine: selectClaimIsMine(state, claim),
|
claimIsMine: selectClaimIsMine(state, claim),
|
||||||
isFetchingComments: selectIsFetchingComments(state),
|
isFetchingComments: selectIsFetchingComments(state),
|
||||||
isFetchingCommentsById: selectIsFetchingCommentsById(state),
|
isFetchingCommentsById: selectIsFetchingCommentsById(state),
|
||||||
|
@ -64,7 +49,6 @@ const perform = {
|
||||||
fetchComment: doCommentById,
|
fetchComment: doCommentById,
|
||||||
fetchReacts: doCommentReactList,
|
fetchReacts: doCommentReactList,
|
||||||
resetComments: doCommentReset,
|
resetComments: doCommentReset,
|
||||||
doResolveUris,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(select, perform)(CommentsList);
|
export default connect(select, perform)(CommentsList);
|
||||||
|
|
|
@ -30,7 +30,6 @@ type Props = {
|
||||||
allCommentIds: any,
|
allCommentIds: any,
|
||||||
pinnedComments: Array<Comment>,
|
pinnedComments: Array<Comment>,
|
||||||
topLevelComments: Array<Comment>,
|
topLevelComments: Array<Comment>,
|
||||||
resolvedComments: Array<Comment>,
|
|
||||||
topLevelTotalPages: number,
|
topLevelTotalPages: number,
|
||||||
uri: string,
|
uri: string,
|
||||||
claimId?: string,
|
claimId?: string,
|
||||||
|
@ -47,11 +46,10 @@ type Props = {
|
||||||
activeChannelId: ?string,
|
activeChannelId: ?string,
|
||||||
settingsByChannelId: { [channelId: string]: PerChannelSettings },
|
settingsByChannelId: { [channelId: string]: PerChannelSettings },
|
||||||
commentsAreExpanded?: boolean,
|
commentsAreExpanded?: boolean,
|
||||||
fetchTopLevelComments: (uri: string, parentId: string, page: number, pageSize: number, sortBy: number) => void,
|
fetchTopLevelComments: (uri: string, parentId: ?string, page: number, pageSize: number, sortBy: number) => void,
|
||||||
fetchComment: (commentId: string) => void,
|
fetchComment: (commentId: string) => void,
|
||||||
fetchReacts: (commentIds: Array<string>) => Promise<any>,
|
fetchReacts: (commentIds: Array<string>) => Promise<any>,
|
||||||
resetComments: (claimId: string) => void,
|
resetComments: (claimId: string) => void,
|
||||||
doResolveUris: (uris: Array<string>, returnCachedClaims: boolean) => void,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function CommentList(props: Props) {
|
export default function CommentList(props: Props) {
|
||||||
|
@ -60,7 +58,6 @@ export default function CommentList(props: Props) {
|
||||||
uri,
|
uri,
|
||||||
pinnedComments,
|
pinnedComments,
|
||||||
topLevelComments,
|
topLevelComments,
|
||||||
resolvedComments,
|
|
||||||
topLevelTotalPages,
|
topLevelTotalPages,
|
||||||
claimId,
|
claimId,
|
||||||
channelId,
|
channelId,
|
||||||
|
@ -79,7 +76,6 @@ export default function CommentList(props: Props) {
|
||||||
fetchComment,
|
fetchComment,
|
||||||
fetchReacts,
|
fetchReacts,
|
||||||
resetComments,
|
resetComments,
|
||||||
doResolveUris,
|
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
|
@ -89,7 +85,6 @@ export default function CommentList(props: Props) {
|
||||||
const DEFAULT_SORT = ENABLE_COMMENT_REACTIONS ? SORT_BY.POPULARITY : SORT_BY.NEWEST;
|
const DEFAULT_SORT = ENABLE_COMMENT_REACTIONS ? SORT_BY.POPULARITY : SORT_BY.NEWEST;
|
||||||
const [sort, setSort] = usePersistedState('comment-sort-by', DEFAULT_SORT);
|
const [sort, setSort] = usePersistedState('comment-sort-by', DEFAULT_SORT);
|
||||||
const [page, setPage] = React.useState(0);
|
const [page, setPage] = React.useState(0);
|
||||||
const [commentsToDisplay, setCommentsToDisplay] = React.useState(topLevelComments);
|
|
||||||
const [didInitialPageFetch, setInitialPageFetch] = React.useState(false);
|
const [didInitialPageFetch, setInitialPageFetch] = React.useState(false);
|
||||||
const hasDefaultExpansion = commentsAreExpanded || !isMediumScreen || isMobile;
|
const hasDefaultExpansion = commentsAreExpanded || !isMediumScreen || isMobile;
|
||||||
const [expandedComments, setExpandedComments] = React.useState(hasDefaultExpansion);
|
const [expandedComments, setExpandedComments] = React.useState(hasDefaultExpansion);
|
||||||
|
@ -97,9 +92,6 @@ export default function CommentList(props: Props) {
|
||||||
const totalFetchedComments = allCommentIds ? allCommentIds.length : 0;
|
const totalFetchedComments = allCommentIds ? allCommentIds.length : 0;
|
||||||
const channelSettings = channelId ? settingsByChannelId[channelId] : undefined;
|
const channelSettings = channelId ? settingsByChannelId[channelId] : undefined;
|
||||||
const moreBelow = page < topLevelTotalPages;
|
const moreBelow = page < topLevelTotalPages;
|
||||||
const isResolvingComments = topLevelComments && resolvedComments.length !== topLevelComments.length;
|
|
||||||
const alreadyResolved = !isResolvingComments && resolvedComments.length !== 0;
|
|
||||||
const canDisplayComments = commentsToDisplay && commentsToDisplay.length === topLevelComments.length;
|
|
||||||
const title = getCommentsListTitle(totalComments);
|
const title = getCommentsListTitle(totalComments);
|
||||||
|
|
||||||
// Display comments immediately if not fetching reactions
|
// Display comments immediately if not fetching reactions
|
||||||
|
@ -123,8 +115,7 @@ export default function CommentList(props: Props) {
|
||||||
}
|
}
|
||||||
setPage(1);
|
setPage(1);
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
}, [page, claimId, resetComments]);
|
||||||
}, [page, uri, resetComments]); // 'claim' is derived from 'uri'
|
|
||||||
|
|
||||||
// Fetch top-level comments
|
// Fetch top-level comments
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -133,7 +124,7 @@ export default function CommentList(props: Props) {
|
||||||
fetchComment(linkedCommentId);
|
fetchComment(linkedCommentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchTopLevelComments(uri, '', page, COMMENT_PAGE_SIZE_TOP_LEVEL, sort);
|
fetchTopLevelComments(uri, undefined, page, COMMENT_PAGE_SIZE_TOP_LEVEL, sort);
|
||||||
}
|
}
|
||||||
}, [fetchComment, fetchTopLevelComments, linkedCommentId, page, sort, uri]);
|
}, [fetchComment, fetchTopLevelComments, linkedCommentId, page, sort, uri]);
|
||||||
|
|
||||||
|
@ -182,6 +173,8 @@ export default function CommentList(props: Props) {
|
||||||
|
|
||||||
// Infinite scroll
|
// Infinite scroll
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (topLevelComments.length === 0) return;
|
||||||
|
|
||||||
function shouldFetchNextPage(page, topLevelTotalPages, yPrefetchPx = 1000) {
|
function shouldFetchNextPage(page, topLevelTotalPages, yPrefetchPx = 1000) {
|
||||||
if (!spinnerRef || !spinnerRef.current) return false;
|
if (!spinnerRef || !spinnerRef.current) return false;
|
||||||
|
|
||||||
|
@ -216,7 +209,7 @@ export default function CommentList(props: Props) {
|
||||||
setInitialPageFetch(true);
|
setInitialPageFetch(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasDefaultExpansion && !isFetchingComments && canDisplayComments && readyToDisplayComments && moreBelow) {
|
if (hasDefaultExpansion && !isFetchingComments && readyToDisplayComments && moreBelow) {
|
||||||
const commentsInDrawer = Boolean(document.querySelector('.MuiDrawer-root .card--enable-overflow'));
|
const commentsInDrawer = Boolean(document.querySelector('.MuiDrawer-root .card--enable-overflow'));
|
||||||
const scrollingElement = commentsInDrawer ? document.querySelector('.card--enable-overflow') : window;
|
const scrollingElement = commentsInDrawer ? document.querySelector('.card--enable-overflow') : window;
|
||||||
|
|
||||||
|
@ -227,7 +220,7 @@ export default function CommentList(props: Props) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
canDisplayComments,
|
topLevelComments,
|
||||||
hasDefaultExpansion,
|
hasDefaultExpansion,
|
||||||
didInitialPageFetch,
|
didInitialPageFetch,
|
||||||
isFetchingComments,
|
isFetchingComments,
|
||||||
|
@ -238,22 +231,6 @@ export default function CommentList(props: Props) {
|
||||||
topLevelTotalPages,
|
topLevelTotalPages,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Wait to only display topLevelComments after resolved or else
|
|
||||||
// other components will try to resolve again, like channelThumbnail
|
|
||||||
useEffect(() => {
|
|
||||||
if (!isResolvingComments) setCommentsToDisplay(topLevelComments);
|
|
||||||
}, [isResolvingComments, topLevelComments]);
|
|
||||||
|
|
||||||
// Batch resolve comment channel urls
|
|
||||||
useEffect(() => {
|
|
||||||
if (!topLevelComments || alreadyResolved) return;
|
|
||||||
|
|
||||||
const urisToResolve = [];
|
|
||||||
topLevelComments.map(({ channel_url }) => channel_url !== undefined && urisToResolve.push(channel_url));
|
|
||||||
|
|
||||||
if (urisToResolve.length > 0) doResolveUris(urisToResolve, true);
|
|
||||||
}, [alreadyResolved, doResolveUris, topLevelComments]);
|
|
||||||
|
|
||||||
const commentProps = { isTopLevel: true, threadDepth: 3, uri, claimIsMine, linkedCommentId };
|
const commentProps = { isTopLevel: true, threadDepth: 3, uri, claimIsMine, linkedCommentId };
|
||||||
const actionButtonsProps = { totalComments, sort, changeSort, setPage };
|
const actionButtonsProps = { totalComments, sort, changeSort, setPage };
|
||||||
|
|
||||||
|
@ -282,7 +259,7 @@ export default function CommentList(props: Props) {
|
||||||
<>
|
<>
|
||||||
{pinnedComments && <CommentElements comments={pinnedComments} {...commentProps} />}
|
{pinnedComments && <CommentElements comments={pinnedComments} {...commentProps} />}
|
||||||
|
|
||||||
{commentsToDisplay && <CommentElements comments={commentsToDisplay} {...commentProps} />}
|
<CommentElements comments={topLevelComments} {...commentProps} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -308,7 +285,7 @@ export default function CommentList(props: Props) {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{(isFetchingComments || (hasDefaultExpansion && moreBelow) || !canDisplayComments) && (
|
{(isFetchingComments || (hasDefaultExpansion && moreBelow)) && (
|
||||||
<div className="main--empty" ref={spinnerRef}>
|
<div className="main--empty" ref={spinnerRef}>
|
||||||
<Spinner type="small" />
|
<Spinner type="small" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,26 +1,16 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doResolveUris } from 'redux/actions/claims';
|
import { selectClaimIsMineForUri } from 'redux/selectors/claims';
|
||||||
import { selectClaimIsMineForUri, makeSelectClaimForUri } from 'redux/selectors/claims';
|
|
||||||
import { selectIsFetchingCommentsByParentId, selectRepliesForParentId } from 'redux/selectors/comments';
|
import { selectIsFetchingCommentsByParentId, selectRepliesForParentId } from 'redux/selectors/comments';
|
||||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
|
||||||
import CommentsReplies from './view';
|
import CommentsReplies from './view';
|
||||||
|
|
||||||
const select = (state, props) => {
|
const select = (state, props) => {
|
||||||
const fetchedReplies = selectRepliesForParentId(state, props.parentId);
|
const { uri, parentId } = props;
|
||||||
const resolvedReplies =
|
|
||||||
fetchedReplies && fetchedReplies.length > 0
|
|
||||||
? fetchedReplies.filter(({ channel_url }) => makeSelectClaimForUri(channel_url)(state) !== undefined)
|
|
||||||
: [];
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
fetchedReplies,
|
fetchedReplies: selectRepliesForParentId(state, parentId),
|
||||||
resolvedReplies,
|
claimIsMine: selectClaimIsMineForUri(state, uri),
|
||||||
claimIsMine: selectClaimIsMineForUri(state, props.uri),
|
isFetching: selectIsFetchingCommentsByParentId(state, parentId),
|
||||||
userCanComment: IS_WEB ? Boolean(selectUserVerifiedEmail(state)) : true,
|
|
||||||
isFetchingByParentId: selectIsFetchingCommentsByParentId(state),
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const perform = (dispatch) => ({ doResolveUris: (uris) => dispatch(doResolveUris(uris, true)) });
|
export default connect(select)(CommentsReplies);
|
||||||
|
|
||||||
export default connect(select, perform)(CommentsReplies);
|
|
||||||
|
|
|
@ -6,61 +6,34 @@ import React from 'react';
|
||||||
import Spinner from 'component/spinner';
|
import Spinner from 'component/spinner';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
fetchedReplies: Array<Comment>,
|
|
||||||
resolvedReplies: Array<Comment>,
|
|
||||||
uri: string,
|
uri: string,
|
||||||
parentId: string,
|
|
||||||
claimIsMine: boolean,
|
|
||||||
linkedCommentId?: string,
|
linkedCommentId?: string,
|
||||||
userCanComment: boolean,
|
|
||||||
threadDepth: number,
|
threadDepth: number,
|
||||||
numDirectReplies: number, // Total replies for parentId as reported by 'comment[replies]'. Includes blocked items.
|
numDirectReplies: number, // Total replies for parentId as reported by 'comment[replies]'. Includes blocked items.
|
||||||
isFetchingByParentId: { [string]: boolean },
|
|
||||||
hasMore: boolean,
|
hasMore: boolean,
|
||||||
supportDisabled: boolean,
|
supportDisabled: boolean,
|
||||||
doResolveUris: (Array<string>) => void,
|
|
||||||
onShowMore?: () => void,
|
onShowMore?: () => void,
|
||||||
|
// redux
|
||||||
|
fetchedReplies: Array<Comment>,
|
||||||
|
claimIsMine: boolean,
|
||||||
|
isFetching: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
function CommentsReplies(props: Props) {
|
export default function CommentsReplies(props: Props) {
|
||||||
const {
|
const {
|
||||||
uri,
|
uri,
|
||||||
parentId,
|
|
||||||
fetchedReplies,
|
fetchedReplies,
|
||||||
resolvedReplies,
|
|
||||||
claimIsMine,
|
claimIsMine,
|
||||||
linkedCommentId,
|
linkedCommentId,
|
||||||
userCanComment,
|
|
||||||
threadDepth,
|
threadDepth,
|
||||||
numDirectReplies,
|
numDirectReplies,
|
||||||
isFetchingByParentId,
|
isFetching,
|
||||||
hasMore,
|
hasMore,
|
||||||
supportDisabled,
|
supportDisabled,
|
||||||
doResolveUris,
|
|
||||||
onShowMore,
|
onShowMore,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const [isExpanded, setExpanded] = React.useState(true);
|
const [isExpanded, setExpanded] = React.useState(true);
|
||||||
const [commentsToDisplay, setCommentsToDisplay] = React.useState(fetchedReplies);
|
|
||||||
const isResolvingReplies = fetchedReplies && resolvedReplies.length !== fetchedReplies.length;
|
|
||||||
const alreadyResolved = !isResolvingReplies && resolvedReplies.length !== 0;
|
|
||||||
const canDisplayComments = commentsToDisplay && commentsToDisplay.length === fetchedReplies.length;
|
|
||||||
|
|
||||||
// Batch resolve comment channel urls
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (!fetchedReplies || alreadyResolved) return;
|
|
||||||
|
|
||||||
const urisToResolve = [];
|
|
||||||
fetchedReplies.map(({ channel_url }) => channel_url !== undefined && urisToResolve.push(channel_url));
|
|
||||||
|
|
||||||
if (urisToResolve.length > 0) doResolveUris(urisToResolve);
|
|
||||||
}, [alreadyResolved, doResolveUris, fetchedReplies]);
|
|
||||||
|
|
||||||
// Wait to only display topLevelComments after resolved or else
|
|
||||||
// other components will try to resolve again, like channelThumbnail
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (!isResolvingReplies) setCommentsToDisplay(fetchedReplies);
|
|
||||||
}, [isResolvingReplies, fetchedReplies]);
|
|
||||||
|
|
||||||
return !numDirectReplies ? null : (
|
return !numDirectReplies ? null : (
|
||||||
<div className="comment__replies-container">
|
<div className="comment__replies-container">
|
||||||
|
@ -78,24 +51,21 @@ function CommentsReplies(props: Props) {
|
||||||
<Button className="comment__threadline" aria-label="Hide Replies" onClick={() => setExpanded(false)} />
|
<Button className="comment__threadline" aria-label="Hide Replies" onClick={() => setExpanded(false)} />
|
||||||
|
|
||||||
<ul className="comments--replies">
|
<ul className="comments--replies">
|
||||||
{!isResolvingReplies &&
|
{fetchedReplies.map((comment) => (
|
||||||
commentsToDisplay &&
|
<Comment
|
||||||
commentsToDisplay.length > 0 &&
|
key={comment.comment_id}
|
||||||
commentsToDisplay.map((comment) => (
|
threadDepth={threadDepth}
|
||||||
<Comment
|
uri={uri}
|
||||||
key={comment.comment_id}
|
comment={comment}
|
||||||
threadDepth={threadDepth}
|
claimIsMine={claimIsMine}
|
||||||
uri={uri}
|
linkedCommentId={linkedCommentId}
|
||||||
comment={comment}
|
supportDisabled={supportDisabled}
|
||||||
claimIsMine={claimIsMine}
|
/>
|
||||||
linkedCommentId={linkedCommentId}
|
))}
|
||||||
commentingEnabled={userCanComment}
|
|
||||||
supportDisabled={supportDisabled}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isExpanded && fetchedReplies && hasMore && (
|
{isExpanded && fetchedReplies && hasMore && (
|
||||||
<div className="comment__actions--nested">
|
<div className="comment__actions--nested">
|
||||||
<Button
|
<Button
|
||||||
|
@ -106,7 +76,8 @@ function CommentsReplies(props: Props) {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{(isFetchingByParentId[parentId] || isResolvingReplies || !canDisplayComments) && (
|
|
||||||
|
{isFetching && (
|
||||||
<div className="comment__replies-container">
|
<div className="comment__replies-container">
|
||||||
<div className="comment__actions--nested">
|
<div className="comment__actions--nested">
|
||||||
<Spinner type="small" />
|
<Spinner type="small" />
|
||||||
|
@ -116,5 +87,3 @@ function CommentsReplies(props: Props) {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CommentsReplies;
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ import {
|
||||||
import { makeSelectNotificationForCommentId } from 'redux/selectors/notifications';
|
import { makeSelectNotificationForCommentId } from 'redux/selectors/notifications';
|
||||||
import { selectActiveChannelClaim } from 'redux/selectors/app';
|
import { selectActiveChannelClaim } from 'redux/selectors/app';
|
||||||
import { toHex } from 'util/hex';
|
import { toHex } from 'util/hex';
|
||||||
|
import { getChannelFromClaim } from 'util/claim';
|
||||||
import Comments from 'comments';
|
import Comments from 'comments';
|
||||||
import { selectPrefsReady } from 'redux/selectors/sync';
|
import { selectPrefsReady } from 'redux/selectors/sync';
|
||||||
import { doAlertWaitingForSync } from 'redux/actions/app';
|
import { doAlertWaitingForSync } from 'redux/actions/app';
|
||||||
|
@ -30,47 +31,41 @@ const MENTION_REGEX = /(?:^| |\n)@[^\s=&#$@%?:;/"<>%{}|^~[]*(?::[\w]+)?/gm;
|
||||||
|
|
||||||
export function doCommentList(
|
export function doCommentList(
|
||||||
uri: string,
|
uri: string,
|
||||||
parentId: string,
|
parentId: ?string,
|
||||||
page: number = 1,
|
page: number = 1,
|
||||||
pageSize: number = 99999,
|
pageSize: number = 99999,
|
||||||
sortBy: number = SORT_BY.NEWEST
|
sortBy: number = SORT_BY.NEWEST
|
||||||
) {
|
) {
|
||||||
return (dispatch: Dispatch, getState: GetState) => {
|
return (dispatch: Dispatch, getState: GetState) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const claim = selectClaimsByUri(state)[uri];
|
const claim = selectClaimForUri(state, uri);
|
||||||
const claimId = claim ? claim.claim_id : null;
|
const { claim_id: claimId } = claim || {};
|
||||||
|
|
||||||
if (!claimId) {
|
if (!claimId) {
|
||||||
dispatch({
|
return dispatch({ type: ACTIONS.COMMENT_LIST_FAILED, data: 'unable to find claim for uri' });
|
||||||
type: ACTIONS.COMMENT_LIST_FAILED,
|
|
||||||
data: 'unable to find claim for uri',
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({ type: ACTIONS.COMMENT_LIST_STARTED, data: { parentId } });
|
||||||
type: ACTIONS.COMMENT_LIST_STARTED,
|
|
||||||
data: {
|
|
||||||
parentId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Adding 'channel_id' and 'channel_name' enables "CreatorSettings > commentsEnabled".
|
// Adding 'channel_id' and 'channel_name' enables "CreatorSettings > commentsEnabled".
|
||||||
const creatorChannelClaim = claim.value_type === 'channel' ? claim : claim.signing_channel;
|
const creatorChannelClaim = getChannelFromClaim(claim);
|
||||||
|
const { claim_id: creatorClaimId, name: channelName } = creatorChannelClaim || {};
|
||||||
|
|
||||||
return Comments.comment_list({
|
return Comments.comment_list({
|
||||||
page,
|
page,
|
||||||
claim_id: claimId,
|
claim_id: claimId,
|
||||||
page_size: pageSize,
|
page_size: pageSize,
|
||||||
parent_id: parentId || undefined,
|
parent_id: parentId,
|
||||||
top_level: !parentId,
|
top_level: !parentId,
|
||||||
channel_id: creatorChannelClaim ? creatorChannelClaim.claim_id : undefined,
|
channel_id: creatorClaimId,
|
||||||
channel_name: creatorChannelClaim ? creatorChannelClaim.name : undefined,
|
channel_name: channelName,
|
||||||
sort_by: sortBy,
|
sort_by: sortBy,
|
||||||
})
|
})
|
||||||
.then((result: CommentListResponse) => {
|
.then((result: CommentListResponse) => {
|
||||||
const { items: comments, total_items, total_filtered_items, total_pages } = result;
|
const { items: comments, total_items, total_filtered_items, total_pages } = result;
|
||||||
dispatch({
|
|
||||||
|
const commentChannelUrls = comments && comments.map((comment) => comment.channel_url || '');
|
||||||
|
const dispatchData = {
|
||||||
type: ACTIONS.COMMENT_LIST_COMPLETED,
|
type: ACTIONS.COMMENT_LIST_COMPLETED,
|
||||||
data: {
|
data: {
|
||||||
comments,
|
comments,
|
||||||
|
@ -78,38 +73,36 @@ export function doCommentList(
|
||||||
totalItems: total_items,
|
totalItems: total_items,
|
||||||
totalFilteredItems: total_filtered_items,
|
totalFilteredItems: total_filtered_items,
|
||||||
totalPages: total_pages,
|
totalPages: total_pages,
|
||||||
claimId: claimId,
|
claimId,
|
||||||
creatorClaimId: creatorChannelClaim ? creatorChannelClaim.claim_id : undefined,
|
creatorClaimId,
|
||||||
uri: uri,
|
uri,
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
|
|
||||||
return result;
|
// Batch resolve comment channel urls
|
||||||
|
if (commentChannelUrls) {
|
||||||
|
return dispatch(async () => await doResolveUris(commentChannelUrls, true)).then(() => {
|
||||||
|
dispatch({ ...dispatchData });
|
||||||
|
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
dispatch({ ...dispatchData });
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
switch (error.message) {
|
const { message } = error;
|
||||||
|
|
||||||
|
switch (message) {
|
||||||
case 'comments are disabled by the creator':
|
case 'comments are disabled by the creator':
|
||||||
dispatch({
|
return dispatch({ type: ACTIONS.COMMENT_LIST_COMPLETED, data: { creatorClaimId, disabled: true } });
|
||||||
type: ACTIONS.COMMENT_LIST_COMPLETED,
|
|
||||||
data: {
|
|
||||||
creatorClaimId: creatorChannelClaim ? creatorChannelClaim.claim_id : undefined,
|
|
||||||
disabled: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FETCH_API_FAILED_TO_FETCH:
|
case FETCH_API_FAILED_TO_FETCH:
|
||||||
dispatch(
|
dispatch(doToast({ isError: true, message: __('Failed to fetch comments.') }));
|
||||||
doToast({
|
return dispatch({ type: ACTIONS.COMMENT_LIST_FAILED, data: error });
|
||||||
isError: true,
|
|
||||||
message: __('Failed to fetch comments.'),
|
|
||||||
})
|
|
||||||
);
|
|
||||||
dispatch({ type: ACTIONS.COMMENT_LIST_FAILED, data: error });
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dispatch(doToast({ isError: true, message: `${error.message}` }));
|
dispatch(doToast({ isError: true, message: `${message}` }));
|
||||||
dispatch({ type: ACTIONS.COMMENT_LIST_FAILED, data: error });
|
dispatch({ type: ACTIONS.COMMENT_LIST_FAILED, data: error });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -24,7 +24,6 @@ export const selectCommentsById = (state: State) => selectState(state).commentBy
|
||||||
export const selectCommentIdsByClaimId = (state: State) => selectState(state).byId;
|
export const selectCommentIdsByClaimId = (state: State) => selectState(state).byId;
|
||||||
export const selectIsFetchingComments = (state: State) => selectState(state).isLoading;
|
export const selectIsFetchingComments = (state: State) => selectState(state).isLoading;
|
||||||
export const selectIsFetchingCommentsById = (state: State) => selectState(state).isLoadingById;
|
export const selectIsFetchingCommentsById = (state: State) => selectState(state).isLoadingById;
|
||||||
export const selectIsFetchingCommentsByParentId = (state: State) => selectState(state).isLoadingByParentId;
|
|
||||||
export const selectIsFetchingReacts = (state: State) => selectState(state).isFetchingReacts;
|
export const selectIsFetchingReacts = (state: State) => selectState(state).isFetchingReacts;
|
||||||
|
|
||||||
export const selectMyReacts = (state: State) => state.comments.myReactsByCommentId;
|
export const selectMyReacts = (state: State) => state.comments.myReactsByCommentId;
|
||||||
|
@ -32,6 +31,9 @@ export const selectMyReactsForComment = (state: State, commentIdChannelId: strin
|
||||||
// @commentIdChannelId: Format = 'commentId:MyChannelId'
|
// @commentIdChannelId: Format = 'commentId:MyChannelId'
|
||||||
return state.comments.myReactsByCommentId && state.comments.myReactsByCommentId[commentIdChannelId];
|
return state.comments.myReactsByCommentId && state.comments.myReactsByCommentId[commentIdChannelId];
|
||||||
};
|
};
|
||||||
|
export const selectIsFetchingCommentsByParentId = (state: State, parentId: string) => {
|
||||||
|
return selectState(state).isLoadingByParentId[parentId];
|
||||||
|
};
|
||||||
|
|
||||||
export const selectOthersReacts = (state: State) => state.comments.othersReactsByCommentId;
|
export const selectOthersReacts = (state: State) => state.comments.othersReactsByCommentId;
|
||||||
export const selectOthersReactsForComment = (state: State, id: string) => {
|
export const selectOthersReactsForComment = (state: State, id: string) => {
|
||||||
|
|
Loading…
Reference in a new issue