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 '@node_modules/preact/src/jsx'; import TargetedEvent = JSXInternal.TargetedEvent; import TargetedKeyboardEvent = JSXInternal.TargetedKeyboardEvent; import { WebApplication } from '@/ui_models/application'; import { StateUpdater, useEffect, useRef, useState } from 'preact/hooks'; import TargetedMouseEvent = JSXInternal.TargetedMouseEvent; import { FunctionalComponent } from 'preact'; import { User } from '@node_modules/@standardnotes/snjs/dist/@types/services/api/responses'; import { ApplicationEvent } from '@node_modules/@standardnotes/snjs'; import { observer } from 'mobx-react-lite'; import { FC } from 'react'; type Props = { application: WebApplication; // url: string | undefined; // setUrl: StateUpdater; server: string | undefined; setServer: StateUpdater; closeAccountMenu: () => void; notesAndTagsCount: number; showLogin: boolean; setShowLogin: StateUpdater; showRegister: boolean; setShowRegister: StateUpdater; user: User | undefined; } const Authentication: FC = ({ // const Authentication = observer(({ application, // url, // setUrl, server, setServer, closeAccountMenu, notesAndTagsCount, showLogin, setShowLogin, showRegister, setShowRegister, user }: Props) => { const [showAdvanced, setShowAdvanced] = useState(false); const [isAuthenticating, setIsAuthenticating] = useState(false); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); // const [passwordConfirmation, setPasswordConfirmation] = useState(undefined); 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); // TODO: maybe create a custom hook, which gets respective arguments and does focusing useEffect(() => { if (isEmailFocused) { emailInputRef.current.focus(); setIsEmailFocused(false); } }, [isEmailFocused]); // Reset password and confirmation fields when hiding the form useEffect(() => { if (!showLogin && !showRegister) { setPassword(''); // setPasswordConfirmation(undefined); // TODO: Vardan: maybe change this to empty string as for password? setPasswordConfirmation(''); } }, [showLogin, showRegister]); const handleHostInputChange = (event: TargetedEvent) => { const { value } = event.target as HTMLInputElement; // setUrl(value); setServer(value); application.setHost(value); }; const emailInputRef = useRef(); const passwordInputRef = useRef(); const passwordConfirmationInputRef = useRef(); const handleSignInClick = () => { setShowLogin(true); setIsEmailFocused(true); }; const handleRegisterClick = () => { setShowRegister(true); setIsEmailFocused(true); }; const blurAuthFields = () => { emailInputRef.current.blur(); passwordInputRef.current.blur(); passwordConfirmationInputRef.current?.blur(); }; const login = 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(''); closeAccountMenu(); return; } setShowLogin(true); setStatus(undefined); setPassword(''); if (error.message) { await application.alertService.alert(error.message); // await handleAlert(error.message); } setIsAuthenticating(false); }; const register = async () => { if (passwordConfirmation !== password) { application.alertService.alert(STRING_NON_MATCHING_PASSWORDS); // handleAlert(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); // handleAlert(error.message); } else { setIsAuthenticating(false); closeAccountMenu(); } }; const handleAuthFormSubmit = (event: TargetedEvent | TargetedMouseEvent | TargetedKeyboardEvent ) => { event.preventDefault(); if (!email || !password) { return; } blurAuthFields(); if (showLogin) { login(); } 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; if (!checked) { setShouldMergeLocal(checked); const confirmResult = await confirmDialog({ text: STRING_ACCOUNT_MENU_UNCHECK_MERGE, confirmButtonStyle: 'danger' }); setShouldMergeLocal(!confirmResult); } }; return ( <> {!user && !showLogin && !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.
)} {(showLogin || showRegister) && (
{showLogin ? 'Sign In' : 'Register'}
{showRegister && }
{showAdvanced && (
Advanced Options
{showLogin && ( )}
)} {!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;