From 9de5ebd4def72816fb5afa0f4546df6ea2a69a52 Mon Sep 17 00:00:00 2001
From: Dariusz Niemczyk
Date: Mon, 19 Jul 2021 15:41:44 +0200
Subject: [PATCH 1/5] Fix grecaptcha throwing useless error sometimes
---
src/@types/global.d.ts | 18 ++++-
.../auth/{CaptchaForm.js => CaptchaForm.tsx} | 66 +++++++++++--------
2 files changed, 54 insertions(+), 30 deletions(-)
rename src/components/views/auth/{CaptchaForm.js => CaptchaForm.tsx} (73%)
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}
);
}
From c2394b9161b08761a9abe38fb9a313c0b6aee4c9 Mon Sep 17 00:00:00 2001
From: Dariusz Niemczyk
Date: Mon, 19 Jul 2021 16:27:39 +0200
Subject: [PATCH 2/5] Fix styling comments
---
src/@types/global.d.ts | 2 +-
src/components/views/auth/CaptchaForm.tsx | 48 +++++++++++------------
2 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts
index f485d753c5..46c23ff8d8 100644
--- a/src/@types/global.d.ts
+++ b/src/@types/global.d.ts
@@ -196,7 +196,7 @@ declare global {
divId: string,
options: {
sitekey: string;
- callback: () => void;
+ callback: (response: string) => void;
}
) => string;
isReady: () => boolean;
diff --git a/src/components/views/auth/CaptchaForm.tsx b/src/components/views/auth/CaptchaForm.tsx
index 878cedc13f..749d6dbd39 100644
--- a/src/components/views/auth/CaptchaForm.tsx
+++ b/src/components/views/auth/CaptchaForm.tsx
@@ -22,12 +22,12 @@ import { replaceableComponent } from "../../../utils/replaceableComponent";
const DIV_ID = 'mx_recaptcha';
interface ICaptchaFormProps {
- sitePublicKey: string
- onCaptchaResponse: () => void
+ sitePublicKey: string;
+ onCaptchaResponse: (response: string) => void;
}
interface ICaptchaFormState {
- errorText: string | null
+ errorText: string | null;
}
@@ -37,19 +37,19 @@ interface ICaptchaFormState {
@replaceableComponent("views.auth.CaptchaForm")
export default class CaptchaForm extends React.Component {
static defaultProps = {
- onCaptchaResponse: () => { },
+ onCaptchaResponse: () => {},
};
- private _captchaWidgetId: string | null = null;
- private _recaptchaContainer: React.RefObject = createRef();
-
- state = {
- errorText: null,
- };
+ private captchaWidgetId: string | null = null;
+ private recaptchaContainer = createRef();
constructor(props: ICaptchaFormProps) {
super(props);
+ this.state = {
+ errorText: null,
+ };
+
CountlyAnalytics.instance.track("onboarding_grecaptcha_begin");
}
@@ -58,30 +58,30 @@ export default class CaptchaForm extends React.Component { this._onCaptchaLoaded(); };
+ window.mxOnRecaptchaLoaded = () => { this.onCaptchaLoaded(); };
const scriptTag = document.createElement('script');
scriptTag.setAttribute(
'src', `https://www.recaptcha.net/recaptcha/api.js?onload=mxOnRecaptchaLoaded&render=explicit`,
);
- this._recaptchaContainer.current.appendChild(scriptTag);
+ this.recaptchaContainer.current.appendChild(scriptTag);
}
}
componentWillUnmount() {
- this._resetRecaptcha();
+ this.resetRecaptcha();
}
// Borrowed directly from: https://github.com/codeep/react-recaptcha-google/commit/e118fa5670fa268426969323b2e7fe77698376ba
- private isRecaptchaReady() {
+ private isRecaptchaReady(): boolean {
return typeof window !== "undefined" &&
typeof global.grecaptcha !== "undefined" &&
typeof global.grecaptcha.render === 'function';
}
- private _renderRecaptcha(divId) {
+ private renderRecaptcha(divId: string) {
if (!this.isRecaptchaReady()) {
console.error("grecaptcha not loaded!");
throw new Error("Recaptcha did not load successfully");
@@ -96,22 +96,22 @@ export default class CaptchaForm extends React.Component
+
{_t(
"This homeserver would like to make sure you are not a robot.",
)}
- {error}
+ { error }
);
}
From 97d490c1b63845f2ee81f11573f37aff7ae2feda Mon Sep 17 00:00:00 2001
From: Dariusz Niemczyk <3636685+Palid@users.noreply.github.com>
Date: Mon, 19 Jul 2021 16:28:30 +0200
Subject: [PATCH 3/5] Update src/components/views/auth/CaptchaForm.tsx
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
---
src/components/views/auth/CaptchaForm.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/views/auth/CaptchaForm.tsx b/src/components/views/auth/CaptchaForm.tsx
index 749d6dbd39..4934382fdb 100644
--- a/src/components/views/auth/CaptchaForm.tsx
+++ b/src/components/views/auth/CaptchaForm.tsx
@@ -130,7 +130,7 @@ export default class CaptchaForm extends React.Component
- {this.state.errorText}
+ { this.state.errorText }
);
}
From 9e9992078baa2756e2e26f22106afbd8f3119828 Mon Sep 17 00:00:00 2001
From: Dariusz Niemczyk <3636685+Palid@users.noreply.github.com>
Date: Mon, 19 Jul 2021 16:34:07 +0200
Subject: [PATCH 4/5] Update src/@types/global.d.ts
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
---
src/@types/global.d.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts
index 46c23ff8d8..8bf6329f80 100644
--- a/src/@types/global.d.ts
+++ b/src/@types/global.d.ts
@@ -197,7 +197,7 @@ declare global {
options: {
sitekey: string;
callback: (response: string) => void;
- }
+ },
) => string;
isReady: () => boolean;
};
From 5acc7fe8d4e8394a82f39fbe17a0ee95106415f2 Mon Sep 17 00:00:00 2001
From: Dariusz Niemczyk
Date: Mon, 19 Jul 2021 16:49:35 +0200
Subject: [PATCH 5/5] Make `errorText` properly optional instead of null
---
src/components/views/auth/CaptchaForm.tsx | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/components/views/auth/CaptchaForm.tsx b/src/components/views/auth/CaptchaForm.tsx
index 4934382fdb..14237b2404 100644
--- a/src/components/views/auth/CaptchaForm.tsx
+++ b/src/components/views/auth/CaptchaForm.tsx
@@ -27,7 +27,7 @@ interface ICaptchaFormProps {
}
interface ICaptchaFormState {
- errorText: string | null;
+ errorText?: string;
}
@@ -40,14 +40,14 @@ export default class CaptchaForm extends React.Component {},
};
- private captchaWidgetId: string | null = null;
+ private captchaWidgetId?: string;
private recaptchaContainer = createRef();
constructor(props: ICaptchaFormProps) {
super(props);
this.state = {
- errorText: null,
+ errorText: undefined,
};
CountlyAnalytics.instance.track("onboarding_grecaptcha_begin");