Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { User } from '../user/user';
import { EditComment } from './edit_comment';
import { clearEditingLocalStorage } from './helpers';
import { AnonymousUser } from '../user/anonymous_user';
import { QuillRenderer } from '../react_quill_editor/quill_renderer';

type CommentAuthorProps = {
comment: CommentType<any>;
Expand All @@ -29,21 +30,14 @@ const CommentAuthor = (props: CommentAuthorProps) => {
// Check for accounts on forums that originally signed up on a different base chain,
// Render them as anonymous as the forum is unable to support them.
if (app.chain.meta.type === ChainType.Offchain) {
if (
comment.authorChain !== app.chain.id &&
comment.authorChain !== app.chain.base
) {
if (comment.authorChain !== app.chain.id && comment.authorChain !== app.chain.base) {
return <AnonymousUser distinguishingKey={comment.author} />;
}
}

const author: Account = app.chain.accounts.get(comment.author);

return comment.deleted ? (
<span>[deleted]</span>
) : (
<User avatarSize={24} user={author} popover linkify />
);
return comment.deleted ? <span>[deleted]</span> : <User avatarSize={24} user={author} popover linkify />;
};

type CommentProps = {
Expand All @@ -58,20 +52,11 @@ type CommentProps = {
};

export const Comment = (props: CommentProps) => {
const {
comment,
handleIsReplying,
isLast,
isLocked,
setIsGloballyEditing,
threadLevel,
updatedCommentsCallback,
} = props;

const [isEditingComment, setIsEditingComment] =
React.useState<boolean>(false);
const [shouldRestoreEdits, setShouldRestoreEdits] =
React.useState<boolean>(false);
const { comment, handleIsReplying, isLast, isLocked, setIsGloballyEditing, threadLevel, updatedCommentsCallback } =
props;

const [isEditingComment, setIsEditingComment] = React.useState<boolean>(false);
const [shouldRestoreEdits, setShouldRestoreEdits] = React.useState<boolean>(false);
const [savedEdits, setSavedEdits] = React.useState<string>('');

const handleSetIsEditingComment = (status: boolean) => {
Expand All @@ -83,24 +68,21 @@ export const Comment = (props: CommentProps) => {
app.user.isSiteAdmin ||
app.roles.isRoleOfCommunity({
role: 'admin',
chain: app.activeChainId(),
chain: app.activeChainId()
}) ||
app.roles.isRoleOfCommunity({
role: 'moderator',
chain: app.activeChainId(),
chain: app.activeChainId()
});

const canReply =
!isLast && !isLocked && app.isLoggedIn() && app.user.activeAccount;
const canReply = !isLast && !isLocked && app.isLoggedIn() && app.user.activeAccount;

const canEditAndDelete =
!isLocked &&
(comment.author === app.user.activeAccount?.address || isAdminOrMod);
const canEditAndDelete = !isLocked && (comment.author === app.user.activeAccount?.address || isAdminOrMod);

const deleteComment = async () => {
await app.comments.delete(comment);
updatedCommentsCallback();
}
};

return (
<div className={`Comment comment-${comment.id}`}>
Expand All @@ -120,12 +102,7 @@ export const Comment = (props: CommentProps) => {
{/* <CWText type="caption" className="published-text">
published on
</CWText> */}
<CWText
key={comment.id}
type="caption"
fontWeight="medium"
className="published-text"
>
<CWText key={comment.id} type="caption" fontWeight="medium" className="published-text">
{moment(comment.createdAt).format('l')}
</CWText>
</div>
Expand All @@ -140,7 +117,7 @@ export const Comment = (props: CommentProps) => {
) : (
<>
<CWText className="comment-text">
{renderQuillTextBody(comment.text)}
<QuillRenderer doc={comment.text} />
</CWText>
{!comment.deleted && (
<div className="comment-footer">
Expand All @@ -165,11 +142,7 @@ export const Comment = (props: CommentProps) => {
{canEditAndDelete && (
<PopoverMenu
renderTrigger={(onclick) => (
<CWIconButton
iconName="dotsVertical"
iconSize="small"
onClick={onclick}
/>
<CWIconButton iconName="dotsVertical" iconSize="small" onClick={onclick} />
)}
menuItems={[
{
Expand All @@ -178,32 +151,23 @@ export const Comment = (props: CommentProps) => {
onClick: async (e) => {
e.preventDefault();
setSavedEdits(
localStorage.getItem(
`${app.activeChainId()}-edit-comment-${
comment.id
}-storedText`
)
localStorage.getItem(`${app.activeChainId()}-edit-comment-${comment.id}-storedText`)
);
if (savedEdits) {
clearEditingLocalStorage(
comment.id,
ContentType.Comment
);
clearEditingLocalStorage(comment.id, ContentType.Comment);

const confirmationResult = window.confirm(
'Previous changes found. Restore edits?'
);
const confirmationResult = window.confirm('Previous changes found. Restore edits?');

setShouldRestoreEdits(confirmationResult);
}
handleSetIsEditingComment(true);
},
}
},
{
label: 'Delete',
iconLeft: 'trash',
onClick: deleteComment,
},
onClick: deleteComment
}
]}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,8 @@ import { CWButton } from '../component_kit/cw_button';
import { CWText } from '../component_kit/cw_text';
import { CWValidationText } from '../component_kit/cw_validation_text';
import { jumpHighlightComment } from './helpers';
import {
createDeltaFromText,
getTextFromDelta,
ReactQuillEditor,
} from '../react_quill_editor';
import { createDeltaFromText, getTextFromDelta, ReactQuillEditor } from '../react_quill_editor';
import { serializeDelta } from '../react_quill_editor/utils';

type CreateCommmentProps = {
handleIsReplying?: (isReplying: boolean, id?: number) => void;
Expand All @@ -32,19 +29,12 @@ type CreateCommmentProps = {

export const CreateComment = (props: CreateCommmentProps) => {
const [errorMsg, setErrorMsg] = React.useState<string | null>(null);
const [contentDelta, setContentDelta] = React.useState<DeltaStatic>(
createDeltaFromText('')
);
const [contentDelta, setContentDelta] = React.useState<DeltaStatic>(createDeltaFromText(''));
const [sendingComment, setSendingComment] = React.useState<boolean>(false);

const editorValue = getTextFromDelta(contentDelta);

const {
handleIsReplying,
parentCommentId,
rootProposal,
updatedCommentsCallback,
} = props;
const { handleIsReplying, parentCommentId, rootProposal, updatedCommentsCallback } = props;

const author = app.user.activeAccount;

Expand All @@ -61,7 +51,7 @@ export const CreateComment = (props: CreateCommmentProps) => {
author.address,
rootProposal.uniqueIdentifier,
chainId,
JSON.stringify(contentDelta),
serializeDelta(contentDelta),
parentCommentId
);

Expand All @@ -88,79 +78,54 @@ export const CreateComment = (props: CreateCommmentProps) => {
}
};

const activeTopicName =
rootProposal instanceof Thread ? rootProposal?.topic?.name : null;
const activeTopicName = rootProposal instanceof Thread ? rootProposal?.topic?.name : null;

// token balance check if needed
const tokenPostingThreshold: BN =
TopicGateCheck.getTopicThreshold(activeTopicName);
const tokenPostingThreshold: BN = TopicGateCheck.getTopicThreshold(activeTopicName);

const userBalance: BN = TopicGateCheck.getUserBalance();
const userFailsThreshold =
tokenPostingThreshold?.gtn(0) &&
userBalance?.gtn(0) &&
userBalance.lt(tokenPostingThreshold);
tokenPostingThreshold?.gtn(0) && userBalance?.gtn(0) && userBalance.lt(tokenPostingThreshold);

const disabled =
editorValue.length === 0 || sendingComment || userFailsThreshold;
const disabled = editorValue.length === 0 || sendingComment || userFailsThreshold;

const decimals = getDecimals(app.chain);

const cancel = (e) => {
e.preventDefault();
setContentDelta(createDeltaFromText(''))
setContentDelta(createDeltaFromText(''));
if (handleIsReplying) {
handleIsReplying(false)
handleIsReplying(false);
}
}
};

return (
<div className="CreateComment">
<div className="attribution-row">
<div className="attribution-left-content">
<CWText type="caption">
{parentType === ContentType.Comment ? 'Reply as' : 'Comment as'}
</CWText>
<CWText type="caption">{parentType === ContentType.Comment ? 'Reply as' : 'Comment as'}</CWText>
<CWText type="caption" fontWeight="medium" className="user-link-text">
<User user={author} hideAvatar linkify />
</CWText>
</div>
{errorMsg && <CWValidationText message={errorMsg} status="failure" />}
</div>
<ReactQuillEditor
className="editor"
contentDelta={contentDelta}
setContentDelta={setContentDelta}
/>
<ReactQuillEditor className="editor" contentDelta={contentDelta} setContentDelta={setContentDelta} />
{tokenPostingThreshold && tokenPostingThreshold.gt(new BN(0)) && (
<CWText className="token-req-text">
Commenting in {activeTopicName} requires{' '}
{weiToTokens(tokenPostingThreshold.toString(), decimals)}{' '}
Commenting in {activeTopicName} requires {weiToTokens(tokenPostingThreshold.toString(), decimals)}{' '}
{app.chain.meta.default_symbol}.{' '}
{userBalance && app.user.activeAccount && (
<>
You have {weiToTokens(userBalance.toString(), decimals)}{' '}
{app.chain.meta.default_symbol}.
You have {weiToTokens(userBalance.toString(), decimals)} {app.chain.meta.default_symbol}.
</>
)}
</CWText>
)}
<div className="form-bottom">
<div className="form-buttons">
{
editorValue.length > 0 && (
<CWButton
buttonType="secondary-blue"
onClick={cancel}
label="Cancel"
/>
)
}
<CWButton
disabled={disabled}
onClick={handleSubmitComment}
label="Submit"
/>
{editorValue.length > 0 && <CWButton buttonType="secondary-blue" onClick={cancel} label="Cancel" />}
<CWButton disabled={disabled} onClick={handleSubmitComment} label="Submit" />
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { CWButton } from '../component_kit/cw_button';
import { clearEditingLocalStorage } from './helpers';
import type { DeltaStatic } from 'quill';
import { ReactQuillEditor } from '../react_quill_editor';
import { parseDeltaString } from '../react_quill_editor/utils';
import { deserializeDelta, serializeDelta } from '../react_quill_editor/utils';

type EditCommentProps = {
comment: Comment<any>;
Expand All @@ -20,16 +20,10 @@ type EditCommentProps = {
};

export const EditComment = (props: EditCommentProps) => {
const {
comment,
savedEdits,
setIsEditing,
shouldRestoreEdits,
updatedCommentsCallback,
} = props;
const { comment, savedEdits, setIsEditing, shouldRestoreEdits, updatedCommentsCallback } = props;

const commentBody = (shouldRestoreEdits && savedEdits) ? savedEdits : comment.text;
const body = parseDeltaString(commentBody)
const commentBody = shouldRestoreEdits && savedEdits ? savedEdits : comment.text;
const body = deserializeDelta(commentBody);

const [contentDelta, setContentDelta] = React.useState<DeltaStatic>(body);
const [saving, setSaving] = React.useState<boolean>();
Expand All @@ -40,53 +34,38 @@ export const EditComment = (props: EditCommentProps) => {
let cancelConfirmed = true;

if (JSON.stringify(body) !== JSON.stringify(contentDelta)) {
cancelConfirmed = window.confirm(
'Cancel editing? Changes will not be saved.'
);
cancelConfirmed = window.confirm('Cancel editing? Changes will not be saved.');
}

if (cancelConfirmed) {
setIsEditing(false);
clearEditingLocalStorage(comment.id, ContentType.Comment);
}
}
};

const save = async (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
e.preventDefault();

setSaving(true);

try {
await app.comments.edit(comment, JSON.stringify(contentDelta))
await app.comments.edit(comment, serializeDelta(contentDelta));
setIsEditing(false);
clearEditingLocalStorage(comment.id, ContentType.Comment);
updatedCommentsCallback();
} catch (err) {
console.error(err)
console.error(err);
} finally {
setSaving(false);
}

}
};

return (
<div className="EditComment">
<ReactQuillEditor
contentDelta={contentDelta}
setContentDelta={setContentDelta}
/>
<ReactQuillEditor contentDelta={contentDelta} setContentDelta={setContentDelta} />
<div className="buttons-row">
<CWButton
label="Cancel"
disabled={saving}
buttonType="secondary-blue"
onClick={cancel}
/>
<CWButton
label="Save"
disabled={saving}
onClick={save}
/>
<CWButton label="Cancel" disabled={saving} buttonType="secondary-blue" onClick={cancel} />
<CWButton label="Save" disabled={saving} onClick={save} />
</div>
</div>
);
Expand Down
Loading