import { confirmDialog } from '@Services/alertService'; import { STRING_ACCOUNT_MENU_UNCHECK_MERGE, STRING_GENERATING_LOGIN_KEYS, STRING_GENERATING_REGISTER_KEYS, STRING_NON_MATCHING_PASSWORDS, } from '@/strings'; import { JSXInternal } from 'preact/src/jsx'; import TargetedEvent = JSXInternal.TargetedEvent; import TargetedKeyboardEvent = JSXInternal.TargetedKeyboardEvent; import { WebApplication } from '@/ui_models/application'; import { useEffect, useRef, useState } from 'preact/hooks'; import TargetedMouseEvent = JSXInternal.TargetedMouseEvent; import { observer } from 'mobx-react-lite'; import { AppState } from '@/ui_models/app_state'; type Props = { application: WebApplication; appState: AppState; }; const Authentication = observer(({ application, appState }: Props) => { const [showAdvanced, setShowAdvanced] = useState(false); const [isAuthenticating, setIsAuthenticating] = useState(false); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [passwordConfirmation, setPasswordConfirmation] = useState(''); const [status, setStatus] = useState(undefined); const [isEmailFocused, setIsEmailFocused] = useState(false); const [isEphemeral, setIsEphemeral] = useState(false); const [isStrictSignIn, setIsStrictSignIn] = useState(false); const [shouldMergeLocal, setShouldMergeLocal] = useState(true); const { server, notesAndTagsCount, showSignIn, showRegister, setShowSignIn, setShowRegister, setServer, closeAccountMenu, } = appState.accountMenu; useEffect(() => { if (isEmailFocused) { emailInputRef.current.focus(); setIsEmailFocused(false); } }, [isEmailFocused]); // Reset password and confirmation fields when hiding the form useEffect(() => { if (!showSignIn && !showRegister) { setPassword(''); setPasswordConfirmation(''); } }, [showSignIn, showRegister]); const handleHostInputChange = (event: TargetedEvent) => { const { value } = event.target as HTMLInputElement; setServer(value); application.setCustomHost(value); }; const emailInputRef = useRef(); const passwordInputRef = useRef(); const passwordConfirmationInputRef = useRef(); const handleSignInClick = () => { setShowSignIn(true); setIsEmailFocused(true); }; const handleRegisterClick = () => { setShowRegister(true); setIsEmailFocused(true); }; const blurAuthFields = () => { emailInputRef.current.blur(); passwordInputRef.current.blur(); passwordConfirmationInputRef.current?.blur(); }; const signin = async () => { setStatus(STRING_GENERATING_LOGIN_KEYS); setIsAuthenticating(true); const response = await application.signIn( email, password, isStrictSignIn, isEphemeral, shouldMergeLocal ); const error = response.error; if (!error) { setIsAuthenticating(false); setPassword(''); setShowSignIn(false); closeAccountMenu(); return; } setShowSignIn(true); setStatus(undefined); setPassword(''); if (error.message) { await application.alertService.alert(error.message); } setIsAuthenticating(false); }; const register = async () => { if (passwordConfirmation !== password) { application.alertService.alert(STRING_NON_MATCHING_PASSWORDS); return; } setStatus(STRING_GENERATING_REGISTER_KEYS); setIsAuthenticating(true); const response = await application.register( email, password, isEphemeral, shouldMergeLocal ); const error = response.error; if (error) { setStatus(undefined); setIsAuthenticating(false); application.alertService.alert(error.message); } else { setIsAuthenticating(false); setShowRegister(false); closeAccountMenu(); } }; const handleAuthFormSubmit = ( event: | TargetedEvent | TargetedMouseEvent | TargetedKeyboardEvent ) => { event.preventDefault(); if (!email || !password) { return; } blurAuthFields(); if (showSignIn) { signin(); } else { register(); } }; const handleKeyPressKeyDown = (event: KeyboardEvent) => { if (event.key === 'Enter') { handleAuthFormSubmit(event as TargetedKeyboardEvent); } }; const handlePasswordChange = (event: TargetedEvent) => { const { value } = event.target as HTMLInputElement; setPassword(value); }; const handleEmailChange = (event: TargetedEvent) => { const { value } = event.target as HTMLInputElement; setEmail(value); }; const handlePasswordConfirmationChange = ( event: TargetedEvent ) => { const { value } = event.target as HTMLInputElement; setPasswordConfirmation(value); }; const handleMergeLocalData = async ( event: TargetedEvent ) => { const { checked } = event.target as HTMLInputElement; setShouldMergeLocal(checked); if (!checked) { const confirmResult = await confirmDialog({ text: STRING_ACCOUNT_MENU_UNCHECK_MERGE, confirmButtonStyle: 'danger', }); setShouldMergeLocal(!confirmResult); } }; return ( <> {!application.hasAccount() && !showSignIn && !showRegister && (
Sign in or register to enable sync and end-to-end encryption.
Standard Notes is free on every platform, and comes standard with sync and encryption.
)} {(showSignIn || showRegister) && (
{showSignIn ? 'Sign In' : 'Register'}
{showRegister && ( )}
{showAdvanced && (
Advanced Options
{showSignIn && ( )}
)} {!isAuthenticating && (
)} {showRegister && (
No Password Reset.
Because your notes are encrypted using your password, Standard Notes does not have a password reset option. You cannot forget your password.
)} {status && (
{status}
)} {!isAuthenticating && (
{notesAndTagsCount > 0 && ( )}
)}
)} ); }); export default Authentication;