@hcaptcha/react-native-hcaptcha
Version:
hCaptcha Library for React Native (both Android and iOS)
263 lines (250 loc) • 6.68 kB
JavaScript
import React, { PureComponent } from 'react';
import { Modal, SafeAreaView, StyleSheet, TouchableWithoutFeedback, View } from 'react-native';
import Hcaptcha from './Hcaptcha';
import PropTypes from 'prop-types';
import { clearJourneyEvents, disableJourneyConsumer, enableJourneyConsumer } from './journey';
export { initJourneyTracking, registerJourneyNavigationContainer } from './journey';
export { default as Hcaptcha } from './Hcaptcha';
class ConfirmHcaptcha extends PureComponent {
state = {
journeyStopped: false,
show: false,
};
hasJourneyConsumer = false;
getJourneyEnabled(props = this.props, state = this.state) {
return Boolean(props.userJourney && !state.journeyStopped);
}
componentDidMount() {
this.syncJourneyConsumer(false, this.getJourneyEnabled());
}
componentDidUpdate(prevProps, prevState) {
if (prevProps.userJourney !== this.props.userJourney && prevState.journeyStopped) {
this.setState({ journeyStopped: false });
return;
}
this.syncJourneyConsumer(
this.getJourneyEnabled(prevProps, prevState),
this.getJourneyEnabled()
);
}
componentWillUnmount() {
this.syncJourneyConsumer(this.getJourneyEnabled(), false);
}
syncJourneyConsumer(previousValue, nextValue) {
if (!previousValue && nextValue && !this.hasJourneyConsumer) {
enableJourneyConsumer();
this.hasJourneyConsumer = true;
} else if (previousValue && !nextValue && this.hasJourneyConsumer) {
disableJourneyConsumer();
this.hasJourneyConsumer = false;
}
}
stopEvents = () => {
if (this.hasJourneyConsumer) {
disableJourneyConsumer();
this.hasJourneyConsumer = false;
}
clearJourneyEvents();
this.setState({ journeyStopped: true });
};
show = () => {
this.setState({ show: true });
};
hide = (source) => {
const { onMessage } = this.props;
this.setState({ show: false });
if (source) { // if source === undefined => called by the user
onMessage({ nativeEvent: { data: 'cancel' } });
}
};
renderCaptcha() {
let {
size,
siteKey,
baseUrl,
languageCode,
orientation,
onMessage,
showLoading,
closableLoading,
loadingIndicatorColor,
backgroundColor,
theme,
rqdata,
sentry,
jsSrc,
endpoint,
reportapi,
assethost,
imghost,
host,
debug,
useSafeAreaView,
phonePrefix,
phoneNumber,
verifyParams,
} = this.props;
const WrapperComponent = useSafeAreaView === false ? View : SafeAreaView;
const journeyEnabled = this.getJourneyEnabled();
return (
<WrapperComponent style={styles.wrapper}>
<Hcaptcha
url={baseUrl}
size={size}
siteKey={siteKey}
onMessage={onMessage}
languageCode={languageCode}
showLoading={showLoading}
closableLoading={closableLoading}
loadingIndicatorColor={loadingIndicatorColor}
backgroundColor={backgroundColor}
theme={theme}
rqdata={rqdata}
sentry={sentry}
jsSrc={jsSrc}
endpoint={endpoint}
reportapi={reportapi}
assethost={assethost}
imghost={imghost}
host={host}
orientation={orientation}
debug={debug}
phonePrefix={phonePrefix}
phoneNumber={phoneNumber}
userJourney={journeyEnabled}
verifyParams={verifyParams}
_journeyManagedExternally={true}
/>
</WrapperComponent>
);
}
render() {
let { show } = this.state;
let {
passiveSiteKey,
backgroundColor,
hasBackdrop,
} = this.props;
if (!show) {
return null;
}
if (passiveSiteKey) {
return (
<View pointerEvents="none" style={styles.passiveContainer}>
{this.renderCaptcha()}
</View>
);
}
return (
<Modal
animationType="fade"
onRequestClose={() => this.hide('back_button')}
transparent
visible={show}
>
<View style={styles.modal}>
{hasBackdrop ? (
<TouchableWithoutFeedback
onPress={() => this.hide('backdrop')}
testID="confirm-hcaptcha-backdrop"
>
<View style={[styles.backdrop, { backgroundColor }]} />
</TouchableWithoutFeedback>
) : null}
<View style={styles.modalContent}>
{this.renderCaptcha()}
</View>
</View>
</Modal>
);
}
}
const styles = StyleSheet.create({
text: {
fontSize: 15,
fontWeight: 'bold',
color: '#fff',
textAlign: 'center',
marginTop: 10,
},
backdrop: {
...StyleSheet.absoluteFillObject,
},
modal: {
flex: 1,
margin: 0,
},
modalContent: {
flex: 1,
},
passiveContainer: {
height: 1,
left: 0,
opacity: 0,
position: 'absolute',
top: 0,
width: 1,
},
wrapper: {
flex: 1,
justifyContent: 'center',
overflow: 'hidden',
},
});
ConfirmHcaptcha.propTypes = {
size: PropTypes.string,
siteKey: PropTypes.string.isRequired,
passiveSiteKey: PropTypes.bool,
baseUrl: PropTypes.string,
onMessage: PropTypes.func.isRequired,
languageCode: PropTypes.string,
orientation: PropTypes.string,
backgroundColor: PropTypes.string,
showLoading: PropTypes.bool,
closableLoading: PropTypes.bool,
loadingIndicatorColor: PropTypes.string,
theme: PropTypes.string,
rqdata: PropTypes.string,
sentry: PropTypes.bool,
jsSrc: PropTypes.string,
endpoint: PropTypes.string,
reportapi: PropTypes.string,
assethost: PropTypes.string,
imghost: PropTypes.string,
host: PropTypes.string,
hasBackdrop: PropTypes.bool,
debug: PropTypes.object,
phonePrefix: PropTypes.string,
phoneNumber: PropTypes.string,
userJourney: PropTypes.bool,
verifyParams: PropTypes.shape({
phoneNumber: PropTypes.string,
phonePrefix: PropTypes.string,
rqdata: PropTypes.string,
}),
};
ConfirmHcaptcha.defaultProps = {
size: 'invisible',
passiveSiteKey: false,
showLoading: false,
closableLoading: false,
orientation: 'portrait',
backgroundColor: 'rgba(0, 0, 0, 0.3)',
loadingIndicatorColor: null,
theme: 'light',
rqdata: null,
sentry: false,
jsSrc: 'https://js.hcaptcha.com/1/api.js',
endpoint: undefined,
reportapi: undefined,
assethost: undefined,
imghost: undefined,
host: undefined,
hasBackdrop: true,
debug: {},
phonePrefix: null,
phoneNumber: null,
userJourney: false,
verifyParams: undefined,
};
export default ConfirmHcaptcha;