/* Copyright 2021-2024 New Vector Ltd. SPDX-License-Identifier: AGPL-3.0-only Please see LICENSE in the repository root for full details. */ import { type ChangeEvent, type FC, type FormEvent, useCallback, useEffect, useRef, useState, } from "react"; import { useNavigate, useLocation } from "react-router-dom"; import { captureException } from "@sentry/react"; import { sleep } from "matrix-js-sdk/src/utils"; import { Trans, useTranslation } from "react-i18next"; import { logger } from "matrix-js-sdk/src/logger"; import { Button, Text } from "@vector-im/compound-web"; import { FieldRow, InputField, ErrorMessage } from "../input/Input"; import { useClientLegacy } from "../ClientContext"; import { useInteractiveRegistration } from "./useInteractiveRegistration"; import styles from "./LoginPage.module.css"; import Logo from "../icons/LogoLarge.svg?react"; import { LoadingView } from "../FullScreenView"; import { useRecaptcha } from "./useRecaptcha"; import { usePageTitle } from "../usePageTitle"; import { PosthogAnalytics } from "../analytics/PosthogAnalytics"; import { Config } from "../config/Config"; import { ExternalLink, Link } from "../button/Link"; export const RegisterPage: FC = () => { const { t } = useTranslation(); usePageTitle(t("action.register")); const { loading, authenticated, passwordlessUser, client, setClient } = useClientLegacy(); const confirmPasswordRef = useRef(null); const navigate = useNavigate(); const location = useLocation(); const [registering, setRegistering] = useState(false); const [error, setError] = useState(); const [password, setPassword] = useState(""); const [passwordConfirmation, setPasswordConfirmation] = useState(""); const { recaptchaKey, register } = useInteractiveRegistration(client); const { execute, reset, recaptchaId } = useRecaptcha(recaptchaKey); const onSubmitRegisterForm = useCallback( (e: FormEvent) => { e.preventDefault(); const data = new FormData(e.target as HTMLFormElement); const userName = data.get("userName") as string; const password = data.get("password") as string; const passwordConfirmation = data.get("passwordConfirmation") as string; if (password !== passwordConfirmation) return; const submit = async (): Promise => { setRegistering(true); const recaptchaResponse = await execute(); const [newClient, session] = await register( userName, password, userName, recaptchaResponse, passwordlessUser, ); if (client && client?.groupCallEventHandler && passwordlessUser) { // Migrate the user's rooms for (const groupCall of client.groupCallEventHandler.groupCalls.values()) { const roomId = groupCall.room.roomId; try { await newClient.joinRoom(roomId); } catch (error) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore if (error.errcode === "M_LIMIT_EXCEEDED") { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore await sleep(error.data.retry_after_ms); await newClient.joinRoom(roomId); } else { captureException(error); logger.error(`Couldn't join room ${roomId}`, error); } } } } setClient?.({ client: newClient, session }); PosthogAnalytics.instance.eventSignup.cacheSignupEnd(new Date()); }; submit() .then(async () => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore if (location.state?.from) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore await navigate(location.state?.from); } else { await navigate("/"); } }) .catch((error) => { setError(error); setRegistering(false); reset(); }); }, [ register, location, navigate, passwordlessUser, reset, execute, client, setClient, ], ); useEffect(() => { if (password && passwordConfirmation && password !== passwordConfirmation) { confirmPasswordRef.current?.setCustomValidity( t("register.passwords_must_match"), ); } else { confirmPasswordRef.current?.setCustomValidity(""); } }, [password, passwordConfirmation, t]); useEffect(() => { if (!loading && authenticated && !passwordlessUser && !registering) { navigate("/")?.catch((error) => { logger.error("Failed to navigate to /", error); }); } }, [loading, navigate, authenticated, passwordlessUser, registering]); if (loading) { return ; } else { PosthogAnalytics.instance.eventSignup.cacheSignupStart(new Date()); } return ( <>

{t("register_heading")}

): void => setPassword(e.target.value) } value={password} placeholder={t("common.password")} label={t("common.password")} data-testid="register_password" /> ): void => setPasswordConfirmation(e.target.value) } value={passwordConfirmation} placeholder={t("register_confirm_password_label")} label={t("register_confirm_password_label")} ref={confirmPasswordRef} data-testid="register_confirm_password" /> This site is protected by ReCAPTCHA and the Google{" "} Privacy Policy {" "} and{" "} Terms of Service {" "} apply.
By clicking "Register", you agree to our{" "} End User Licensing Agreement (EULA)
{error && ( )}

Already have an account?

Log in {" Or "} Access as a guest

); };