rune
Version:
CLI to upload your games to Rune
89 lines (88 loc) • 4.66 kB
JavaScript
import { Text, Box } from "ink";
import TextInputImport from "ink-text-input";
import React, { useState, useEffect, useMemo, useCallback } from "react";
import { Step } from "../components/Step.js";
import { useCheckVerification } from "../gql/useCheckVerification.js";
import { useMe } from "../gql/useMe.js";
import { useStartVerification } from "../gql/useStartVerification.js";
import { formatApolloError } from "../lib/formatApolloError.js";
import { deleteAuthTokenFromStorage, getAuthTokenFromStorage, setAuthTokenInStorage, } from "../lib/login.js";
// @ts-ignore
const TextInput = TextInputImport.default;
const checkVerificationEvery = 2000;
const alreadyHasAuthToken = !!getAuthTokenFromStorage();
export function Login() {
const [authToken, setAuthToken] = useState(() => getAuthTokenFromStorage());
const { meLoading, meError } = useMe({ skip: !authToken });
const [email, setEmail] = useState("");
const { startVerification, startVerificationLoading, startVerificationError, verificationToken, } = useStartVerification();
const { checkVerification, checkVerificationLoading, checkVerificationError, authToken: newAuthToken, } = useCheckVerification();
const sanitizedEmail = useMemo(() => email.trim().toLowerCase(), [email]);
const submitEmail = useCallback(() => {
if (sanitizedEmail)
startVerification({ email: sanitizedEmail });
}, [sanitizedEmail, startVerification]);
useEffect(() => {
if (verificationToken &&
!authToken &&
!checkVerificationLoading &&
!checkVerificationError) {
const handle = setTimeout(() => {
checkVerification({ verificationToken });
}, checkVerificationEvery);
return () => clearTimeout(handle);
}
}, [
authToken,
checkVerification,
checkVerificationError,
checkVerificationLoading,
verificationToken,
]);
useEffect(() => {
if (newAuthToken) {
setAuthTokenInStorage(newAuthToken);
setAuthToken(newAuthToken);
}
}, [newAuthToken]);
useEffect(() => {
if (meError?.message.includes("[tango][AUTH_FAILED]")) {
deleteAuthTokenFromStorage();
}
}, [meError?.message]);
if (alreadyHasAuthToken && meLoading) {
return React.createElement(Step, { status: "waiting", label: "Checking authorization" });
}
if (meError) {
return (React.createElement(Step, { status: "error", label: formatApolloError(meError, {
"[tango][AUTH_FAILED]": "Authentication failed. Please try again.",
}) }));
}
return (React.createElement(Box, { flexDirection: "column" }, !alreadyHasAuthToken && (React.createElement(React.Fragment, null,
React.createElement(Step, { status: verificationToken
? "success"
: startVerificationLoading
? "waiting"
: "userInput", label: (status) => status === "success"
? "Email sent"
: status === "waiting"
? "Sending verification email"
: "Login to your Rune account to continue. If you don't have a Rune account, install the app and create an email-verified account", view: (status) => status === "userInput" && (React.createElement(Box, { flexDirection: "column" },
startVerificationError && (React.createElement(Text, { color: "red" }, formatApolloError(startVerificationError, {
"[tango][VERIFICATION_RATE_LIMIT]": "It looks like you’ve already tried to verify this email recently, please wait a bit before trying again",
}))),
React.createElement(Box, null,
React.createElement(Text, null, "Email: "),
React.createElement(TextInput, { placeholder: "email@example.com", value: email, onChange: setEmail, onSubmit: submitEmail })))) }),
!!verificationToken && (React.createElement(Step, { status: authToken
? "success"
: checkVerificationError
? "error"
: "waiting", label: (status) => status === "success"
? "Email confirmed"
: checkVerificationError
? formatApolloError(checkVerificationError, {
"[tango][JWT_EXPIRED]": "It looks like the email link has expired, please try again",
})
: `An email was sent to \`${sanitizedEmail}\`, please open it and click the link inside to proceed` }))))));
}