import { FormPaperFooter, FormPaperTitle } from "@/base/components/FormPaper"; import { LoadingButton } from "@/base/components/mui/LoadingButton"; import log from "@/base/log"; import { LS_KEYS, setLSUser } from "@ente/shared//storage/localStorage"; import { VerticallyCentered } from "@ente/shared/components/Container"; import ShowHidePassword from "@ente/shared/components/Form/ShowHidePassword"; import LinkButton from "@ente/shared/components/LinkButton"; import { generateAndSaveIntermediateKeyAttributes, saveKeyInSessionStore, } from "@ente/shared/crypto/helpers"; import { setData } from "@ente/shared/storage/localStorage"; import { setJustSignedUp, setLocalReferralSource, } from "@ente/shared/storage/localStorage/helpers"; import { SESSION_KEYS } from "@ente/shared/storage/sessionStorage"; import InfoOutlined from "@mui/icons-material/InfoOutlined"; import { Box, Checkbox, FormControlLabel, FormGroup, IconButton, InputAdornment, Link, Stack, TextField, Tooltip, Typography, } from "@mui/material"; import { Formik, type FormikHelpers } from "formik"; import { t } from "i18next"; import type { NextRouter } from "next/router"; import React, { useState } from "react"; import { Trans } from "react-i18next"; import * as Yup from "yup"; import { PAGES } from "../constants/pages"; import { generateKeyAndSRPAttributes } from "../services/srp"; import { sendOtt } from "../services/user"; import { isWeakPassword } from "../utils/password"; import { PasswordStrengthHint } from "./PasswordStrength"; interface FormValues { email: string; passphrase: string; confirm: string; referral: string; } interface SignUpProps { router: NextRouter; login: () => void; /** Reactive value of {@link customAPIHost}. */ host: string | undefined; } export const SignUp: React.FC = ({ router, login, host }) => { const [acceptTerms, setAcceptTerms] = useState(false); const [loading, setLoading] = useState(false); const [showPassword, setShowPassword] = useState(false); const handleClickShowPassword = () => { setShowPassword(!showPassword); }; const handleMouseDownPassword = ( event: React.MouseEvent, ) => { event.preventDefault(); }; const registerUser = async ( { email, passphrase, confirm, referral }: FormValues, { setFieldError }: FormikHelpers, ) => { try { if (passphrase !== confirm) { setFieldError("confirm", t("PASSPHRASE_MATCH_ERROR")); return; } setLoading(true); try { await setLSUser({ email }); setLocalReferralSource(referral); await sendOtt(email); } catch (e) { const message = e instanceof Error ? e.message : ""; setFieldError( "confirm", `${t("generic_error_retry")} ${message}`, ); throw e; } try { const { keyAttributes, masterKey, srpSetupAttributes } = await generateKeyAndSRPAttributes(passphrase); setData(LS_KEYS.ORIGINAL_KEY_ATTRIBUTES, keyAttributes); setData(LS_KEYS.SRP_SETUP_ATTRIBUTES, srpSetupAttributes); await generateAndSaveIntermediateKeyAttributes( passphrase, keyAttributes, masterKey, ); await saveKeyInSessionStore( SESSION_KEYS.ENCRYPTION_KEY, masterKey, ); setJustSignedUp(true); void router.push(PAGES.VERIFY); } catch (e) { setFieldError("confirm", t("PASSWORD_GENERATION_FAILED")); throw e; } } catch (e) { log.error("signup failed", e); } setLoading(false); }; return ( <> {t("sign_up")} initialValues={{ email: "", passphrase: "", confirm: "", referral: "", }} validationSchema={Yup.object().shape({ email: Yup.string() .email(t("EMAIL_ERROR")) .required(t("required")), passphrase: Yup.string().required(t("required")), confirm: Yup.string().required(t("required")), })} validateOnChange={false} validateOnBlur={false} onSubmit={registerUser} > {({ values, errors, handleChange, handleSubmit, }): React.JSX.Element => (
), }} /> {t("REFERRAL_CODE_HINT")} ), }} fullWidth name="referral" type="text" value={values.referral} onChange={handleChange("referral")} error={Boolean(errors.referral)} disabled={loading} /> setAcceptTerms(e.target.checked) } color="accent" /> } label={ ), b: ( ), }} /> } /> {t("create_account")} {loading && ( {t("key_generation_in_progress")} )}
)} {t("ACCOUNT_EXISTS")} {host ?? "" /* prevent layout shift with a minHeight */} ); };