added functionality to captcha modal

This commit is contained in:
plebbitor
2023-04-07 17:47:51 +02:00
parent 664533d465
commit 73ed32c848
3 changed files with 89 additions and 33 deletions
+69 -19
View File
@@ -1,4 +1,4 @@
import React, { useRef } from 'react';
import React, { useEffect, useState, useRef } from 'react';
import useAppStore from '../useAppStore';
import Modal from 'react-modal';
import styled from 'styled-components';
@@ -42,7 +42,7 @@ const StyledModal = styled(Modal)`
border: none;
}
#name {
#field {
border: 1px solid #aaa;
font-family: Arial, Helvetica, sans-serif;
font-size: 10pt;
@@ -85,10 +85,10 @@ const StyledModal = styled(Modal)`
display: block;
}
#next {
#nav {
float: right;
margin: 0;
width: 75px;
width: 40px;
}
${({ selectedStyle }) => {
@@ -193,7 +193,7 @@ const StyledModal = styled(Modal)`
background-image: url(/assets/buttons/cross_dark.png);
}
#name {
#field {
background-color: #282a2e;
color: #c5c8c6;
border: 1px solid #515151;
@@ -245,13 +245,35 @@ const StyledModal = styled(Modal)`
`;
const CaptchaModal = ({ isOpen, closeModal, captchaImage }) => {
const { setCaptchaResponse } = useAppStore(state => state);
const selectedStyle = useAppStore(state => state.selectedStyle);
const CaptchaModal = ({ isOpen, closeModal }) => {
const {
challengesArray,
pendingComment,
selectedStyle,
setCaptchaResponse,
} = useAppStore(state => state);
const [imageSources, setImageSources] = useState([]);
const [currentChallengeIndex, setCurrentChallengeIndex] = useState(0);
const [totalChallenges, setTotalChallenges] = useState(0);
const responseRef = useRef();
const nodeRef = useRef(null);
useEffect(() => {
if (challengesArray) {
const challenges = challengesArray.challenges;
const decryptedChallenges = [];
for (let i = 0; i < challenges.length; i++) {
const imageString = challenges[i].challenge;
const imageSource = `data:image/png;base64,${imageString}`;
decryptedChallenges.push(imageSource);
}
setImageSources(decryptedChallenges);
setTotalChallenges(decryptedChallenges.length);
}
}, [challengesArray]);
const handleKeyDown = (event) => {
if (event.key === "Enter") {
@@ -261,7 +283,6 @@ const CaptchaModal = ({ isOpen, closeModal, captchaImage }) => {
}
};
return (
<StyledModal
isOpen={isOpen}
@@ -274,16 +295,37 @@ const CaptchaModal = ({ isOpen, closeModal, captchaImage }) => {
<Draggable handle=".modal-header" nodeRef={nodeRef}>
<div className="modal-content" ref={nodeRef}>
<div className="modal-header">
Challenges for
{pendingComment.parentCid ?
("Challenges for Reply c/" + pendingComment.cid) :
"Challenges for New Thread"}
<button className="icon" onClick={() => closeModal()} title="close" />
</div>
<div id="form">
<div>
<input id="name" type="text" placeholder="Name" disabled></input>
</div>
<div>
<textarea rows="4" placeholder="Comment" wrap="soft" disabled></textarea>
</div>
{pendingComment.displayName ? (
<div>
<input id="field" type="text" placeholder={pendingComment.displayName} disabled />
</div>
) : null}
{pendingComment.title ? (
<div>
<input id="field" type="text" placeholder={pendingComment.title} disabled />
</div>
) : null}
{pendingComment.content ? (
<div>
<textarea
rows="4"
placeholder={pendingComment.content || "Comment"}
wrap="soft"
disabled
/>
</div>
) : null}
{pendingComment.link ? (
<div>
<input id="field" type="text" placeholder={pendingComment.link} disabled />
</div>
) : null}
<div id="captcha-container">
<input
id="response"
@@ -293,11 +335,19 @@ const CaptchaModal = ({ isOpen, closeModal, captchaImage }) => {
ref={responseRef}
onKeyDown={handleKeyDown}
autoFocus />
<img src={captchaImage} alt="captcha" />
<img src={imageSources[currentChallengeIndex]} alt="captcha" />
</div>
<div>
<span>Challenge 1 of 3</span>
<button id="next">Next</button>
<span style={{lineHeight: '1.7'}}>
Challenge {currentChallengeIndex + 1} of {totalChallenges}
</span>
<button id="nav" onClick={() => {
setCurrentChallengeIndex((currentChallengeIndex + 1) % totalChallenges)
}
}>&gt;</button>
<button id="nav" onClick={()=> {
setCurrentChallengeIndex((currentChallengeIndex - 1 + totalChallenges) % totalChallenges)
}}>&lt;</button>
</div>
</div>
</div>
+8 -11
View File
@@ -24,8 +24,10 @@ import useSuccess from '../../hooks/useSuccess';
const Board = () => {
const {
captchaResponse, setCaptchaResponse,
setChallengesArray,
defaultSubplebbits,
isSettingsOpen, setIsSettingsOpen,
setPendingComment,
selectedAddress, setSelectedAddress,
selectedStyle,
setSelectedThread,
@@ -41,7 +43,6 @@ const Board = () => {
const [isCaptchaOpen, setIsCaptchaOpen] = useState(false);
const [isReplyOpen, setIsReplyOpen] = useState(false);
const [captchaImage, setCaptchaImage] = useState('');
const navigate = useNavigate();
const [prevScrollPos, setPrevScrollPos] = useState(0);
const [visible, setVisible] = useState(true);
@@ -55,10 +56,6 @@ const Board = () => {
useSuccess(successMessage, [successMessage]);
// useEffect(() => {
// console.log(selectedFeed[3]);
// }, [selectedFeed]);
// temporary title from JSON, gets subplebbitAddress from URL
useEffect(() => {
setSelectedAddress(subplebbitAddress);
@@ -110,7 +107,8 @@ const Board = () => {
const onChallenge = async (challenges, comment) => {
console.log("onChallenge:", challenges, comment)
setPendingComment(comment);
let challengeAnswers = [];
try {
challengeAnswers = await getChallengeAnswersFromUser(challenges)
@@ -150,6 +148,8 @@ const Board = () => {
const getChallengeAnswersFromUser = async (challenges) => {
setChallengesArray(challenges);
return new Promise((resolve, reject) => {
const imageString = challenges?.challenges[0].challenge;
const imageSource = `data:image/png;base64,${imageString}`;
@@ -158,11 +158,9 @@ const Board = () => {
challengeImg.onload = () => {
setIsCaptchaOpen(true);
setCaptchaImage(imageSource);
const handleKeyDown = (event) => {
if (event.key === 'Enter') {
setCaptchaImage('');
resolve(captchaResponse);
setIsCaptchaOpen(false);
document.removeEventListener('keydown', handleKeyDown);
@@ -175,7 +173,7 @@ const Board = () => {
};
challengeImg.onerror = () => {
reject(setErrorMessage('Could not load challenge image'));
reject(setErrorMessage('Could not load challenges'));
};
});
};
@@ -213,8 +211,7 @@ const Board = () => {
<CaptchaModal
selectedStyle={selectedStyle}
isOpen={isCaptchaOpen}
closeModal={() => setIsCaptchaOpen(false)}
captchaImage={captchaImage} />
closeModal={() => setIsCaptchaOpen(false)} />
<ReplyModal
selectedStyle={selectedStyle}
isOpen={isReplyOpen}
+12 -3
View File
@@ -1,9 +1,6 @@
import { create } from 'zustand';
const useAppStore = create((set) => ({
captchaResponse: '',
setCaptchaResponse: (response) => set({ captchaResponse: response }),
bodyStyle: JSON.parse(localStorage.getItem('bodyStyle')) || {
background: '#ffe url(/assets/fade.png) top repeat-x',
color: 'maroon',
@@ -14,11 +11,23 @@ const useAppStore = create((set) => ({
set(() => ({ bodyStyle }));
},
captchaResponse: '',
setCaptchaResponse: (response) => set({ captchaResponse: response }),
challengesArray: [],
setChallengesArray: (challengesArray) => set({ challengesArray }),
defaultSubplebbits: [],
setDefaultSubplebbits: (subplebbits) => set({ defaultSubplebbits: subplebbits }),
isSettingsOpen: false,
setIsSettingsOpen: (isOpen) => set({ isSettingsOpen: isOpen }),
pendingComment: '',
setPendingComment: (comment) => set({ pendingComment: comment }),
publishedComment: '',
setPublishedComment: (comment) => set({ publishedComment: comment }),
selectedAddress: '',
setSelectedAddress: (address) => set({ selectedAddress: address }),