import clsx from 'clsx'; import { h, Fragment, JSX } from 'preact'; import { useState, useRef } from 'preact/hooks'; import { useIntl } from 'react-intl'; import { useDispatch } from 'react-redux'; import { BASE_URL, API_BASE } from 'common/constants.config'; import { setUser } from 'store/user/actions'; import { Input } from 'components/input'; import { CrossIcon } from 'components/icons/cross'; import { TextareaAutosize } from 'components/textarea-autosize'; import { Spinner } from 'components/spinner/spinner'; import { ArrowIcon } from 'components/icons/arrow'; import { Button } from './components/button'; import { OAuth } from './components/oauth'; import { messages } from './auth.messsages'; import { useDropdown, useErrorMessage } from './auth.hooks'; import { getProviders, getTokenInvalidReason } from './auth.utils'; import { oauthSignin, emailSignin, verifyEmailSignin, anonymousSignin, verifyTelegramSignin, getTelegramSigninParams, } from './auth.api'; import styles from './auth.module.css'; export function Auth() { const intl = useIntl(); const telegramParamsRef = useRef(null); const dispatch = useDispatch(); const [oauthProviders, formProviders] = getProviders(); // UI State const [isLoading, setLoading] = useState(false); const [view, setView] = useState(formProviders[0]); const [ref, isDropdownShown, toggleDropdownState] = useDropdown(view === 'token' || view === 'telegram'); // Errors const [errorMessage, setError] = useErrorMessage(); function handleClickSingIn(evt: Event) { evt.preventDefault(); toggleDropdownState(); } function resetView() { setView(formProviders[0]); setError(null); } function handleDropdownClose(evt: Event) { evt.preventDefault(); resetView(); toggleDropdownState(); } function handleClickBack(evt: JSX.TargetedMouseEvent) { evt.preventDefault(); resetView(); } async function handleOauthClick(evt: JSX.TargetedMouseEvent) { evt.preventDefault(); const { href, dataset } = evt.currentTarget; if (dataset.providerName?.toLowerCase() === 'telegram') { try { telegramParamsRef.current = await getTelegramSigninParams(); } catch (e) { setError(e); return; } setView('telegram'); setError(null); return; } try { const user = await oauthSignin(href); if (user === null) { // TODO: add error message when user is null return; } dispatch(setUser(user)); } catch (e) { setError(e); } } function handleProviderChange(evt: Event) { const { value } = evt.currentTarget as HTMLInputElement; setView(value as typeof formProviders[number]); setError(null); } async function handleSubmit(evt: Event) { const data = new FormData(evt.target as HTMLFormElement); evt.preventDefault(); setLoading(true); setError(null); try { switch (view) { case 'anonymous': { const username = data.get('username') as string; const user = await anonymousSignin(username); dispatch(setUser(user)); break; } case 'email': { const email = data.get('email') as string; const username = data.get('username') as string; await emailSignin(email, username); setView('token'); break; } case 'token': { const token = data.get('token') as string; const invalidReason = getTokenInvalidReason(token); if (invalidReason) { setError(invalidReason); } else { const user = await verifyEmailSignin(token); dispatch(setUser(user)); } break; } } } catch (e) { setError(e); } setLoading(false); } async function handleTelegramSubmit(evt: Event) { evt.preventDefault(); setLoading(true); setError(null); if (telegramParamsRef.current === null) { try { telegramParamsRef.current = await getTelegramSigninParams(); } catch (e) { setError(e); return; } } try { const user = await verifyTelegramSignin(telegramParamsRef.current.token); dispatch(setUser(user)); } catch (e) { setError(e); } setLoading(false); } function handleShowEmailStep(evt: Event) { evt.preventDefault(); setView('email'); setError(null); } const hasOAuthProviders = oauthProviders.length > 0; const hasFormProviders = formProviders.length > 0; const formFooterJSX = ( <> {errorMessage &&
{errorMessage}
} ); return (
{isDropdownShown && (
{view === 'telegram' && telegramParamsRef.current !== null ? ( <>

{intl.formatMessage(messages.telegramMessage1)}{' '} {intl.formatMessage(messages.telegramLink)} {window.screen.width >= 768 && ` ${intl.formatMessage(messages.telegramOptionalQR)}`}{' '} {intl.formatMessage(messages.telegramMessage2)}
{intl.formatMessage(messages.telegramMessage3)}

{window.screen.width >= 768 && ( {intl.formatMessage(messages.telegramQR)} )} {errorMessage &&
{errorMessage}
} ) : view === 'token' ? ( <>
{formFooterJSX} ) : ( <> {hasOAuthProviders && ( <>
{intl.formatMessage(messages.oauthSource)}
)} {hasOAuthProviders && hasFormProviders && (
)} {hasFormProviders && ( <> {formProviders.length === 1 ? (
{formProviders[0]}
) : (
{formProviders.map((p) => ( ))}
)}
{ const element = evt.target as HTMLInputElement; element.value = element.value.trim(); }} />
{view === 'email' && (
)} {formFooterJSX} )} )}
)}
); }