diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts
index 7192eb81cc..f485d753c5 100644
--- a/src/@types/global.d.ts
+++ b/src/@types/global.d.ts
@@ -90,6 +90,7 @@ declare global {
mxUIStore: UIStore;
mxSetupEncryptionStore?: SetupEncryptionStore;
mxRoomScrollStateStore?: RoomScrollStateStore;
+ mxOnRecaptchaLoaded?: () => void;
}
interface Document {
@@ -114,7 +115,7 @@ declare global {
}
interface StorageEstimate {
- usageDetails?: {[key: string]: number};
+ usageDetails?: { [key: string]: number };
}
interface HTMLAudioElement {
@@ -185,4 +186,19 @@ declare global {
parameterDescriptors?: AudioParamDescriptor[];
}
);
+
+ // eslint-disable-next-line no-var
+ var grecaptcha:
+ | undefined
+ | {
+ reset: (id: string) => void;
+ render: (
+ divId: string,
+ options: {
+ sitekey: string;
+ callback: () => void;
+ }
+ ) => string;
+ isReady: () => boolean;
+ };
}
diff --git a/src/components/views/auth/CaptchaForm.js b/src/components/views/auth/CaptchaForm.tsx
similarity index 73%
rename from src/components/views/auth/CaptchaForm.js
rename to src/components/views/auth/CaptchaForm.tsx
index bea4f89f53..878cedc13f 100644
--- a/src/components/views/auth/CaptchaForm.js
+++ b/src/components/views/auth/CaptchaForm.tsx
@@ -15,55 +15,56 @@ limitations under the License.
*/
import React, { createRef } from 'react';
-import PropTypes from 'prop-types';
import { _t } from '../../../languageHandler';
import CountlyAnalytics from "../../../CountlyAnalytics";
import { replaceableComponent } from "../../../utils/replaceableComponent";
const DIV_ID = 'mx_recaptcha';
+interface ICaptchaFormProps {
+ sitePublicKey: string
+ onCaptchaResponse: () => void
+}
+
+interface ICaptchaFormState {
+ errorText: string | null
+
+}
+
/**
* A pure UI component which displays a captcha form.
*/
@replaceableComponent("views.auth.CaptchaForm")
-export default class CaptchaForm extends React.Component {
- static propTypes = {
- sitePublicKey: PropTypes.string,
-
- // called with the captcha response
- onCaptchaResponse: PropTypes.func,
- };
-
+export default class CaptchaForm extends React.Component {
static defaultProps = {
- onCaptchaResponse: () => {},
+ onCaptchaResponse: () => { },
};
- constructor(props) {
+ private _captchaWidgetId: string | null = null;
+ private _recaptchaContainer: React.RefObject = createRef();
+
+ state = {
+ errorText: null,
+ };
+
+ constructor(props: ICaptchaFormProps) {
super(props);
- this.state = {
- errorText: null,
- };
-
- this._captchaWidgetId = null;
-
- this._recaptchaContainer = createRef();
-
CountlyAnalytics.instance.track("onboarding_grecaptcha_begin");
}
componentDidMount() {
// Just putting a script tag into the returned jsx doesn't work, annoyingly,
// so we do this instead.
- if (global.grecaptcha) {
+ if (this.isRecaptchaReady()) {
// already loaded
this._onCaptchaLoaded();
} else {
console.log("Loading recaptcha script...");
- window.mx_on_recaptcha_loaded = () => {this._onCaptchaLoaded();};
+ window.mxOnRecaptchaLoaded = () => { this._onCaptchaLoaded(); };
const scriptTag = document.createElement('script');
scriptTag.setAttribute(
- 'src', `https://www.recaptcha.net/recaptcha/api.js?onload=mx_on_recaptcha_loaded&render=explicit`,
+ 'src', `https://www.recaptcha.net/recaptcha/api.js?onload=mxOnRecaptchaLoaded&render=explicit`,
);
this._recaptchaContainer.current.appendChild(scriptTag);
}
@@ -73,8 +74,15 @@ export default class CaptchaForm extends React.Component {
this._resetRecaptcha();
}
- _renderRecaptcha(divId) {
- if (!global.grecaptcha) {
+ // Borrowed directly from: https://github.com/codeep/react-recaptcha-google/commit/e118fa5670fa268426969323b2e7fe77698376ba
+ private isRecaptchaReady() {
+ return typeof window !== "undefined" &&
+ typeof global.grecaptcha !== "undefined" &&
+ typeof global.grecaptcha.render === 'function';
+ }
+
+ private _renderRecaptcha(divId) {
+ if (!this.isRecaptchaReady()) {
console.error("grecaptcha not loaded!");
throw new Error("Recaptcha did not load successfully");
}
@@ -84,7 +92,7 @@ export default class CaptchaForm extends React.Component {
console.error("No public key for recaptcha!");
throw new Error(
"This server has not supplied enough information for Recaptcha "
- + "authentication");
+ + "authentication");
}
console.info("Rendering to %s", divId);
@@ -94,13 +102,13 @@ export default class CaptchaForm extends React.Component {
});
}
- _resetRecaptcha() {
+ private _resetRecaptcha() {
if (this._captchaWidgetId !== null) {
global.grecaptcha.reset(this._captchaWidgetId);
}
}
- _onCaptchaLoaded() {
+ private _onCaptchaLoaded() {
console.log("Loaded recaptcha script.");
try {
this._renderRecaptcha(DIV_ID);
@@ -122,7 +130,7 @@ export default class CaptchaForm extends React.Component {
if (this.state.errorText) {
error = (
- { this.state.errorText }
+ {this.state.errorText}
);
}
@@ -133,7 +141,7 @@ export default class CaptchaForm extends React.Component {
"This homeserver would like to make sure you are not a robot.",
)}
- { error }
+ {error}
);
}