import React, { useEffect } from 'react'; import classNames from 'classnames'; import styled from 'styled-components'; import autoBind from 'auto-bind'; import { isString } from 'lodash'; import { SessionButton, SessionButtonColor, SessionButtonType } from './basic/SessionButton'; import { SessionSpinner } from './basic/SessionSpinner'; import { SessionTheme } from '../themes/SessionTheme'; import { switchThemeTo } from '../themes/switchTheme'; import { ToastUtils } from '../session/utils'; import { SessionToastContainer } from './SessionToastContainer'; import { SessionWrapperModal } from './SessionWrapperModal'; import { switchPrimaryColorTo } from '../themes/switchPrimaryColor'; interface State { errorCount: number; clearDataView: boolean; loading: boolean; } export const MAX_LOGIN_TRIES = 3; const TextPleaseWait = (props: { isLoading: boolean }) => { if (!props.isLoading) { return null; } return
{window.i18n('pleaseWaitOpenAndOptimizeDb')}
; }; const StyledContent = styled.div` background-color: var(--background-secondary-color); height: 100%; width: 100%; `; class SessionPasswordPromptInner extends React.PureComponent { private inputRef?: any; constructor(props: any) { super(props); this.state = { errorCount: 0, clearDataView: false, loading: false, }; autoBind(this); } public componentDidMount() { setTimeout(() => { this.inputRef?.focus(); }, 100); } public render() { const isLoading = this.state.loading; const spinner = isLoading ? : null; const featureElement = this.state.clearDataView ? (

{window.i18n('deleteAccountFromLogin')}

) : (
{ this.inputRef = input; }} />
); return ( {spinner || featureElement} {this.state.clearDataView ? this.renderClearDataViewButtons() : this.renderPasswordViewButtons()} ); } public onKeyUp(event: any) { switch (event.key) { case 'Enter': this.initLogin(); break; default: } event.preventDefault(); } public async onLogin(passPhrase: string) { const passPhraseTrimmed = passPhrase.trim(); try { await window.onLogin(passPhraseTrimmed); } catch (error) { // Increment the error counter and show the button if necessary this.setState({ errorCount: this.state.errorCount + 1, }); if (error && isString(error)) { ToastUtils.pushToastError('onLogin', error); } else if (error?.message && isString(error.message)) { ToastUtils.pushToastError('onLogin', error.message); } global.setTimeout(() => { document.getElementById('password-prompt-input')?.focus(); }, 50); } this.setState({ loading: false, }); } private initLogin() { this.setState({ loading: true, }); const passPhrase = String((this.inputRef as HTMLInputElement).value); // this is to make sure a render has the time to happen before we lock the thread with all of the db work // this might be removed once we get the db operations to a worker thread global.setTimeout(() => { void this.onLogin(passPhrase); }, 100); } private initClearDataView() { this.setState({ errorCount: 0, clearDataView: true, }); } private renderPasswordViewButtons(): JSX.Element { const showResetElements = this.state.errorCount >= MAX_LOGIN_TRIES; return (
{showResetElements && ( <> )} {!this.state.loading && ( )}
); } private renderClearDataViewButtons(): JSX.Element { return (
{ this.setState({ clearDataView: false }); }} />
); } } export const SessionPasswordPrompt = () => { useEffect(() => { if (window.theme) { void switchThemeTo({ theme: window.theme, }); } if (window.primaryColor) { void switchPrimaryColorTo(window.primaryColor); } }, []); return ( ); };