diff --git a/src/App.jsx b/src/App.jsx
index dc5c6e68..4808a67d 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -19,8 +19,8 @@ import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import * as Sentry from "@sentry/react";
import { OverlayProvider } from "@react-aria/overlays";
import { HomePage } from "./home/HomePage";
-import { LoginPage } from "./LoginPage";
-import { RegisterPage } from "./RegisterPage";
+import { LoginPage } from "./auth/LoginPage";
+import { RegisterPage } from "./auth/RegisterPage";
import { RoomPage } from "./room/RoomPage";
import { RoomRedirect } from "./room/RoomRedirect";
import { ClientProvider } from "./ConferenceCallManagerHooks";
diff --git a/src/RecaptchaInput.jsx b/src/RecaptchaInput.jsx
deleted file mode 100644
index 1901196c..00000000
--- a/src/RecaptchaInput.jsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import React, { useEffect, useRef } from "react";
-
-export function RecaptchaInput({ publicKey, onResponse }) {
- const containerRef = useRef();
- const recaptchaRef = useRef();
-
- useEffect(() => {
- const onRecaptchaLoaded = () => {
- if (!recaptchaRef.current) {
- return;
- }
-
- window.grecaptcha.render(recaptchaRef.current, {
- sitekey: publicKey,
- callback: (response) => {
- if (!recaptchaRef.current) {
- return;
- }
-
- onResponse(response);
- },
- });
- };
-
- if (
- typeof window.grecaptcha !== "undefined" &&
- typeof window.grecaptcha.render === "function"
- ) {
- onRecaptchaLoaded();
- } else {
- window.mxOnRecaptchaLoaded = onRecaptchaLoaded;
- const scriptTag = document.createElement("script");
- scriptTag.setAttribute(
- "src",
- `https://www.recaptcha.net/recaptcha/api.js?onload=mxOnRecaptchaLoaded&render=explicit`
- );
- containerRef.current.appendChild(scriptTag);
- }
- }, []);
-
- return (
-
- );
-}
diff --git a/src/LoginPage.jsx b/src/auth/LoginPage.jsx
similarity index 94%
rename from src/LoginPage.jsx
rename to src/auth/LoginPage.jsx
index 60992611..c5a6841a 100644
--- a/src/LoginPage.jsx
+++ b/src/auth/LoginPage.jsx
@@ -16,14 +16,14 @@ limitations under the License.
import React, { useCallback, useRef, useState, useMemo } from "react";
import { useHistory, useLocation, Link } from "react-router-dom";
-import { ReactComponent as Logo } from "./icons/LogoLarge.svg";
-import { FieldRow, InputField, ErrorMessage } from "./Input";
-import { Button } from "./button";
+import { ReactComponent as Logo } from "../icons/LogoLarge.svg";
+import { FieldRow, InputField, ErrorMessage } from "../Input";
+import { Button } from "../button";
import {
defaultHomeserver,
defaultHomeserverHost,
useInteractiveLogin,
-} from "./ConferenceCallManagerHooks";
+} from "../ConferenceCallManagerHooks";
import styles from "./LoginPage.module.css";
export function LoginPage() {
diff --git a/src/LoginPage.module.css b/src/auth/LoginPage.module.css
similarity index 100%
rename from src/LoginPage.module.css
rename to src/auth/LoginPage.module.css
diff --git a/src/RegisterPage.jsx b/src/auth/RegisterPage.jsx
similarity index 64%
rename from src/RegisterPage.jsx
rename to src/auth/RegisterPage.jsx
index 81c6662e..c9ed9b82 100644
--- a/src/RegisterPage.jsx
+++ b/src/auth/RegisterPage.jsx
@@ -15,18 +15,19 @@ limitations under the License.
*/
import React, { useCallback, useEffect, useRef, useState } from "react";
-import { useHistory, useLocation, Link } from "react-router-dom";
-import { FieldRow, InputField, ErrorMessage, Field } from "./Input";
-import { Button } from "./button";
+import { useHistory, useLocation } from "react-router-dom";
+import { FieldRow, InputField, ErrorMessage } from "../Input";
+import { Button } from "../button";
import {
useClient,
defaultHomeserverHost,
useInteractiveRegistration,
-} from "./ConferenceCallManagerHooks";
+} from "../ConferenceCallManagerHooks";
import styles from "./LoginPage.module.css";
-import { ReactComponent as Logo } from "./icons/LogoLarge.svg";
-import { LoadingView } from "./FullScreenView";
-import { RecaptchaInput } from "./RecaptchaInput";
+import { ReactComponent as Logo } from "../icons/LogoLarge.svg";
+import { LoadingView } from "../FullScreenView";
+import { useRecaptcha } from "./useRecaptcha";
+import { Caption, Link } from "../typography/Typography";
export function RegisterPage() {
const {
@@ -37,17 +38,15 @@ export function RegisterPage() {
isPasswordlessUser,
} = useClient();
const confirmPasswordRef = useRef();
- const acceptTermsRef = useRef();
const history = useHistory();
const location = useLocation();
const [registering, setRegistering] = useState(false);
const [error, setError] = useState();
const [password, setPassword] = useState("");
const [passwordConfirmation, setPasswordConfirmation] = useState("");
- const [acceptTerms, setAcceptTerms] = useState(false);
const [{ privacyPolicyUrl, recaptchaKey }, register] =
useInteractiveRegistration();
- const [recaptchaResponse, setRecaptchaResponse] = useState();
+ const { execute, reset, recaptchaId } = useRecaptcha(recaptchaKey);
const onSubmitRegisterForm = useCallback(
(e) => {
@@ -56,51 +55,35 @@ export function RegisterPage() {
const userName = data.get("userName");
const password = data.get("password");
const passwordConfirmation = data.get("passwordConfirmation");
- const acceptTerms = data.get("acceptTerms");
- if (isPasswordlessUser) {
- if (password !== passwordConfirmation) {
- return;
- }
-
- setRegistering(true);
-
- changePassword(password)
- .then(() => {
- if (location.state && location.state.from) {
- history.push(location.state.from);
- } else {
- history.push("/");
- }
- })
- .catch((error) => {
- setError(error);
- setRegistering(false);
- });
- } else {
- if (
- password !== passwordConfirmation ||
- !acceptTerms ||
- !recaptchaResponse
- ) {
- return;
- }
-
- setRegistering(true);
-
- register(userName, password, recaptchaResponse)
- .then(() => {
- if (location.state && location.state.from) {
- history.push(location.state.from);
- } else {
- history.push("/");
- }
- })
- .catch((error) => {
- setError(error);
- setRegistering(false);
- });
+ if (password !== passwordConfirmation) {
+ return;
}
+
+ async function submit() {
+ setRegistering(true);
+
+ if (isPasswordlessUser) {
+ changePassword(password);
+ } else {
+ const recaptchaResponse = await execute();
+ await register(userName, password, recaptchaResponse);
+ }
+ }
+
+ submit()
+ .then(() => {
+ if (location.state && location.state.from) {
+ history.push(location.state.from);
+ } else {
+ history.push("/");
+ }
+ })
+ .catch((error) => {
+ setError(error);
+ setRegistering(false);
+ reset();
+ });
},
[
register,
@@ -108,7 +91,8 @@ export function RegisterPage() {
location,
history,
isPasswordlessUser,
- recaptchaResponse,
+ reset,
+ execute,
]
);
@@ -124,20 +108,6 @@ export function RegisterPage() {
}
}, [password, passwordConfirmation]);
- useEffect(() => {
- if (!acceptTermsRef.current) {
- return;
- }
-
- if (!acceptTerms) {
- acceptTermsRef.current.setCustomValidity(
- "You must accept the terms to continue."
- );
- } else {
- acceptTermsRef.current.setCustomValidity("");
- }
- }, [acceptTerms]);
-
useEffect(() => {
if (!loading && isAuthenticated && !isPasswordlessUser) {
history.push("/");
@@ -198,28 +168,20 @@ export function RegisterPage() {
/>
{!isPasswordlessUser && (
-
- setAcceptTerms(e.target.checked)}
- checked={acceptTerms}
- label="Accept Privacy Policy"
- ref={acceptTermsRef}
- />
-
+
+ This site is protected by ReCAPTCHA and the Google{" "}
+
Privacy Policy
-
-
- )}
- {!isPasswordlessUser && recaptchaKey && (
-
-
-
+ {" "}
+ and{" "}
+
+ Terms of Service
+ {" "}
+ apply.
+
+ By clicking "Go", you agree to our{" "}
+ Terms and conditions
+
)}
{error && (
@@ -231,6 +193,7 @@ export function RegisterPage() {
{registering ? "Registering..." : "Register"}
+
diff --git a/src/useRecaptcha.js b/src/auth/useRecaptcha.js
similarity index 100%
rename from src/useRecaptcha.js
rename to src/auth/useRecaptcha.js
diff --git a/src/home/UnauthenticatedView.jsx b/src/home/UnauthenticatedView.jsx
index 79d33987..bb5306ca 100644
--- a/src/home/UnauthenticatedView.jsx
+++ b/src/home/UnauthenticatedView.jsx
@@ -12,7 +12,7 @@ import {
} from "../ConferenceCallManagerHooks";
import { useModalTriggerState } from "../Modal";
import { JoinExistingCallModal } from "../JoinExistingCallModal";
-import { useRecaptcha } from "../useRecaptcha";
+import { useRecaptcha } from "../auth/useRecaptcha";
import { Body, Caption, Link, Headline } from "../typography/Typography";
import { Form } from "../form/Form";
import styles from "./UnauthenticatedView.module.css";
diff --git a/src/room/RoomAuthView.jsx b/src/room/RoomAuthView.jsx
index acaa1bb4..72634e59 100644
--- a/src/room/RoomAuthView.jsx
+++ b/src/room/RoomAuthView.jsx
@@ -4,7 +4,7 @@ import { Button } from "../button";
import { Body, Caption, Link, Headline } from "../typography/Typography";
import { Header, HeaderLogo, LeftNav, RightNav } from "../Header";
import { useLocation } from "react-router-dom";
-import { useRecaptcha } from "../useRecaptcha";
+import { useRecaptcha } from "../auth/useRecaptcha";
import { FieldRow, InputField, ErrorMessage } from "../Input";
import { randomString } from "matrix-js-sdk/src/randomstring";
import { useInteractiveRegistration } from "../ConferenceCallManagerHooks";