TypeScriptify useRecaptcha
This commit is contained in:
parent
9a44790450
commit
af74228f8e
3 changed files with 34 additions and 33 deletions
|
|
@ -8,7 +8,7 @@
|
||||||
"build-storybook": "build-storybook",
|
"build-storybook": "build-storybook",
|
||||||
"prettier:check": "prettier -c src",
|
"prettier:check": "prettier -c src",
|
||||||
"prettier:format": "prettier -w src",
|
"prettier:format": "prettier -w src",
|
||||||
"lint:js": "eslint --max-warnings 2 src",
|
"lint:js": "eslint --max-warnings 0 src",
|
||||||
"lint:types": "tsc"
|
"lint:types": "tsc"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
"@react-stately/tree": "^3.2.0",
|
"@react-stately/tree": "^3.2.0",
|
||||||
"@sentry/react": "^6.13.3",
|
"@sentry/react": "^6.13.3",
|
||||||
"@sentry/tracing": "^6.13.3",
|
"@sentry/tracing": "^6.13.3",
|
||||||
|
"@types/grecaptcha": "^3.0.4",
|
||||||
"@use-gesture/react": "^10.2.11",
|
"@use-gesture/react": "^10.2.11",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
"color-hash": "^2.0.1",
|
"color-hash": "^2.0.1",
|
||||||
|
|
|
||||||
|
|
@ -14,52 +14,49 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { randomString } from "matrix-js-sdk/src/randomstring";
|
|
||||||
import { useEffect, useCallback, useRef, useState } from "react";
|
import { useEffect, useCallback, useRef, useState } from "react";
|
||||||
|
import { randomString } from "matrix-js-sdk/src/randomstring";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
mxOnRecaptchaLoaded: () => void;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const RECAPTCHA_SCRIPT_URL =
|
const RECAPTCHA_SCRIPT_URL =
|
||||||
"https://www.recaptcha.net/recaptcha/api.js?onload=mxOnRecaptchaLoaded&render=explicit";
|
"https://www.recaptcha.net/recaptcha/api.js?onload=mxOnRecaptchaLoaded&render=explicit";
|
||||||
|
|
||||||
export function useRecaptcha(sitekey) {
|
interface RecaptchaPromiseRef {
|
||||||
|
resolve: (response: string) => void;
|
||||||
|
reject: (error: Error) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useRecaptcha = (sitekey: string) => {
|
||||||
const [recaptchaId] = useState(() => randomString(16));
|
const [recaptchaId] = useState(() => randomString(16));
|
||||||
const promiseRef = useRef();
|
const promiseRef = useRef<RecaptchaPromiseRef>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!sitekey) {
|
if (!sitekey) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const onRecaptchaLoaded = () => {
|
const onRecaptchaLoaded = () => {
|
||||||
if (!document.getElementById(recaptchaId)) {
|
if (!document.getElementById(recaptchaId)) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.grecaptcha.render(recaptchaId, {
|
window.grecaptcha.render(recaptchaId, {
|
||||||
sitekey,
|
sitekey,
|
||||||
size: "invisible",
|
size: "invisible",
|
||||||
callback: (response) => {
|
callback: (response: string) => promiseRef.current?.resolve(response),
|
||||||
if (promiseRef.current) {
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
promiseRef.current.resolve(response);
|
"error-callback": () => promiseRef.current?.reject(new Error()),
|
||||||
}
|
|
||||||
},
|
|
||||||
"error-callback": (error) => {
|
|
||||||
if (promiseRef.current) {
|
|
||||||
promiseRef.current.reject(error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (
|
if (typeof window.grecaptcha?.render === "function") {
|
||||||
typeof window.grecaptcha !== "undefined" &&
|
|
||||||
typeof window.grecaptcha.render === "function"
|
|
||||||
) {
|
|
||||||
onRecaptchaLoaded();
|
onRecaptchaLoaded();
|
||||||
} else {
|
} else {
|
||||||
window.mxOnRecaptchaLoaded = onRecaptchaLoaded;
|
window.mxOnRecaptchaLoaded = onRecaptchaLoaded;
|
||||||
|
|
||||||
if (!document.querySelector(`script[src="${RECAPTCHA_SCRIPT_URL}"]`)) {
|
if (!document.querySelector(`script[src="${RECAPTCHA_SCRIPT_URL}"]`)) {
|
||||||
const scriptTag = document.createElement("script");
|
const scriptTag = document.createElement("script") as HTMLScriptElement;
|
||||||
scriptTag.src = RECAPTCHA_SCRIPT_URL;
|
scriptTag.src = RECAPTCHA_SCRIPT_URL;
|
||||||
scriptTag.async = true;
|
scriptTag.async = true;
|
||||||
document.body.appendChild(scriptTag);
|
document.body.appendChild(scriptTag);
|
||||||
|
|
@ -80,7 +77,7 @@ export function useRecaptcha(sitekey) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const observer = new MutationObserver((mutationsList) => {
|
const observer = new MutationObserver((mutationsList) => {
|
||||||
for (const item of mutationsList) {
|
for (const item of mutationsList) {
|
||||||
if (item.target?.style?.visibility !== "visible") {
|
if ((item.target as HTMLElement)?.style?.visibility !== "visible") {
|
||||||
reject(new Error("Recaptcha dismissed"));
|
reject(new Error("Recaptcha dismissed"));
|
||||||
observer.disconnect();
|
observer.disconnect();
|
||||||
return;
|
return;
|
||||||
|
|
@ -101,7 +98,7 @@ export function useRecaptcha(sitekey) {
|
||||||
|
|
||||||
window.grecaptcha.execute();
|
window.grecaptcha.execute();
|
||||||
|
|
||||||
const iframe = document.querySelector(
|
const iframe = document.querySelector<HTMLIFrameElement>(
|
||||||
'iframe[src*="recaptcha/api2/bframe"]'
|
'iframe[src*="recaptcha/api2/bframe"]'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -111,13 +108,11 @@ export function useRecaptcha(sitekey) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [recaptchaId, sitekey]);
|
}, [sitekey]);
|
||||||
|
|
||||||
const reset = useCallback(() => {
|
const reset = useCallback(() => {
|
||||||
if (window.grecaptcha) {
|
window.grecaptcha?.reset();
|
||||||
window.grecaptcha.reset();
|
}, []);
|
||||||
}
|
|
||||||
}, [recaptchaId]);
|
|
||||||
|
|
||||||
return { execute, reset, recaptchaId };
|
return { execute, reset, recaptchaId };
|
||||||
}
|
};
|
||||||
|
|
@ -2876,6 +2876,11 @@
|
||||||
"@types/minimatch" "*"
|
"@types/minimatch" "*"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/grecaptcha@^3.0.4":
|
||||||
|
version "3.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/grecaptcha/-/grecaptcha-3.0.4.tgz#3de601f3b0cd0298faf052dd5bd62aff64c2be2e"
|
||||||
|
integrity sha512-7l1Y8DTGXkx/r4pwU1nMVAR+yD/QC+MCHKXAyEX/7JZhwcN1IED09aZ9vCjjkcGdhSQiu/eJqcXInpl6eEEEwg==
|
||||||
|
|
||||||
"@types/hast@^2.0.0":
|
"@types/hast@^2.0.0":
|
||||||
version "2.3.4"
|
version "2.3.4"
|
||||||
resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc"
|
resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue