Refactor auth pages
This commit is contained in:
102
src/auth/useRecaptcha.js
Normal file
102
src/auth/useRecaptcha.js
Normal file
@@ -0,0 +1,102 @@
|
||||
import { randomString } from "matrix-js-sdk/src/randomstring";
|
||||
import { useEffect, useCallback, useRef, useState } from "react";
|
||||
|
||||
const RECAPTCHA_SCRIPT_URL =
|
||||
"https://www.recaptcha.net/recaptcha/api.js?onload=mxOnRecaptchaLoaded&render=explicit";
|
||||
|
||||
export function useRecaptcha(sitekey) {
|
||||
const [recaptchaId] = useState(() => randomString(16));
|
||||
const promiseRef = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
if (!sitekey) {
|
||||
return;
|
||||
}
|
||||
|
||||
const onRecaptchaLoaded = () => {
|
||||
if (!document.getElementById(recaptchaId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.grecaptcha.render(recaptchaId, {
|
||||
sitekey,
|
||||
size: "invisible",
|
||||
callback: (response) => {
|
||||
if (promiseRef.current) {
|
||||
promiseRef.current.resolve(response);
|
||||
}
|
||||
},
|
||||
"error-callback": (error) => {
|
||||
if (promiseRef.current) {
|
||||
promiseRef.current.reject(error);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
if (
|
||||
typeof window.grecaptcha !== "undefined" &&
|
||||
typeof window.grecaptcha.render === "function"
|
||||
) {
|
||||
onRecaptchaLoaded();
|
||||
} else {
|
||||
window.mxOnRecaptchaLoaded = onRecaptchaLoaded;
|
||||
|
||||
if (!document.querySelector(`script[src="${RECAPTCHA_SCRIPT_URL}"]`)) {
|
||||
const scriptTag = document.createElement("script");
|
||||
scriptTag.src = RECAPTCHA_SCRIPT_URL;
|
||||
scriptTag.async = true;
|
||||
document.body.appendChild(scriptTag);
|
||||
}
|
||||
}
|
||||
}, [recaptchaId, sitekey]);
|
||||
|
||||
const execute = useCallback(() => {
|
||||
if (!window.grecaptcha) {
|
||||
return Promise.reject(new Error("Recaptcha not loaded"));
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const observer = new MutationObserver((mutationsList) => {
|
||||
for (const item of mutationsList) {
|
||||
if (item.target.style.visibility !== "visible") {
|
||||
reject(new Error("Recaptcha dismissed"));
|
||||
observer.disconnect();
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
promiseRef.current = {
|
||||
resolve: (value) => {
|
||||
resolve(value);
|
||||
observer.disconnect();
|
||||
},
|
||||
reject: (error) => {
|
||||
reject(error);
|
||||
observer.disconnect();
|
||||
},
|
||||
};
|
||||
|
||||
window.grecaptcha.execute();
|
||||
|
||||
const iframe = document.querySelector(
|
||||
'iframe[src*="recaptcha/api2/bframe"]'
|
||||
);
|
||||
|
||||
if (iframe?.parentNode?.parentNode) {
|
||||
observer.observe(iframe?.parentNode?.parentNode, {
|
||||
attributes: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
}, [recaptchaId]);
|
||||
|
||||
const reset = useCallback(() => {
|
||||
if (window.grecaptcha) {
|
||||
window.grecaptcha.reset();
|
||||
}
|
||||
}, [recaptchaId]);
|
||||
|
||||
return { execute, reset, recaptchaId };
|
||||
}
|
||||
Reference in New Issue
Block a user