UNPKG

rune

Version:

CLI to upload your games to Rune

89 lines (88 loc) 4.66 kB
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` })))))); }