diff --git a/web/apps/photos/src/pages/index.tsx b/web/apps/photos/src/pages/index.tsx
index 492785c91..907f37d3d 100644
--- a/web/apps/photos/src/pages/index.tsx
+++ b/web/apps/photos/src/pages/index.tsx
@@ -1,6 +1,6 @@
import log from "@/next/log";
-import Login from "@ente/accounts/components/Login";
-import SignUp from "@ente/accounts/components/SignUp";
+import { Login } from "@ente/accounts/components/Login";
+import { SignUp } from "@ente/accounts/components/SignUp";
import { APPS } from "@ente/shared/apps/constants";
import { EnteLogo } from "@ente/shared/components/EnteLogo";
import EnteSpinner from "@ente/shared/components/EnteSpinner";
diff --git a/web/packages/accounts/components/Login.tsx b/web/packages/accounts/components/Login.tsx
new file mode 100644
index 000000000..6ddbe1491
--- /dev/null
+++ b/web/packages/accounts/components/Login.tsx
@@ -0,0 +1,75 @@
+import log from "@/next/log";
+import { appNameToAppNameOld } from "@ente/shared/apps/constants";
+import FormPaperFooter from "@ente/shared/components/Form/FormPaper/Footer";
+import FormPaperTitle from "@ente/shared/components/Form/FormPaper/Title";
+import LinkButton from "@ente/shared/components/LinkButton";
+import SingleInputForm, {
+ type SingleInputFormProps,
+} from "@ente/shared/components/SingleInputForm";
+import { LS_KEYS, setData } from "@ente/shared/storage/localStorage";
+import { Input } from "@mui/material";
+import { t } from "i18next";
+import { useRouter } from "next/router";
+import type { AppName } from "packages/next/types/app";
+import { getSRPAttributes } from "../api/srp";
+import { sendOtt } from "../api/user";
+import { PAGES } from "../constants/pages";
+
+interface LoginProps {
+ signUp: () => void;
+ appName: AppName;
+}
+
+export function Login(props: LoginProps) {
+ const appNameOld = appNameToAppNameOld(props.appName);
+
+ const router = useRouter();
+
+ const loginUser: SingleInputFormProps["callback"] = async (
+ email,
+ setFieldError,
+ ) => {
+ try {
+ setData(LS_KEYS.USER, { email });
+ const srpAttributes = await getSRPAttributes(email);
+ log.debug(() => ` srpAttributes: ${JSON.stringify(srpAttributes)}`);
+ if (!srpAttributes || srpAttributes.isEmailMFAEnabled) {
+ await sendOtt(appNameOld, email);
+ router.push(PAGES.VERIFY);
+ } else {
+ setData(LS_KEYS.SRP_ATTRIBUTES, srpAttributes);
+ router.push(PAGES.CREDENTIALS);
+ }
+ } catch (e) {
+ if (e instanceof Error) {
+ setFieldError(`${t("UNKNOWN_ERROR")} (reason:${e.message})`);
+ } else {
+ setFieldError(
+ `${t("UNKNOWN_ERROR")} (reason:${JSON.stringify(e)})`,
+ );
+ }
+ }
+ };
+
+ return (
+ <>
+ {t("LOGIN")}
+
+ }
+ />
+
+
+
+ {t("NO_ACCOUNT")}
+
+
+ >
+ );
+}
diff --git a/web/packages/accounts/components/SignUp.tsx b/web/packages/accounts/components/SignUp.tsx
new file mode 100644
index 000000000..6c89eb8fb
--- /dev/null
+++ b/web/packages/accounts/components/SignUp.tsx
@@ -0,0 +1,320 @@
+import log from "@/next/log";
+import { sendOtt } from "@ente/accounts/api/user";
+import { PasswordStrengthHint } from "@ente/accounts/components/PasswordStrength";
+import { PAGES } from "@ente/accounts/constants/pages";
+import { isWeakPassword } from "@ente/accounts/utils";
+import { generateKeyAndSRPAttributes } from "@ente/accounts/utils/srp";
+import { LS_KEYS } from "@ente/shared//storage/localStorage";
+import { appNameToAppNameOld } from "@ente/shared/apps/constants";
+import { VerticallyCentered } from "@ente/shared/components/Container";
+import FormPaperFooter from "@ente/shared/components/Form/FormPaper/Footer";
+import FormPaperTitle from "@ente/shared/components/Form/FormPaper/Title";
+import ShowHidePassword from "@ente/shared/components/Form/ShowHidePassword";
+import LinkButton from "@ente/shared/components/LinkButton";
+import SubmitButton from "@ente/shared/components/SubmitButton";
+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,
+ TextField,
+ Tooltip,
+ Typography,
+} from "@mui/material";
+import { Formik, type FormikHelpers } from "formik";
+import { t } from "i18next";
+import type { NextRouter } from "next/router";
+import type { AppName } from "packages/next/types/app";
+import React, { useState } from "react";
+import { Trans } from "react-i18next";
+import * as Yup from "yup";
+
+interface FormValues {
+ email: string;
+ passphrase: string;
+ confirm: string;
+ referral: string;
+}
+
+interface SignUpProps {
+ router: NextRouter;
+ login: () => void;
+ appName: AppName;
+}
+
+export function SignUp({ router, appName, login }: SignUpProps) {
+ const appNameOld = appNameToAppNameOld(appName);
+
+ 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 {
+ setData(LS_KEYS.USER, { email });
+ setLocalReferralSource(referral);
+ await sendOtt(appNameOld, email);
+ } catch (e) {
+ const message = e instanceof Error ? e.message : "";
+ setFieldError("confirm", `${t("UNKNOWN_ERROR")} ${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);
+ 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,
+ }): JSX.Element => (
+
+ )}
+
+
+
+ {t("ACCOUNT_EXISTS")}
+
+ >
+ );
+}
diff --git a/web/packages/accounts/pages/login.tsx b/web/packages/accounts/pages/login.tsx
index 506cc81bc..57ea023ff 100644
--- a/web/packages/accounts/pages/login.tsx
+++ b/web/packages/accounts/pages/login.tsx
@@ -1,23 +1,11 @@
-import log from "@/next/log";
-import { appNameToAppNameOld } from "@ente/shared/apps/constants";
import type { PageProps } from "@ente/shared/apps/types";
import { VerticallyCentered } from "@ente/shared/components/Container";
import EnteSpinner from "@ente/shared/components/EnteSpinner";
import FormPaper from "@ente/shared/components/Form/FormPaper";
-import FormPaperFooter from "@ente/shared/components/Form/FormPaper/Footer";
-import FormPaperTitle from "@ente/shared/components/Form/FormPaper/Title";
-import LinkButton from "@ente/shared/components/LinkButton";
-import SingleInputForm, {
- type SingleInputFormProps,
-} from "@ente/shared/components/SingleInputForm";
-import { LS_KEYS, getData, setData } from "@ente/shared/storage/localStorage";
-import { Input } from "@mui/material";
-import { t } from "i18next";
+import { LS_KEYS, getData } from "@ente/shared/storage/localStorage";
import { useRouter } from "next/router";
-import type { AppName } from "packages/next/types/app";
import React, { useEffect, useState } from "react";
-import { getSRPAttributes } from "../api/srp";
-import { sendOtt } from "../api/user";
+import { Login } from "../components/Login";
import { PAGES } from "../constants/pages";
const Page: React.FC = ({ appContext }) => {
@@ -54,62 +42,3 @@ const Page: React.FC = ({ appContext }) => {
};
export default Page;
-
-interface LoginProps {
- signUp: () => void;
- appName: AppName;
-}
-
-function Login(props: LoginProps) {
- const appNameOld = appNameToAppNameOld(props.appName);
-
- const router = useRouter();
-
- const loginUser: SingleInputFormProps["callback"] = async (
- email,
- setFieldError,
- ) => {
- try {
- setData(LS_KEYS.USER, { email });
- const srpAttributes = await getSRPAttributes(email);
- log.debug(() => ` srpAttributes: ${JSON.stringify(srpAttributes)}`);
- if (!srpAttributes || srpAttributes.isEmailMFAEnabled) {
- await sendOtt(appNameOld, email);
- router.push(PAGES.VERIFY);
- } else {
- setData(LS_KEYS.SRP_ATTRIBUTES, srpAttributes);
- router.push(PAGES.CREDENTIALS);
- }
- } catch (e) {
- if (e instanceof Error) {
- setFieldError(`${t("UNKNOWN_ERROR")} (reason:${e.message})`);
- } else {
- setFieldError(
- `${t("UNKNOWN_ERROR")} (reason:${JSON.stringify(e)})`,
- );
- }
- }
- };
-
- return (
- <>
- {t("LOGIN")}
-
- }
- />
-
-
-
- {t("NO_ACCOUNT")}
-
-
- >
- );
-}
diff --git a/web/packages/accounts/pages/signup.tsx b/web/packages/accounts/pages/signup.tsx
index 02f810250..affc0099b 100644
--- a/web/packages/accounts/pages/signup.tsx
+++ b/web/packages/accounts/pages/signup.tsx
@@ -1,51 +1,12 @@
-import log from "@/next/log";
-import { sendOtt } from "@ente/accounts/api/user";
-import { PasswordStrengthHint } from "@ente/accounts/components/PasswordStrength";
import { PAGES } from "@ente/accounts/constants/pages";
-import { isWeakPassword } from "@ente/accounts/utils";
-import { generateKeyAndSRPAttributes } from "@ente/accounts/utils/srp";
import { LS_KEYS, getData } from "@ente/shared//storage/localStorage";
-import { appNameToAppNameOld } from "@ente/shared/apps/constants";
import type { PageProps } from "@ente/shared/apps/types";
import { VerticallyCentered } from "@ente/shared/components/Container";
import EnteSpinner from "@ente/shared/components/EnteSpinner";
import FormPaper from "@ente/shared/components/Form/FormPaper";
-import FormPaperFooter from "@ente/shared/components/Form/FormPaper/Footer";
-import FormPaperTitle from "@ente/shared/components/Form/FormPaper/Title";
-import ShowHidePassword from "@ente/shared/components/Form/ShowHidePassword";
-import LinkButton from "@ente/shared/components/LinkButton";
-import SubmitButton from "@ente/shared/components/SubmitButton";
-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,
- TextField,
- Tooltip,
- Typography,
-} from "@mui/material";
-import { Formik, type FormikHelpers } from "formik";
-import { t } from "i18next";
-import type { NextRouter } from "next/router";
import { useRouter } from "next/router";
-import type { AppName } from "packages/next/types/app";
import React, { useEffect, useState } from "react";
-import { Trans } from "react-i18next";
-import * as Yup from "yup";
+import { SignUp } from "../components/SignUp";
const Page: React.FC = ({ appContext }) => {
const { appName } = appContext;
@@ -81,279 +42,3 @@ const Page: React.FC = ({ appContext }) => {
};
export default Page;
-
-interface FormValues {
- email: string;
- passphrase: string;
- confirm: string;
- referral: string;
-}
-
-interface SignUpProps {
- router: NextRouter;
- login: () => void;
- appName: AppName;
-}
-
-function SignUp({ router, appName, login }: SignUpProps) {
- const appNameOld = appNameToAppNameOld(appName);
-
- 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 {
- setData(LS_KEYS.USER, { email });
- setLocalReferralSource(referral);
- await sendOtt(appNameOld, email);
- } catch (e) {
- const message = e instanceof Error ? e.message : "";
- setFieldError("confirm", `${t("UNKNOWN_ERROR")} ${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);
- 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,
- }): JSX.Element => (
-
- )}
-
-
-
- {t("ACCOUNT_EXISTS")}
-
- >
- );
-}