comment reactions
This commit is contained in:
parent
bdb3d695ee
commit
63ce107cc1
14 changed files with 252 additions and 16 deletions
12
flow-typed/Comment.js
vendored
12
flow-typed/Comment.js
vendored
|
@ -22,4 +22,16 @@ declare type CommentsState = {
|
||||||
commentById: { [string]: Comment },
|
commentById: { [string]: Comment },
|
||||||
isLoading: boolean,
|
isLoading: boolean,
|
||||||
myComments: ?Set<string>,
|
myComments: ?Set<string>,
|
||||||
|
isFetchingReacts: boolean,
|
||||||
|
myReactsByCommentId: any,
|
||||||
|
othersReactsByCommentId: any,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
declare type CommentReactParams = {
|
||||||
|
comment_ids: string,
|
||||||
|
channel_name: string,
|
||||||
|
channel_id: string,
|
||||||
|
react_type: string,
|
||||||
|
clear_types?: string,
|
||||||
|
remove?: boolean,
|
||||||
|
}
|
||||||
|
|
|
@ -136,7 +136,7 @@
|
||||||
"imagesloaded": "^4.1.4",
|
"imagesloaded": "^4.1.4",
|
||||||
"json-loader": "^0.5.4",
|
"json-loader": "^0.5.4",
|
||||||
"lbry-format": "https://github.com/lbryio/lbry-format.git",
|
"lbry-format": "https://github.com/lbryio/lbry-format.git",
|
||||||
"lbry-redux": "lbryio/lbry-redux#90012bf47c170f244039261548dab7c7597046dc",
|
"lbry-redux": "lbryio/lbry-redux#04015155796bc588bdf5b10762cfc874e6a1b00c",
|
||||||
"lbryinc": "lbryio/lbryinc#db0663fcc4a64cb082b6edc5798fafa67eb4300f",
|
"lbryinc": "lbryio/lbryinc#db0663fcc4a64cb082b6edc5798fafa67eb4300f",
|
||||||
"lint-staged": "^7.0.2",
|
"lint-staged": "^7.0.2",
|
||||||
"localforage": "^1.7.1",
|
"localforage": "^1.7.1",
|
||||||
|
|
|
@ -1175,7 +1175,6 @@
|
||||||
"Uncheck your email below if you want to stop receiving messages.": "Uncheck your email below if you want to stop receiving messages.",
|
"Uncheck your email below if you want to stop receiving messages.": "Uncheck your email below if you want to stop receiving messages.",
|
||||||
"Remove from blocked list": "Remove from blocked list",
|
"Remove from blocked list": "Remove from blocked list",
|
||||||
"Are you sure you want to remove this from the list?": "Are you sure you want to remove this from the list?",
|
"Are you sure you want to remove this from the list?": "Are you sure you want to remove this from the list?",
|
||||||
"Send a tip": "Send a tip",
|
|
||||||
"Send a chunk of change to this creator to let them know you appreciate their content.": "Send a chunk of change to this creator to let them know you appreciate their content.",
|
"Send a chunk of change to this creator to let them know you appreciate their content.": "Send a chunk of change to this creator to let them know you appreciate their content.",
|
||||||
"CableTube Escape Artists": "CableTube Escape Artists",
|
"CableTube Escape Artists": "CableTube Escape Artists",
|
||||||
"Unlink YouTube Channel": "Unlink YouTube Channel",
|
"Unlink YouTube Channel": "Unlink YouTube Channel",
|
||||||
|
@ -1279,5 +1278,24 @@
|
||||||
"Something went wrong. Please %click_here% to learn about sync limitations.": "Something went wrong. Please %click_here% to learn about sync limitations.",
|
"Something went wrong. Please %click_here% to learn about sync limitations.": "Something went wrong. Please %click_here% to learn about sync limitations.",
|
||||||
"Buy LBC": "Buy LBC",
|
"Buy LBC": "Buy LBC",
|
||||||
"Continue...": "Continue...",
|
"Continue...": "Continue...",
|
||||||
|
"Leave a comment": "Leave a comment",
|
||||||
|
"Be the first to comment!": "Be the first to comment!",
|
||||||
|
"Comment as": "Comment as",
|
||||||
|
"No uploads": "No uploads",
|
||||||
|
"You haven't uploaded anything yet. This is where you can find them when you do!": "You haven't uploaded anything yet. This is where you can find them when you do!",
|
||||||
|
"Discussion": "Discussion",
|
||||||
|
"Staked LBRY Credits": "Staked LBRY Credits",
|
||||||
|
"uploads": "uploads",
|
||||||
|
"1 comment": "1 comment",
|
||||||
|
"Upvote": "Upvote",
|
||||||
|
"Downvote": "Downvote",
|
||||||
|
"Replying as": "Replying as",
|
||||||
|
"Hide %number% Replies": "Hide %number% Replies",
|
||||||
|
"Show %number% Replies": "Show %number% Replies",
|
||||||
|
"Change to list layout": "Change to list layout",
|
||||||
|
"Create a channel": "Create a channel",
|
||||||
|
"Credit Details": "Credit Details",
|
||||||
|
"Sign In": "Sign In",
|
||||||
|
"Change to tile layout": "Change to tile layout",
|
||||||
"--end--": "--end--"
|
"--end--": "--end--"
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,7 +246,6 @@ function Comment(props: Props) {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="comment__actions">
|
<div className="comment__actions">
|
||||||
<CommentReactions />
|
|
||||||
{!hideReplyButton && (
|
{!hideReplyButton && (
|
||||||
<Button
|
<Button
|
||||||
requiresAuth={IS_WEB}
|
requiresAuth={IS_WEB}
|
||||||
|
@ -256,6 +255,7 @@ function Comment(props: Props) {
|
||||||
icon={ICONS.REPLY}
|
icon={ICONS.REPLY}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
<CommentReactions commentId={commentId} />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import Comment from './view';
|
import Comment from './view';
|
||||||
|
import { makeSelectMyReactionsForComment, makeSelectOthersReactionsForComment } from 'redux/selectors/comments';
|
||||||
|
import { doCommentReact } from 'redux/actions/comments';
|
||||||
|
|
||||||
const select = (state, props) => ({});
|
const select = (state, props) => ({
|
||||||
|
myReacts: makeSelectMyReactionsForComment(props.commentId)(state),
|
||||||
|
othersReacts: makeSelectOthersReactionsForComment(props.commentId)(state),
|
||||||
|
});
|
||||||
|
|
||||||
const perform = dispatch => ({});
|
const perform = dispatch => ({
|
||||||
|
react: (commentId, type) => dispatch(doCommentReact(commentId, type)),
|
||||||
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(Comment);
|
export default connect(select, perform)(Comment);
|
||||||
|
|
|
@ -4,13 +4,29 @@ import * as REACTION_TYPES from 'constants/reactions';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
import usePersistedState from 'effects/use-persisted-state';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
myReaction: ?string,
|
myReacts: Array<string>,
|
||||||
|
othersReacts: any,
|
||||||
|
react: (string, string) => void,
|
||||||
|
commentId: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function CommentReactions(props: Props) {
|
export default function CommentReactions(props: Props) {
|
||||||
const { myReaction } = props;
|
const { myReacts, othersReacts, commentId, react } = props;
|
||||||
|
const [activeChannel] = usePersistedState('comment-channel');
|
||||||
|
|
||||||
|
const getCountForReact = type => {
|
||||||
|
let count = 0;
|
||||||
|
if (othersReacts && othersReacts[type]) {
|
||||||
|
count += othersReacts[type];
|
||||||
|
}
|
||||||
|
if (myReacts && myReacts.includes(type)) {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -18,15 +34,20 @@ export default function CommentReactions(props: Props) {
|
||||||
title={__('Upvote')}
|
title={__('Upvote')}
|
||||||
icon={ICONS.UPVOTE}
|
icon={ICONS.UPVOTE}
|
||||||
className={classnames('comment__action', {
|
className={classnames('comment__action', {
|
||||||
'comment__action--active': myReaction === REACTION_TYPES.LIKE,
|
'comment__action--active': myReacts && myReacts.includes(REACTION_TYPES.LIKE),
|
||||||
})}
|
})}
|
||||||
|
disabled={!activeChannel}
|
||||||
|
onClick={() => react(commentId, REACTION_TYPES.LIKE)}
|
||||||
|
label={getCountForReact(REACTION_TYPES.LIKE)}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
title={__('Downvote')}
|
title={__('Downvote')}
|
||||||
icon={ICONS.DOWNVOTE}
|
icon={ICONS.DOWNVOTE}
|
||||||
className={classnames('comment__action', {
|
className={classnames('comment__action', {
|
||||||
'comment__action--active': myReaction === REACTION_TYPES.DISLIKE,
|
'comment__action--active': myReacts && myReacts.includes(REACTION_TYPES.DISLIKE),
|
||||||
})}
|
})}
|
||||||
|
onClick={() => react(commentId, REACTION_TYPES.DISLIKE)}
|
||||||
|
label={getCountForReact(REACTION_TYPES.DISLIKE)}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { makeSelectClaimIsMine, selectMyChannelClaims } from 'lbry-redux';
|
import { makeSelectClaimIsMine, selectMyChannelClaims } from 'lbry-redux';
|
||||||
import { makeSelectTopLevelCommentsForUri, selectIsFetchingComments } from 'redux/selectors/comments';
|
import { makeSelectTopLevelCommentsForUri, selectIsFetchingComments } from 'redux/selectors/comments';
|
||||||
import { doCommentList } from 'redux/actions/comments';
|
import { doCommentList, doCommentReactList } from 'redux/actions/comments';
|
||||||
import CommentsList from './view';
|
import CommentsList from './view';
|
||||||
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ const select = (state, props) => ({
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const perform = dispatch => ({
|
||||||
fetchComments: uri => dispatch(doCommentList(uri)),
|
fetchComments: uri => dispatch(doCommentList(uri)),
|
||||||
|
fetchReacts: uri => dispatch(doCommentReactList(uri)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(select, perform)(CommentsList);
|
export default connect(select, perform)(CommentsList);
|
||||||
|
|
|
@ -5,10 +5,12 @@ import Spinner from 'component/spinner';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import Card from 'component/common/card';
|
import Card from 'component/common/card';
|
||||||
import CommentCreate from 'component/commentCreate';
|
import CommentCreate from 'component/commentCreate';
|
||||||
|
import usePersistedState from 'effects/use-persisted-state';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
comments: Array<any>,
|
comments: Array<any>,
|
||||||
fetchComments: string => void,
|
fetchComments: string => void,
|
||||||
|
fetchReacts: string => void,
|
||||||
uri: string,
|
uri: string,
|
||||||
claimIsMine: boolean,
|
claimIsMine: boolean,
|
||||||
myChannels: ?Array<ChannelClaim>,
|
myChannels: ?Array<ChannelClaim>,
|
||||||
|
@ -17,7 +19,16 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
function CommentList(props: Props) {
|
function CommentList(props: Props) {
|
||||||
const { fetchComments, uri, comments, claimIsMine, myChannels, isFetchingComments, linkedComment } = props;
|
const {
|
||||||
|
fetchComments,
|
||||||
|
fetchReacts,
|
||||||
|
uri,
|
||||||
|
comments,
|
||||||
|
claimIsMine,
|
||||||
|
myChannels,
|
||||||
|
isFetchingComments,
|
||||||
|
linkedComment,
|
||||||
|
} = props;
|
||||||
|
|
||||||
const linkedCommentId = linkedComment && linkedComment.comment_id;
|
const linkedCommentId = linkedComment && linkedComment.comment_id;
|
||||||
const [start] = React.useState(0);
|
const [start] = React.useState(0);
|
||||||
|
@ -44,12 +55,19 @@ function CommentList(props: Props) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [activeChannel] = usePersistedState('comment-channel', '');
|
||||||
const commentRef = React.useRef();
|
const commentRef = React.useRef();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchComments(uri);
|
fetchComments(uri);
|
||||||
}, [fetchComments, uri]);
|
}, [fetchComments, uri]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (totalComments) {
|
||||||
|
fetchReacts(uri);
|
||||||
|
}
|
||||||
|
}, [fetchReacts, uri, totalComments, activeChannel]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (linkedCommentId && commentRef && commentRef.current) {
|
if (linkedCommentId && commentRef && commentRef.current) {
|
||||||
commentRef.current.scrollIntoView({ block: 'start' });
|
commentRef.current.scrollIntoView({ block: 'start' });
|
||||||
|
|
|
@ -265,6 +265,12 @@ export const COMMENT_UPDATE_FAILED = 'COMMENT_UPDATE_FAILED';
|
||||||
export const COMMENT_HIDE_STARTED = 'COMMENT_HIDE_STARTED';
|
export const COMMENT_HIDE_STARTED = 'COMMENT_HIDE_STARTED';
|
||||||
export const COMMENT_HIDE_COMPLETED = 'COMMENT_HIDE_COMPLETED';
|
export const COMMENT_HIDE_COMPLETED = 'COMMENT_HIDE_COMPLETED';
|
||||||
export const COMMENT_HIDE_FAILED = 'COMMENT_HIDE_FAILED';
|
export const COMMENT_HIDE_FAILED = 'COMMENT_HIDE_FAILED';
|
||||||
|
export const COMMENT_REACTION_LIST_STARTED = 'COMMENT_REACTION_LIST_STARTED';
|
||||||
|
export const COMMENT_REACTION_LIST_COMPLETED = 'COMMENT_REACTION_LIST_COMPLETED';
|
||||||
|
export const COMMENT_REACTION_LIST_FAILED = 'COMMENT_REACTION_LIST_FAILED';
|
||||||
|
export const COMMENT_REACT_STARTED = 'COMMENT_REACT_STARTED';
|
||||||
|
export const COMMENT_REACT_COMPLETED = 'COMMENT_REACT_COMPLETED';
|
||||||
|
export const COMMENT_REACT_FAILED = 'COMMENT_REACT_FAILED';
|
||||||
|
|
||||||
// Blocked channels
|
// Blocked channels
|
||||||
export const TOGGLE_BLOCK_CHANNEL = 'TOGGLE_BLOCK_CHANNEL';
|
export const TOGGLE_BLOCK_CHANNEL = 'TOGGLE_BLOCK_CHANNEL';
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
|
import * as REACTION_TYPES from 'constants/reactions';
|
||||||
import { Lbry, selectClaimsByUri, selectMyChannelClaims } from 'lbry-redux';
|
import { Lbry, selectClaimsByUri, selectMyChannelClaims } from 'lbry-redux';
|
||||||
import { doToast } from 'redux/actions/notifications';
|
import { doToast } from 'redux/actions/notifications';
|
||||||
|
import { makeSelectCommentIdsForUri, makeSelectMyReactionsForComment } from 'redux/selectors/comments';
|
||||||
|
|
||||||
export function doCommentList(uri: string, page: number = 1, pageSize: number = 99999) {
|
export function doCommentList(uri: string, page: number = 1, pageSize: number = 99999) {
|
||||||
return (dispatch: Dispatch, getState: GetState) => {
|
return (dispatch: Dispatch, getState: GetState) => {
|
||||||
|
@ -39,6 +41,102 @@ export function doCommentList(uri: string, page: number = 1, pageSize: number =
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function doCommentReactList(uri: string | null, commentId?: string) {
|
||||||
|
return (dispatch: Dispatch, getState: GetState) => {
|
||||||
|
const state = getState();
|
||||||
|
const channel = localStorage.getItem('comment-channel');
|
||||||
|
// if not channel, fail?
|
||||||
|
if (!channel) {
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.COMMENT_REACTION_LIST_FAILED,
|
||||||
|
data: 'No active channel found',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const commentIds = uri ? makeSelectCommentIdsForUri(uri)(state) : [commentId];
|
||||||
|
const myChannels = selectMyChannelClaims(state);
|
||||||
|
const claimForChannelName = myChannels.find(chan => chan.name === channel);
|
||||||
|
const channelId = claimForChannelName && claimForChannelName.claim_id;
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.COMMENT_REACTION_LIST_STARTED,
|
||||||
|
});
|
||||||
|
Lbry.comment_react_list({
|
||||||
|
comment_ids: commentIds.join(','),
|
||||||
|
channel_name: channel,
|
||||||
|
channel_id: channelId,
|
||||||
|
})
|
||||||
|
.then((result: CommentReactListResponse) => {
|
||||||
|
const { my_reactions: myReactions, others_reactions: othersReactions } = result;
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.COMMENT_REACTION_LIST_COMPLETED,
|
||||||
|
data: {
|
||||||
|
myReactions,
|
||||||
|
othersReactions,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.COMMENT_REACTION_LIST_FAILED,
|
||||||
|
data: error,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function doCommentReact(commentId: string, type: string) {
|
||||||
|
return (dispatch: Dispatch, getState: GetState) => {
|
||||||
|
const state = getState();
|
||||||
|
const channel = localStorage.getItem('comment-channel');
|
||||||
|
// if not channel, fail?
|
||||||
|
if (!channel) {
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.COMMENT_REACTION_LIST_FAILED,
|
||||||
|
data: 'No active channel found',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const myChannels = selectMyChannelClaims(state);
|
||||||
|
const myReacts = makeSelectMyReactionsForComment(commentId)(state);
|
||||||
|
const claimForChannelName = myChannels.find(chan => chan.name === channel);
|
||||||
|
const channelId = claimForChannelName && claimForChannelName.claim_id;
|
||||||
|
const exclusiveTypes = {
|
||||||
|
[REACTION_TYPES.LIKE]: REACTION_TYPES.DISLIKE,
|
||||||
|
[REACTION_TYPES.DISLIKE]: REACTION_TYPES.LIKE,
|
||||||
|
};
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.COMMENT_REACT_STARTED,
|
||||||
|
});
|
||||||
|
const params: CommentReactParams = {
|
||||||
|
comment_ids: commentId,
|
||||||
|
channel_name: channel,
|
||||||
|
channel_id: channelId,
|
||||||
|
react_type: type,
|
||||||
|
};
|
||||||
|
if (Object.keys(exclusiveTypes).includes(type)) {
|
||||||
|
params['clear_types'] = exclusiveTypes[type];
|
||||||
|
}
|
||||||
|
if (myReacts.includes(type)) {
|
||||||
|
params['remove'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Lbry.comment_react(params)
|
||||||
|
.then((result: CommentReactListResponse) => {
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.COMMENT_REACT_COMPLETED,
|
||||||
|
});
|
||||||
|
dispatch(doCommentReactList(null, commentId));
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
dispatch({
|
||||||
|
type: ACTIONS.COMMENT_REACT_FAILED,
|
||||||
|
data: error,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function doCommentCreate(
|
export function doCommentCreate(
|
||||||
comment: string = '',
|
comment: string = '',
|
||||||
claim_id: string = '',
|
claim_id: string = '',
|
||||||
|
@ -83,7 +181,6 @@ export function doCommentCreate(
|
||||||
uri,
|
uri,
|
||||||
comment: result,
|
comment: result,
|
||||||
claimId: claim_id,
|
claimId: claim_id,
|
||||||
uri,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
|
@ -11,6 +11,9 @@ const defaultState: CommentsState = {
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isCommenting: false,
|
isCommenting: false,
|
||||||
myComments: undefined,
|
myComments: undefined,
|
||||||
|
isFetchingReacts: false,
|
||||||
|
myReactsByCommentId: {},
|
||||||
|
othersReactsByCommentId: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default handleActions(
|
export default handleActions(
|
||||||
|
@ -56,7 +59,6 @@ export default handleActions(
|
||||||
topLevelCommentsById[claimId].unshift(comment.comment_id);
|
topLevelCommentsById[claimId].unshift(comment.comment_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
topLevelCommentsById,
|
topLevelCommentsById,
|
||||||
|
@ -69,6 +71,44 @@ export default handleActions(
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
[ACTIONS.COMMENT_REACTION_LIST_STARTED]: (state: CommentsState, action: any): CommentsState => ({
|
||||||
|
...state,
|
||||||
|
isFetchingReacts: true,
|
||||||
|
}),
|
||||||
|
|
||||||
|
[ACTIONS.COMMENT_REACTION_LIST_FAILED]: (state: CommentsState, action: any) => ({
|
||||||
|
...state,
|
||||||
|
isFetchingReacts: false,
|
||||||
|
}),
|
||||||
|
|
||||||
|
[ACTIONS.COMMENT_REACTION_LIST_COMPLETED]: (state: CommentsState, action: any): CommentsState => {
|
||||||
|
const { myReactions, othersReactions } = action.data;
|
||||||
|
const myReacts = Object.assign({}, state.myReactsByCommentId);
|
||||||
|
const othersReacts = Object.assign({}, state.othersReactsByCommentId);
|
||||||
|
if (myReactions) {
|
||||||
|
Object.entries(myReactions).forEach(e => {
|
||||||
|
myReacts[e[0]] = Object.entries(e[1]).reduce((acc, el) => {
|
||||||
|
if (el[1] === 1) {
|
||||||
|
acc.push(el[0]);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (othersReactions) {
|
||||||
|
Object.entries(othersReactions).forEach(e => {
|
||||||
|
othersReacts[e[0]] = e[1];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
isFetchingReacts: false,
|
||||||
|
myReactsByCommentId: myReacts,
|
||||||
|
othersReactsByCommentId: othersReacts,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
[ACTIONS.COMMENT_LIST_STARTED]: state => ({ ...state, isLoading: true }),
|
[ACTIONS.COMMENT_LIST_STARTED]: state => ({ ...state, isLoading: true }),
|
||||||
|
|
||||||
[ACTIONS.COMMENT_LIST_COMPLETED]: (state: CommentsState, action: any) => {
|
[ACTIONS.COMMENT_LIST_COMPLETED]: (state: CommentsState, action: any) => {
|
||||||
|
|
|
@ -88,6 +88,22 @@ export const selectCommentsByUri = createSelector(selectState, state => {
|
||||||
return comments;
|
return comments;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const makeSelectCommentIdsForUri = (uri: string) =>
|
||||||
|
createSelector(selectState, selectCommentsByUri, selectClaimsById, (state, byUri) => {
|
||||||
|
const claimId = byUri[uri];
|
||||||
|
return state.byId[claimId];
|
||||||
|
});
|
||||||
|
|
||||||
|
export const makeSelectMyReactionsForComment = (commentId: string) =>
|
||||||
|
createSelector(selectState, state => {
|
||||||
|
return state.myReactsByCommentId[commentId];
|
||||||
|
});
|
||||||
|
|
||||||
|
export const makeSelectOthersReactionsForComment = (commentId: string) =>
|
||||||
|
createSelector(selectState, state => {
|
||||||
|
return state.othersReactsByCommentId[commentId];
|
||||||
|
});
|
||||||
|
|
||||||
export const makeSelectCommentsForUri = (uri: string) =>
|
export const makeSelectCommentsForUri = (uri: string) =>
|
||||||
createSelector(
|
createSelector(
|
||||||
selectCommentsByClaimId,
|
selectCommentsByClaimId,
|
||||||
|
|
|
@ -199,7 +199,7 @@ $thumbnailWidthSmall: 1.5rem;
|
||||||
margin-top: var(--spacing-s);
|
margin-top: var(--spacing-s);
|
||||||
|
|
||||||
> *:not(:last-child) {
|
> *:not(:last-child) {
|
||||||
margin-right: var(--spacing-xs);
|
margin-right: var(--spacing-s);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
|
|
|
@ -6411,9 +6411,9 @@ lazy-val@^1.0.4:
|
||||||
yargs "^13.2.2"
|
yargs "^13.2.2"
|
||||||
zstd-codec "^0.1.1"
|
zstd-codec "^0.1.1"
|
||||||
|
|
||||||
lbry-redux@lbryio/lbry-redux#90012bf47c170f244039261548dab7c7597046dc:
|
lbry-redux@lbryio/lbry-redux#04015155796bc588bdf5b10762cfc874e6a1b00c:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/90012bf47c170f244039261548dab7c7597046dc"
|
resolved "https://codeload.github.com/lbryio/lbry-redux/tar.gz/04015155796bc588bdf5b10762cfc874e6a1b00c"
|
||||||
dependencies:
|
dependencies:
|
||||||
proxy-polyfill "0.1.6"
|
proxy-polyfill "0.1.6"
|
||||||
reselect "^3.0.0"
|
reselect "^3.0.0"
|
||||||
|
|
Loading…
Add table
Reference in a new issue