144 lines
4.8 KiB
JavaScript
144 lines
4.8 KiB
JavaScript
import { TextField } from "@mui/material";
|
|
import PropTypes from "prop-types";
|
|
import React, { Component } from "react";
|
|
// import "./captcha.css";
|
|
|
|
function getRandomInt(min, max) {
|
|
min = Math.ceil(min);
|
|
max = Math.floor(max);
|
|
return Math.floor(Math.random() * (max - min)) + min;
|
|
}
|
|
|
|
class Captcha extends Component {
|
|
state = {
|
|
solution: getRandomInt(111111, 999999),
|
|
input: "",
|
|
};
|
|
|
|
componentDidMount = () => {
|
|
this.drawCaptcha();
|
|
// this.props.captchaSolution(this.state.solution.toString());
|
|
};
|
|
|
|
drawCaptcha = () => {
|
|
const { solution } = this.state;
|
|
const { width, height } = this.canvas;
|
|
const ctx = this.canvas.getContext("2d");
|
|
ctx.clearRect(0, 0, width, height);
|
|
ctx.font = "40px serif";
|
|
ctx.textAlign = "center";
|
|
ctx.textBaseline = "middle";
|
|
ctx.fillText(solution, width / 2, height / 2 + 3);
|
|
ctx.strokeStyle = "#000000";
|
|
ctx.beginPath();
|
|
ctx.moveTo(getRandomInt(5, 20), getRandomInt(5, 20));
|
|
ctx.lineTo(width - getRandomInt(5, 20), height - getRandomInt(5, 20));
|
|
ctx.stroke();
|
|
ctx.moveTo(getRandomInt(5, 20), height - getRandomInt(5, 20));
|
|
ctx.lineTo(width - getRandomInt(5, 20), getRandomInt(5, 20));
|
|
ctx.stroke();
|
|
ctx.closePath();
|
|
this.canvas.style.backgroundColor = "transparent";
|
|
};
|
|
|
|
refresh = () => {
|
|
this.setState(
|
|
{
|
|
solution: getRandomInt(111111, 999999),
|
|
input: "",
|
|
},
|
|
this.drawCaptcha
|
|
);
|
|
};
|
|
|
|
playAudio = () => {
|
|
const { solution } = this.state;
|
|
let audio = new SpeechSynthesisUtterance(
|
|
solution.toString().split("").join(" ")
|
|
);
|
|
audio.rate = 0.25;
|
|
window.speechSynthesis.speak(audio);
|
|
};
|
|
|
|
handleChange = (e) => {
|
|
const { onChange } = this.props;
|
|
const { solution } = this.state;
|
|
this.setState({ input: e.target.value });
|
|
onChange(e.target.value === solution.toString());
|
|
};
|
|
|
|
render() {
|
|
const { input } = this.state;
|
|
return (
|
|
<div className="rnc">
|
|
<div className="rnc-row">
|
|
<canvas
|
|
ref={(el) => (this.canvas = el)}
|
|
width={200}
|
|
height={50}
|
|
className="rnc-canvas"
|
|
data-testid="captcha-canvas"
|
|
/>
|
|
<div className="rnc-column">
|
|
<button
|
|
type="button"
|
|
aria-label="get new captcha"
|
|
onClick={this.refresh}
|
|
className="rnc-button"
|
|
data-testid="captcha-refresh"
|
|
tabIndex={-1}
|
|
>
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
<g data-name="Layer 2">
|
|
<g data-name="refresh">
|
|
<rect width="24" height="24" opacity="0" />
|
|
<path d="M20.3 13.43a1 1 0 0 0-1.25.65A7.14 7.14 0 0 1 12.18 19 7.1 7.1 0 0 1 5 12a7.1 7.1 0 0 1 7.18-7 7.26 7.26 0 0 1 4.65 1.67l-2.17-.36a1 1 0 0 0-1.15.83 1 1 0 0 0 .83 1.15l4.24.7h.17a1 1 0 0 0 .34-.06.33.33 0 0 0 .1-.06.78.78 0 0 0 .2-.11l.09-.11c0-.05.09-.09.13-.15s0-.1.05-.14a1.34 1.34 0 0 0 .07-.18l.75-4a1 1 0 0 0-2-.38l-.27 1.45A9.21 9.21 0 0 0 12.18 3 9.1 9.1 0 0 0 3 12a9.1 9.1 0 0 0 9.18 9A9.12 9.12 0 0 0 21 14.68a1 1 0 0 0-.7-1.25z" />
|
|
</g>
|
|
</g>
|
|
</svg>
|
|
</button>
|
|
<button
|
|
type="button"
|
|
aria-label="play audio"
|
|
onClick={this.playAudio}
|
|
className="rnc-button"
|
|
data-testid="captcha-audio"
|
|
tabIndex={-1}
|
|
>
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
<g data-name="Layer 2">
|
|
<g data-name="volume-up">
|
|
<rect width="24" height="24" opacity="0" />
|
|
<path d="M18.28 8.37a1 1 0 1 0-1.56 1.26 4 4 0 0 1 0 4.74A1 1 0 0 0 17.5 16a1 1 0 0 0 .78-.37 6 6 0 0 0 0-7.26z" />
|
|
<path d="M19.64 5.23a1 1 0 1 0-1.28 1.54A6.8 6.8 0 0 1 21 12a6.8 6.8 0 0 1-2.64 5.23 1 1 0 0 0-.13 1.41A1 1 0 0 0 19 19a1 1 0 0 0 .64-.23A8.75 8.75 0 0 0 23 12a8.75 8.75 0 0 0-3.36-6.77z" />
|
|
<path d="M15 3.12a1 1 0 0 0-1 0L7.52 7.57h-5a1 1 0 0 0-1 1v6.86a1 1 0 0 0 1 1h5l6.41 4.4a1.06 1.06 0 0 0 .57.17 1 1 0 0 0 1-1V4a1 1 0 0 0-.5-.88zm-1.47 15L8.4 14.6a1 1 0 0 0-.57-.17H3.5V9.57h4.33a1 1 0 0 0 .57-.17l5.1-3.5z" />
|
|
</g>
|
|
</g>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<TextField
|
|
id="captcha"
|
|
label="کد امنیتی"
|
|
variant="outlined"
|
|
value={input}
|
|
onChange={this.handleChange}
|
|
sx={{ width: "100%" }}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|
|
}
|
|
|
|
Captcha.defaultProps = {
|
|
placeholder: "کد امنیتی را وارد کنید...",
|
|
};
|
|
|
|
Captcha.propTypes = {
|
|
onChange: PropTypes.func.isRequired,
|
|
placeholder: PropTypes.string,
|
|
};
|
|
|
|
export default Captcha;
|