implemented replying in modal

This commit is contained in:
plebbitor
2023-04-12 21:00:51 +02:00
parent ba6fe429b0
commit 322a7d3d23
4 changed files with 175 additions and 16 deletions
+157 -11
View File
@@ -1,18 +1,164 @@
import React from 'react';
import React, { useRef, useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { usePublishComment } from '@plebbit/plebbit-react-hooks';
import { StyledModal } from './styled/ReplyModal.styled';
import useGeneralStore from '../hooks/stores/useGeneralStore';
import Modal from 'react-modal';
import Draggable from 'react-draggable';
import useError from '../hooks/useError';
import useSuccess from '../hooks/useSuccess';
const ReplyModal = ({ isOpen, closeModal }) => {
const selectedStyle = useGeneralStore(state => state.selectedStyle);
const {
captchaResponse, setCaptchaResponse,
setChallengesArray,
setIsCaptchaOpen,
setPendingComment,
selectedAddress,
selectedReply,
selectedStyle,
selectedThread,
} = useGeneralStore(state => state);
const handleCloseModal = () => {
closeModal();
const navigate = useNavigate();
const nodeRef = useRef(null);
const nameRef = useRef();
const commentRef = useRef();
const linkRef = useRef();
const onChallengeVerificationRef = useRef();
const [errorMessage, setErrorMessage] = useState(null);
const [successMessage, setSuccessMessage] = useState(null);
useError(errorMessage, [errorMessage]);
useSuccess(successMessage, [successMessage]);
const onChallengeVerification = (challengeVerification) => {
if (challengeVerification.challengeSuccess === true) {
setSuccessMessage('challenge success', {publishedCid: challengeVerification.publication?.cid});
navigate(`/p/${selectedAddress}/c/${selectedThread}`);
}
else if (challengeVerification.challengeSuccess === false) {
setErrorMessage('challenge failed', {reason: challengeVerification.reason, errors: challengeVerification.errors});
setErrorMessage("Error: You seem to have mistyped the CAPTCHA. Please try again.");
}
};
const onChallenge = async (challenges, comment) => {
setPendingComment(comment);
let challengeAnswers = [];
try {
challengeAnswers = await getChallengeAnswersFromUser(challenges)
}
catch (error) {
setErrorMessage(error);
}
if (challengeAnswers) {
await comment.publishChallengeAnswers(challengeAnswers)
}
};
const [publishCommentOptions, setPublishCommentOptions] = useState({
subplebbitAddress: selectedAddress,
onChallenge,
onChallengeVerification: onChallengeVerificationRef.current,
onError: (error) => {
setErrorMessage(error);
},
});
const { publishComment, index } = usePublishComment(publishCommentOptions);
useEffect(() => {
if (index !== undefined) {
navigate(`/profile/c/${index}`);
setSuccessMessage('Comment pending with index ' + index + '.');
}
}, [index]);
onChallengeVerificationRef.current = onChallengeVerification;
const resetFields = () => {
nameRef.current.value = '';
commentRef.current.value = '';
linkRef.current.value = '';
};
useEffect(() => {
setPublishCommentOptions((prevPublishCommentOptions) => ({
...prevPublishCommentOptions,
subplebbitAddress: selectedAddress,
onChallengeVerification: onChallengeVerificationRef.current,
}));
}, [selectedAddress]);
const handleSubmit = async (event) => {
event.preventDefault();
setPublishCommentOptions((prevPublishCommentOptions) => ({
...prevPublishCommentOptions,
displayName: nameRef.current.value || undefined,
content: commentRef.current.value || undefined,
link: linkRef.current.value || undefined,
parentCid: selectedReply,
}));
};
useEffect(() => {
if (publishCommentOptions.content) {
(async () => {
await publishComment();
resetFields();
})();
}
}, [publishCommentOptions]);
const getChallengeAnswersFromUser = async (challenges) => {
setChallengesArray(challenges);
return new Promise((resolve, reject) => {
const imageString = challenges?.challenges[0].challenge;
const imageSource = `data:image/png;base64,${imageString}`;
const challengeImg = new Image();
challengeImg.src = imageSource;
challengeImg.onload = () => {
setIsCaptchaOpen(true);
const handleKeyDown = (event) => {
if (event.key === 'Enter') {
resolve(captchaResponse);
setIsCaptchaOpen(false);
document.removeEventListener('keydown', handleKeyDown);
event.preventDefault();
}
};
setCaptchaResponse('');
document.addEventListener('keydown', handleKeyDown);
};
challengeImg.onerror = () => {
reject(setErrorMessage('Could not load challenges'));
};
});
};
const nodeRef = React.useRef(null);
return (
<StyledModal
@@ -26,21 +172,21 @@ const ReplyModal = ({ isOpen, closeModal }) => {
<Draggable handle=".modal-header" nodeRef={nodeRef}>
<div className="modal-content" ref={nodeRef}>
<div className="modal-header">
Reply to Thread
<button className="icon" onClick={handleCloseModal} title="close" />
Reply to c/{selectedReply}
<button className="icon" onClick={() => closeModal()} title="close" />
</div>
<div id="form">
<div>
<input id="name" type="text" placeholder="Name"></input>
<input id="name" type="text" placeholder="Name" ref={nameRef} />
</div>
<div>
<input id="name" type="text" placeholder="Embed link" disabled></input>
<input id="name" type="text" placeholder="Embed link" ref={linkRef} />
</div>
<div>
<textarea rows="4" placeholder="Comment" wrap="soft"></textarea>
<textarea rows="4" placeholder="Comment" wrap="soft" ref={commentRef} />
</div>
<div>
<button id="next">Post</button>
<button id="next" onClick={handleSubmit}>Post</button>
</div>
</div>
</div>
+15 -4
View File
@@ -29,6 +29,7 @@ const Board = () => {
isSettingsOpen, setIsSettingsOpen,
setPendingComment,
selectedAddress, setSelectedAddress,
setSelectedReply,
selectedStyle,
setSelectedThread,
selectedTitle, setSelectedTitle,
@@ -476,7 +477,10 @@ const Board = () => {
&nbsp;
<span key={`pn-${thread.cid}`} className="post-number">
<Link to="" key={`pl1-${thread.cid}`} onClick={() => {}} title="Link to this post">c/</Link>
<button id="reply-button" style={{ all: 'unset', cursor: 'pointer' }} key={`pl2-${thread.cid}`} onClick={() => setIsReplyOpen(true)} title="Reply to this post">{thread.shortCid}</button>
<button id="reply-button" style={{ all: 'unset', cursor: 'pointer' }} key={`pl2-${thread.cid}`}
onClick={() => {
setIsReplyOpen(true); setSelectedReply(thread.shortCid);
}} title="Reply to this post">{thread.shortCid}</button>
&nbsp;
<span key={`rl1-${thread.cid}`}>&nbsp;
[
@@ -566,7 +570,10 @@ const Board = () => {
&nbsp;
<span key={`pn-${reply.cid}`} className="post-number">
<Link to="" key={`pl1-${reply.cid}`} onClick={() => {}} title="Link to this post">c/</Link>
<button id="reply-button" style={{ all: 'unset', cursor: 'pointer' }} key={`pl2-${reply.cid}`} onClick={() => setIsReplyOpen(true)} title="Reply to this post">{reply.shortCid}</button>
<button id="reply-button" style={{ all: 'unset', cursor: 'pointer' }} key={`pl2-${reply.cid}`}
onClick={() => {
setIsReplyOpen(true); setSelectedReply(reply.shortCid);
}} title="Reply to this post">{reply.shortCid}</button>
</span>&nbsp;
<button key={`pmb-${reply.cid}`} className="post-menu-button" onClick={() => {}} title="Post menu" style={{ all: 'unset', cursor: 'pointer' }} data-cmd="post-menu"></button>
<div id="backlink-id" className="backlink">
@@ -706,7 +713,9 @@ const Board = () => {
{getDate(thread.timestamp)}
&nbsp;
<Link to="" key={`mob-no-${thread.cid}`} onClick={() => {}} title="Link to this post">c/</Link>
<button id="reply-button" style={{ all: 'unset', cursor: 'pointer' }} key={`mob-no2-${thread.cid}`} onClick={() => setIsReplyOpen(true)} title="Reply to this post">{thread.shortCid}</button>
<button id="reply-button" style={{ all: 'unset', cursor: 'pointer' }} key={`mob-no2-${thread.cid}`} onClick={() => {
setIsReplyOpen(true); setSelectedReply(thread.shortCid);
}} title="Reply to this post">{thread.shortCid}</button>
</span>
</div>
{thread.link ? (
@@ -800,7 +809,9 @@ const Board = () => {
<span key={`mob-dt-${reply.cid}`} className="date-time-mobile">
{getDate(reply.timestamp)}&nbsp;
<Link to="" key={`mob-pl1-${reply.cid}`} onClick={() => {}} title="Link to this post">c/</Link>
<button id="reply-button" style={{ all: 'unset', cursor: 'pointer' }} key={`mob-pl2-${reply.cid}`} onClick={() => setIsReplyOpen(true)} title="Reply to this post">{reply.shortCid}</button>
<button id="reply-button" style={{ all: 'unset', cursor: 'pointer' }} key={`mob-pl2-${reply.cid}`} onClick={() => {
setIsReplyOpen(true); setSelectedReply(reply.shortCid);
}} title="Reply to this post">{reply.shortCid}</button>
</span>
</div>
{reply.link ? (
-1
View File
@@ -95,7 +95,6 @@ const Thread = () => {
const onChallenge = async (challenges, comment) => {
console.log(comment);
setPendingComment(comment);
let challengeAnswers = [];