diff --git a/ui/component/comment/view.jsx b/ui/component/comment/view.jsx index 5161382fa..0496b7e7c 100644 --- a/ui/component/comment/view.jsx +++ b/ui/component/comment/view.jsx @@ -59,7 +59,9 @@ type Props = { stakedLevel: number, supportAmount: number, numDirectReplies: number, - isFiat: boolean + isFiat: boolean, + setCommentReply: (any) => void, + commentReply: any, }; const LENGTH_TO_COLLAPSE = 300; @@ -93,6 +95,8 @@ function Comment(props: Props) { supportAmount, numDirectReplies, isFiat, + setCommentReply, + commentReply, } = props; const { @@ -178,6 +182,7 @@ function Comment(props: Props) { function handleSubmit() { updateComment(commentId, editedMessage); + setCommentReply({ ...commentReply, comment_id: commentId, comment: editedMessage }); setEditing(false); } @@ -253,7 +258,10 @@ function Comment(props: Props) { )} -
+ { + e.stopPropagation(); + e.preventDefault(); + }}> -
+
{isEditing ? ( @@ -286,6 +295,10 @@ function Comment(props: Props) { charCount={charCount} onChange={handleEditMessageChanged} textAreaMaxLength={FF_MAX_CHARS_IN_COMMENT} + onClick={(e) => { + e.stopPropagation(); + e.preventDefault(); + }} />
) : ( @@ -330,7 +350,11 @@ function Comment(props: Props) { requiresAuth={IS_WEB} label={commentingEnabled ? __('Reply') : __('Log in to reply')} className="comment__action" - onClick={handleCommentReply} + onClick={(e) => { + handleCommentReply(); + e.stopPropagation(); + e.preventDefault(); + }} icon={ICONS.REPLY} /> )} diff --git a/ui/component/commentCreate/view.jsx b/ui/component/commentCreate/view.jsx index a1936d73d..35e2b1c7a 100644 --- a/ui/component/commentCreate/view.jsx +++ b/ui/component/commentCreate/view.jsx @@ -50,6 +50,7 @@ type Props = { sendTip: ({}, (any) => void, (any) => void) => void, doToast: ({ message: string }) => void, disabled: boolean, + setCommentReply: (any) => void, }; export function CommentCreate(props: Props) { @@ -71,6 +72,7 @@ export function CommentCreate(props: Props) { claimIsMine, sendTip, doToast, + setCommentReply, } = props; const buttonRef: ElementRef = React.useRef(); const { @@ -244,6 +246,7 @@ export function CommentCreate(props: Props) { createComment(commentValue, claimId, parentId, txid, payment_intent_id, environment) .then((res) => { setIsSubmitting(false); + setCommentReply(res); if (res && res.signature) { setCommentValue(''); diff --git a/ui/component/commentMenuList/view.jsx b/ui/component/commentMenuList/view.jsx index e9f59bf4c..58ecf9989 100644 --- a/ui/component/commentMenuList/view.jsx +++ b/ui/component/commentMenuList/view.jsx @@ -30,6 +30,7 @@ type Props = { moderationDelegatorsById: { [string]: { global: boolean, delegators: { name: string, claimId: string } } }, openModal: (id: string, {}) => void, supportAmount?: any, + setCommentReply: (any) => void, }; function CommentMenuList(props: Props) { @@ -56,6 +57,7 @@ function CommentMenuList(props: Props) { moderationDelegatorsById, openModal, supportAmount, + setCommentReply, } = props; const contentChannelClaim = !claim @@ -83,7 +85,7 @@ function CommentMenuList(props: Props) { if (playingUri && playingUri.source === 'comment') { clearPlayingUri(); } - openModal(MODALS.CONFIRM_REMOVE_COMMENT, { commentId, commentIsMine, contentChannelPermanentUrl, supportAmount }); + openModal(MODALS.CONFIRM_REMOVE_COMMENT, { commentId, commentIsMine, contentChannelPermanentUrl, supportAmount, setCommentReply }); } function handleCommentBlock() { diff --git a/ui/component/common/form-components/form-field.jsx b/ui/component/common/form-components/form-field.jsx index 83e01f85d..f23d826d5 100644 --- a/ui/component/common/form-components/form-field.jsx +++ b/ui/component/common/form-components/form-field.jsx @@ -283,10 +283,12 @@ export class FormField extends React.PureComponent { type="button" className="button--emoji" label={emoji} - onClick={() => { + onClick={(e) => { inputProps.onChange({ target: { value: inputProps.value ? `${inputProps.value} ${emoji}` : emoji }, }); + e.stopPropagation(); + e.preventDefault(); }} /> ))} diff --git a/ui/component/notification/index.js b/ui/component/notification/index.js index ac33a7d69..5d5b49095 100644 --- a/ui/component/notification/index.js +++ b/ui/component/notification/index.js @@ -1,9 +1,13 @@ import { connect } from 'react-redux'; import { doReadNotifications, doDeleteNotification } from 'redux/actions/notifications'; -import { doResolveUri } from 'lbry-redux'; +import { doResolveUri, selectMyChannelClaims } from 'lbry-redux'; import Notification from './view'; -export default connect(null, { +const select = (state) => ({ + myChannels: selectMyChannelClaims(state), + }); + +export default connect(select, { doReadNotifications, doDeleteNotification, doResolveUri, diff --git a/ui/component/notification/view.jsx b/ui/component/notification/view.jsx index 9fd083a3c..d75c2f404 100644 --- a/ui/component/notification/view.jsx +++ b/ui/component/notification/view.jsx @@ -19,6 +19,7 @@ import LbcMessage from 'component/common/lbc-message'; import UriIndicator from 'component/uriIndicator'; import CommentReactions from 'component/commentReactions'; import CommentCreate from 'component/commentCreate'; +import CommentView from 'component/comment'; import { NavLink } from 'react-router-dom'; type Props = { @@ -28,13 +29,27 @@ type Props = { doReadNotifications: ([number]) => void, doDeleteNotification: (number) => void, doResolveUri: (string) => void, + myChannels: ?Array, }; export default function Notification(props: Props) { - const { notification, menuButton = false, doReadNotifications, doDeleteNotification, doResolveUri } = props; + const { notification, menuButton = false, doReadNotifications, doDeleteNotification, doResolveUri, myChannels } = props; const { push } = useHistory(); const { notification_rule, notification_parameters, is_read, id } = notification; const [isReplying, setReplying] = React.useState(false); + const [commentReply, setCommentReply] = React.useState(); + + const isMyComment = (channelId: string): boolean => { + if (myChannels != null && channelId != null) { + for (let i = 0; i < myChannels.length; i++) { + if (myChannels[i].claim_id === channelId) { + return true; + } + } + } + return false; + }; + const isCommentNotification = notification_rule === RULE.COMMENT || notification_rule === RULE.COMMENT_REPLY || @@ -246,12 +261,29 @@ export default function Notification(props: Props) { isReply uri={notificationTarget} parentId={notification_parameters.dynamic.hash} - onDoneReplying={() => { - setReplying(false); - }} - onCancelReplying={() => { - setReplying(false); - }} + onDoneReplying={() => setReplying(false)} + onCancelReplying={() => setReplying(false)} + setCommentReply={setCommentReply} + /> + )} + + {commentReply && ( + )} diff --git a/ui/modal/modalRemoveComment/view.jsx b/ui/modal/modalRemoveComment/view.jsx index f595be838..58c60ae17 100644 --- a/ui/modal/modalRemoveComment/view.jsx +++ b/ui/modal/modalRemoveComment/view.jsx @@ -11,10 +11,11 @@ type Props = { closeModal: () => void, deleteComment: (string, ?string) => void, supportAmount?: any, + setCommentReply: (any) => void, }; function ModalRemoveComment(props: Props) { - const { commentId, commentIsMine, contentChannelPermanentUrl, closeModal, deleteComment, supportAmount } = props; + const { commentId, commentIsMine, contentChannelPermanentUrl, closeModal, deleteComment, supportAmount, setCommentReply } = props; return ( @@ -36,6 +37,7 @@ function ModalRemoveComment(props: Props) { label={__('Remove')} onClick={() => { deleteComment(commentId, commentIsMine ? undefined : contentChannelPermanentUrl); + setCommentReply(undefined); closeModal(); }} /> diff --git a/ui/scss/component/_comments.scss b/ui/scss/component/_comments.scss index 90077b759..674c584a2 100644 --- a/ui/scss/component/_comments.scss +++ b/ui/scss/component/_comments.scss @@ -218,6 +218,7 @@ $thumbnailWidthSmall: 1rem; .comment__message { word-break: break-word; max-width: 35rem; + color: var(--color-text); ul li, ol li {