From 642282f0494d512053a734f48dd072fb976161f8 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Tue, 28 Apr 2020 11:57:40 -0500 Subject: [PATCH] Refactor CaptchaField --- .../features/auth_login/components/captcha.js | 96 +++++++++++++++++++ .../components/registration_form.js | 48 +++------- 2 files changed, 111 insertions(+), 33 deletions(-) create mode 100644 app/gabsocial/features/auth_login/components/captcha.js diff --git a/app/gabsocial/features/auth_login/components/captcha.js b/app/gabsocial/features/auth_login/components/captcha.js new file mode 100644 index 000000000..9542111b7 --- /dev/null +++ b/app/gabsocial/features/auth_login/components/captcha.js @@ -0,0 +1,96 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { connect } from 'react-redux'; +import { Map as ImmutableMap } from 'immutable'; +import { fetchCaptcha } from 'gabsocial/actions/auth'; +import { TextInput } from 'gabsocial/features/forms'; + +const noOp = () => {}; + +export default @connect() +class CaptchaField extends React.Component { + + static propTypes = { + onChange: PropTypes.func, + onFetch: PropTypes.func, + onFetchFail: PropTypes.func, + dispatch: PropTypes.func, + refreshInterval: PropTypes.number, + } + + static defaultProps = { + onChange: noOp, + onFetch: noOp, + onFetchFail: noOp, + refreshInterval: 5*60*1000, // 5 minutes, Pleroma default + } + + state = { + captcha: ImmutableMap(), + } + + setRefreshTimeout = () => { + const { refreshInterval } = this.props; + if (refreshInterval) { + const refreshTimeout = setTimeout(this.fetchCaptcha, refreshInterval); + this.setState({ refreshTimeout }); + } + } + + clearRefreshTimeout = () => { + clearTimeout(this.state.refreshTimeout); + } + + fetchCaptcha = () => { + const { dispatch, onFetch, onFetchFail } = this.props; + dispatch(fetchCaptcha()).then(response => { + const captcha = ImmutableMap(response.data); + this.setState({ captcha }); + onFetch(captcha); + }).catch(error => { + onFetchFail(error); + }); + this.setRefreshTimeout(); // Refresh periodically + } + + componentWillMount() { + this.fetchCaptcha(); + } + + componentWillUnmount() { + this.clearRefreshTimeout(); + } + + render() { + const { captcha } = this.state; + const { onChange } = this.props; + + switch(captcha.get('type')) { + case 'native': + return ; + case 'none': + default: + return null; + } + } + +} + +const NativeCaptchaField = ({ captcha, onChange }) => ( +
+ captcha + +
+); + +NativeCaptchaField.propTypes = { + captcha: ImmutablePropTypes.map.isRequired, + onChange: PropTypes.func, +}; diff --git a/app/gabsocial/features/landing_page/components/registration_form.js b/app/gabsocial/features/landing_page/components/registration_form.js index c249a4a48..5bf19ef9c 100644 --- a/app/gabsocial/features/landing_page/components/registration_form.js +++ b/app/gabsocial/features/landing_page/components/registration_form.js @@ -9,7 +9,8 @@ import { TextInput, Checkbox, } from 'gabsocial/features/forms'; -import { register, fetchCaptcha } from 'gabsocial/actions/auth'; +import { register } from 'gabsocial/actions/auth'; +import CaptchaField from 'gabsocial/features/auth_login/components/captcha'; import { Map as ImmutableMap } from 'immutable'; const mapStateToProps = (state, props) => ({ @@ -24,16 +25,11 @@ class RegistrationForm extends ImmutablePureComponent { } state = { - captcha: ImmutableMap(), captchaLoading: true, submissionLoading: false, params: ImmutableMap(), } - componentWillMount() { - this.fetchCaptcha(); - } - setParams = map => { this.setState({ params: this.state.params.merge(ImmutableMap(map)) }); } @@ -50,34 +46,16 @@ class RegistrationForm extends ImmutablePureComponent { this.props.dispatch(register(this.state.params.toJS())); } - fetchCaptcha = () => { - this.props.dispatch(fetchCaptcha()).then(response => { - const captcha = ImmutableMap(response.data); - this.setState({ captcha: captcha, captchaLoading: false }); - this.setParams({ - captcha_token: captcha.get('token'), - captcha_answer_data: captcha.get('answer_data'), - }); - }).catch(error => console.error(error)); - setTimeout(this.fetchCaptcha, 5*60*100); // Captcha invalidates after 5 minutes + onFetchCaptcha = captcha => { + this.setState({ captchaLoading: false }); + this.setParams({ + captcha_token: captcha.get('token'), + captcha_answer_data: captcha.get('answer_data'), + }); } - getCaptchaElem = () => { - const { captcha } = this.state; - if (captcha.get('type') !== 'native') return null; - - return ( -
- captcha - -
- ); + onFetchCaptchaFail = error => { + this.setState({ captchaLoading: false }); } render() { @@ -123,7 +101,11 @@ class RegistrationForm extends ImmutablePureComponent { required /> - {this.getCaptchaElem()} +
I agree to the Terms of Service.}