import { CodeBlock } from "@/accounts/components/CodeBlock";
import { Verify2FACodeForm } from "@/accounts/components/Verify2FACodeForm";
import { appHomeRoute } from "@/accounts/services/redirect";
import type { TwoFactorSecret } from "@/accounts/services/user";
import { enableTwoFactor, setupTwoFactor } from "@/accounts/services/user";
import { CenteredFill } from "@/base/components/containers";
import { LinkButton } from "@/base/components/LinkButton";
import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator";
import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton";
import { encryptWithRecoveryKey } from "@ente/shared/crypto/helpers";
import { getData, LS_KEYS, setLSUser } from "@ente/shared/storage/localStorage";
import { Paper, Stack, styled, Typography } from "@mui/material";
import { t } from "i18next";
import { useRouter } from "next/router";
import React, { useEffect, useState } from "react";
const Page: React.FC = () => {
const [twoFactorSecret, setTwoFactorSecret] = useState<
TwoFactorSecret | undefined
>();
const router = useRouter();
useEffect(() => {
void setupTwoFactor().then(setTwoFactorSecret);
}, []);
const handleSubmit = async (otp: string) => {
const {
encryptedData: encryptedTwoFactorSecret,
nonce: twoFactorSecretDecryptionNonce,
} = await encryptWithRecoveryKey(twoFactorSecret!.secretCode);
await enableTwoFactor({
code: otp,
encryptedTwoFactorSecret,
twoFactorSecretDecryptionNonce,
});
await setLSUser({
...getData(LS_KEYS.USER),
isTwoFactorEnabled: true,
});
await router.push(appHomeRoute);
};
return (
{t("two_factor")}
{t("go_back")}
);
};
export default Page;
const ContentsPaper = styled(Paper)(({ theme }) => ({
marginBlock: theme.spacing(2),
padding: theme.spacing(4, 2),
// Wide enough to fit the QR code secret in one line under default settings.
width: "min(440px, 95vw)",
display: "flex",
flexDirection: "column",
gap: theme.spacing(4),
}));
interface InstructionsProps {
twoFactorSecret: TwoFactorSecret | undefined;
}
const Instructions: React.FC = ({ twoFactorSecret }) => {
const [setupMode, setSetupMode] = useState<"qr" | "manual">("qr");
return (
{setupMode == "qr" ? (
setSetupMode("manual")}
/>
) : (
setSetupMode("qr")}
/>
)}
);
};
interface SetupManualModeProps {
twoFactorSecret: TwoFactorSecret | undefined;
onChangeMode: () => void;
}
const SetupManualMode: React.FC = ({
twoFactorSecret,
onChangeMode,
}) => (
<>
{t("two_factor_manual_entry_message")}
{t("scan_qr_title")}
>
);
interface SetupQRModeProps {
twoFactorSecret?: TwoFactorSecret;
onChangeMode: () => void;
}
const SetupQRMode: React.FC = ({
twoFactorSecret,
onChangeMode,
}) => (
<>
{t("two_factor_qr_help")}
{!twoFactorSecret ? (
) : (
)}
{t("two_factor_manual_entry_title")}
>
);
const QRCode = styled("img")(`
width: 200px;
height: 200px;
`);
const LoadingQRCode = styled(Stack)(
({ theme }) => `
width: 200px;
height: 200px;
border: 1px solid ${theme.vars.palette.stroke.muted};
align-items: center;
justify-content: center;
`,
);