refactor: migrate account-menu to react - implement functionality

- remove all Angular code related to `account-menu`
- rename React component to AccountMenu so that many parts of old code remain unchanged
- code cleanup
This commit is contained in:
VardanHakobyan
2021-06-07 20:30:49 +04:00
parent 6db97436b8
commit 7f11e25e63
14 changed files with 430 additions and 1427 deletions

View File

@@ -32,6 +32,7 @@ import TargetedKeyboardEvent = JSXInternal.TargetedKeyboardEvent;
import TargetedMouseEvent = JSXInternal.TargetedMouseEvent;
import { alertDialog, confirmDialog } from '@Services/alertService';
import { RefObject } from 'react';
import { ConfirmSignoutContainer } from '@/components/ConfirmSignoutModal';
type Props = {
appState: AppState;
@@ -367,7 +368,7 @@ const AccountMenu = observer(({ application, appState, closeAccountMenu }: Props
};
const signOut = () => {
appState.accountMenuReact.setSigningOut(true);
appState.accountMenu.setSigningOut(true);
};
const changePasscodePressed = () => {
@@ -526,118 +527,109 @@ const AccountMenu = observer(({ application, appState, closeAccountMenu }: Props
}, [refreshEncryptionStatus]);
return (
<div style={{
top: '-70px',
right: '-450px',
width: '100px',
height: '100px',
background: 'green',
zIndex: 100,
position: 'absolute'
}}>
<div className='sn-component'>
<div id='account-panel-react' className='sk-panel'>
<div className='sk-panel-header'>
<div className='sk-panel-header-title'>Account</div>
<a className='sk-a info close-button' onClick={closeAccountMenu}>Close</a>
</div>
<div className='sk-panel-content'>
{!user && !showLogin && !showRegister && (
<div className='sk-panel-section sk-panel-hero'>
<div className='sk-panel-row'>
<div className='sk-h1'>Sign in or register to enable sync and end-to-end encryption.</div>
</div>
<div className='flex my-1'>
<button
className='sn-button info flex-grow text-base py-3 mr-1.5'
onClick={handleSignInClick}
>
Sign In
</button>
<button
className='sn-button info flex-grow text-base py-3 ml-1.5'
onClick={handleRegisterClick}
>
Register
</button>
</div>
<div className='sk-panel-row sk-p'>
Standard Notes is free on every platform, and comes
standard with sync and encryption.
</div>
<div className='sn-component'>
<div id='account-panel' className='sk-panel'>
<div className='sk-panel-header'>
<div className='sk-panel-header-title'>Account</div>
<a className='sk-a info close-button' onClick={closeAccountMenu}>Close</a>
</div>
<div className='sk-panel-content'>
{!user && !showLogin && !showRegister && (
<div className='sk-panel-section sk-panel-hero'>
<div className='sk-panel-row'>
<div className='sk-h1'>Sign in or register to enable sync and end-to-end encryption.</div>
</div>
)}
{(showLogin || showRegister) && (
<div className='sk-panel-section'>
<div className='sk-panel-section-title'>
{showLogin ? 'Sign In' : 'Register'}
<div className='flex my-1'>
<button
className='sn-button info flex-grow text-base py-3 mr-1.5'
onClick={handleSignInClick}
>
Sign In
</button>
<button
className='sn-button info flex-grow text-base py-3 ml-1.5'
onClick={handleRegisterClick}
>
Register
</button>
</div>
<div className='sk-panel-row sk-p'>
Standard Notes is free on every platform, and comes
standard with sync and encryption.
</div>
</div>
)}
{(showLogin || showRegister) && (
<div className='sk-panel-section'>
<div className='sk-panel-section-title'>
{showLogin ? 'Sign In' : 'Register'}
</div>
<form className='sk-panel-form' onSubmit={handleAuthFormSubmit} noValidate>
<div className='sk-panel-section'>
<input className='sk-input contrast'
name='email'
type='email'
value={email}
onChange={handleEmailChange}
placeholder='Email'
required
spellCheck={false}
ref={emailInputRef}
/>
<input className='sk-input contrast'
name='password'
type='password'
value={password}
onChange={handlePasswordChange}
placeholder='Password'
required
onKeyPress={handleKeyPressKeyDown}
onKeyDown={handleKeyPressKeyDown}
ref={passwordInputRef}
/>
{showRegister &&
<input className='sk-input contrast'
name='password_conf'
type='password'
placeholder='Confirm Password' required
onKeyPress={handleKeyPressKeyDown}
onKeyDown={handleKeyPressKeyDown}
value={passwordConfirmation}
onChange={handlePasswordConfirmationChange}
/>}
<div className='sk-panel-row' />
<a className='sk-panel-row sk-bold' onClick={() => {
setShowAdvanced(showAdvanced => !showAdvanced);
}}>
Advanced Options
</a>
</div>
<form className='sk-panel-form' onSubmit={handleAuthFormSubmit} noValidate>
<div className='sk-panel-section'>
<input className='sk-input contrast'
name='email'
type='email'
value={email}
onChange={handleEmailChange}
placeholder='Email'
required
spellCheck={false}
ref={emailInputRef}
/>
<input className='sk-input contrast'
name='password'
type='password'
value={password}
onChange={handlePasswordChange}
placeholder='Password'
required
onKeyPress={handleKeyPressKeyDown}
onKeyDown={handleKeyPressKeyDown}
ref={passwordInputRef}
/>
{showRegister &&
<input className='sk-input contrast'
name='password_conf'
type='password'
placeholder='Confirm Password' required
onKeyPress={handleKeyPressKeyDown}
onKeyDown={handleKeyPressKeyDown}
value={passwordConfirmation}
onChange={handlePasswordConfirmationChange}
/>}
<div className='sk-panel-row' />
<a className='sk-panel-row sk-bold' onClick={() => {
setShowAdvanced(showAdvanced => !showAdvanced);
}}>
Advanced Options
</a>
</div>
{showAdvanced && (
<div className='sk-notification unpadded contrast advanced-options sk-panel-row'>
<div className='sk-panel-column stretch'>
<div className='sk-notification-title sk-panel-row padded-row'>
Advanced Options
</div>
<div className='bordered-row padded-row'>
<label className='sk-label'>Sync Server Domain</label>
<input className='sk-input sk-base'
name='server'
placeholder='Server URL'
onChange={handleHostInputChange}
value={url}
required
/>
</div>
{showLogin && (
<label className='sk-label padded-row sk-panel-row justify-left'>
<div className='sk-horizontal-group tight'>
<input
className='sk-input'
type='checkbox'
onChange={() => setIsStrictSignIn(prevState => !prevState)}
/>
<p className='sk-p'>Use strict sign in</p>
<span>
{showAdvanced && (
<div className='sk-notification unpadded contrast advanced-options sk-panel-row'>
<div className='sk-panel-column stretch'>
<div className='sk-notification-title sk-panel-row padded-row'>
Advanced Options
</div>
<div className='bordered-row padded-row'>
<label className='sk-label'>Sync Server Domain</label>
<input className='sk-input sk-base'
name='server'
placeholder='Server URL'
onChange={handleHostInputChange}
value={url}
required
/>
</div>
{showLogin && (
<label className='sk-label padded-row sk-panel-row justify-left'>
<div className='sk-horizontal-group tight'>
<input
className='sk-input'
type='checkbox'
onChange={() => setIsStrictSignIn(prevState => !prevState)}
/>
<p className='sk-p'>Use strict sign in</p>
<span>
<a className='info'
href='https://standardnotes.org/help/security' rel='noopener'
target='_blank'
@@ -645,340 +637,340 @@ const AccountMenu = observer(({ application, appState, closeAccountMenu }: Props
(Learn more)
</a>
</span>
</div>
</label>
)}
</div>
</div>
)}
{!isAuthenticating && (
<div className='sk-panel-section form-submit'>
<button className='sn-button info text-base py-3 text-center' type='submit'
disabled={isAuthenticating}>
{showLogin ? 'Sign In' : 'Register'}
</button>
</div>
)}
{showRegister && (
<div className='sk-notification neutral'>
<div className='sk-notification-title'>No Password Reset.</div>
<div className='sk-notification-text'>
Because your notes are encrypted using your password,
Standard Notes does not have a password reset option.
You cannot forget your password.
</div>
</div>
)}
{status && (
<div className='sk-panel-section no-bottom-pad'>
<div className='sk-horizontal-group'>
<div className='sk-spinner small neutral' />
<div className='sk-label'>{status}</div>
</div>
</div>
)}
{!isAuthenticating && (
<div className='sk-panel-section no-bottom-pad'>
<label className='sk-panel-row justify-left'>
<div className='sk-horizontal-group tight'>
<input
type='checkbox'
checked={!isEphemeral}
onChange={() => setIsEphemeral(prevState => !prevState)}
/>
<p className='sk-p'>Stay signed in</p>
</div>
</label>
{notesAndTagsCount > 0 && (
<label className='sk-panel-row justify-left'>
<div className='sk-horizontal-group tight'>
<input
type='checkbox'
checked={shouldMergeLocal}
onChange={handleMergeLocalData}
/>
<p className='sk-p'>Merge local data ({notesAndTagsCount}) notes and tags</p>
</div>
</label>
)}
</div>
)}
</form>
</div>
)}
{!showLogin && !showRegister && (
<div>
{user && (
<div className='sk-panel-section'>
{syncError && (
<div className='sk-notification danger'>
<div className='sk-notification-title'>Sync Unreachable</div>
<div className='sk-notification-text'>
Hmm...we can't seem to sync your account.
The reason: {syncError}
</div>
<a
className='sk-a info-contrast sk-bold sk-panel-row'
href='https://standardnotes.org/help'
rel='noopener'
target='_blank'
>
Need help?
</a>
</div>
)}
<div className='sk-panel-row'>
<div className='sk-panel-column'>
<div className='sk-h1 sk-bold wrap'>
{user.email}
</div>
<div className='sk-subtitle neutral'>
{server}
</div>
</div>
</div>
<div className='sk-panel-row' />
<a className='sk-a info sk-panel-row condensed' onClick={openPasswordWizard}>
Change Password
</a>
<a className='sk-a info sk-panel-row condensed' onClick={openSessionsModal}>
Manage Sessions
</a>
</div>
)}
<div className='sk-panel-section'>
<div className='sk-panel-section-title'>
Encryption
</div>
{isEncryptionEnabled && (
<div className='sk-panel-section-subtitle info'>
{getEncryptionStatusForNotes()}
</div>
)}
<p className='sk-p'>
{encryptionStatusString}
</p>
</div>
{hasProtections && (
<div className='sk-panel-section'>
<div className='sk-panel-section-title'>Protections</div>
{protectionsDisabledUntil && (
<div className='sk-panel-section-subtitle info'>
Protections are disabled until {protectionsDisabledUntil}
</div>
)}
{!protectionsDisabledUntil && (
<div className='sk-panel-section-subtitle info'>
Protections are enabled
</div>
)}
<p className='sk-p'>
Actions like viewing protected notes, exporting decrypted backups,
or revoking an active session, require additional authentication
like entering your account password or application passcode.
</p>
{protectionsDisabledUntil && (
<div className='sk-panel-row'>
<button className='sn-button small info' onClick={enableProtections}>
Enable protections
</button>
</div>
)}
</div>
)}
<div className='sk-panel-section'>
<div className='sk-panel-section-title'>Passcode Lock</div>
{!hasPasscode && (
<div>
{canAddPasscode && (
<>
{!showPasscodeForm && (
<div className='sk-panel-row'>
<button className='sn-button small info' onClick={handleAddPassCode}>
Add Passcode
</button>
</div>
)}
<p className='sk-p'>
Add a passcode to lock the application and
encrypt on-device key storage.
</p>
{keyStorageInfo && (
<p>{keyStorageInfo}</p>
)}
</>
)}
{!canAddPasscode && (
<p className='sk-p'>
Adding a passcode is not supported in temporary sessions. Please sign
out, then sign back in with the "Stay signed in" option checked.
</p>
)}
</div>
)}
{showPasscodeForm && (
<form className='sk-panel-form' onSubmit={submitPasscodeForm}>
<div className='sk-panel-row' />
<input
className='sk-input contrast'
type='password'
ref={passcodeInputRef}
value={passcode}
onChange={handlePasscodeChange}
placeholder='Passcode'
/>
<input
className='sk-input contrast'
type='password'
value={passcodeConfirmation}
onChange={handleConfirmPasscodeChange}
placeholder='Confirm Passcode'
/>
<button className='sn-button small info mt-2' onClick={submitPasscodeForm}>
Set Passcode
</button>
<button className='sn-button small outlined ml-2' onClick={() => setShowPasscodeForm(false)}>
Cancel
</button>
</form>
)}
{hasPasscode && !showPasscodeForm && (
<>
<div className='sk-panel-section-subtitle info'>Passcode lock is enabled</div>
<div className='sk-notification contrast'>
<div className='sk-notification-title'>Options</div>
<div className='sk-notification-text'>
<div className='sk-panel-row'>
<div className='sk-horizontal-group'>
<div className='sk-h4 sk-bold'>Autolock</div>
{passcodeAutoLockOptions.map(option => {
return (
<a
className={`sk-a info ${option.value === selectedAutoLockInterval ? 'boxed' : ''}`}
onClick={() => selectAutoLockInterval(option.value)}>
{option.label}
</a>
);
})}
</div>
</div>
<div className='sk-p'>The autolock timer begins when the window or tab loses focus.</div>
<div className='sk-panel-row' />
<a className='sk-a info sk-panel-row condensed' onClick={changePasscodePressed}>
Change Passcode
</a>
<a className='sk-a danger sk-panel-row condensed' onClick={removePasscodePressed}>
Remove Passcode
</a>
</div>
</div>
</>
)}
</div>
{!isImportDataLoading && (
<div className='sk-panel-section'>
<div className='sk-panel-section-title'>Data Backups</div>
<div className='sk-p'>Download a backup of all your data.</div>
{isEncryptionEnabled && (
<form className='sk-panel-form sk-panel-row'>
<div className='sk-input-group'>
<label className='sk-horizontal-group tight'>
<input
type='radio'
onChange={() => setIsBackupEncrypted(true)}
checked={isBackupEncrypted}
/>
<p className='sk-p'>Encrypted</p>
</label>
<label className='sk-horizontal-group tight'>
<input
type='radio'
onChange={() => setIsBackupEncrypted(false)}
checked={!isBackupEncrypted}
/>
<p className='sk-p'>Decrypted</p>
</label>
</div>
</form>
)}
<div className='sk-panel-row' />
<div className='flex'>
<button className='sn-button small info' onClick={downloadDataArchive}>Download Backup</button>
<label className='sn-button small flex items-center info ml-2'>
<input
type='file'
onChange={importFileSelected}
style={{ display: 'none' }}
/>
Import Backup
</label>
</div>
{isDesktopApplication() && (
<p className='mt-5'>
Backups are automatically created on desktop and can be managed
via the "Backups" top-level menu.
</p>
)}
<div className='sk-panel-row' />
{isImportDataLoading && (
<div className='sk-spinner small info' />
)}
</div>
)}
<div className='sk-panel-section'>
<div className='sk-panel-section-title'>Error Reporting</div>
<div className='sk-panel-section-subtitle info'>
Automatic error reporting is {isErrorReportingEnabled ? 'enabled' : 'disabled'}
</div>
<p className='sk-p'>
Help us improve Standard Notes by automatically submitting
anonymized error reports.
</p>
{errorReportingIdValue && (
<>
<p className='sk-p selectable'>
Your random identifier is
strong {errorReportingIdValue}
</p>
<p className='sk-p'>
Disabling error reporting will remove that identifier from your
local storage, and a new identifier will be created should you
decide to enable error reporting again in the future.
</p>
</>
)}
<div className='sk-panel-row'>
<button className='sn-button small info' onClick={toggleErrorReportingEnabled}>
{isErrorReportingEnabled ? 'Disable' : 'Enable'} Error Reporting
{!isAuthenticating && (
<div className='sk-panel-section form-submit'>
<button className='sn-button info text-base py-3 text-center' type='submit'
disabled={isAuthenticating}>
{showLogin ? 'Sign In' : 'Register'}
</button>
</div>
<div className='sk-panel-row'>
<a className='sk-a' onClick={openErrorReportingDialog}>What data is being sent?</a>
)}
{showRegister && (
<div className='sk-notification neutral'>
<div className='sk-notification-title'>No Password Reset.</div>
<div className='sk-notification-text'>
Because your notes are encrypted using your password,
Standard Notes does not have a password reset option.
You cannot forget your password.
</div>
</div>
)}
{status && (
<div className='sk-panel-section no-bottom-pad'>
<div className='sk-horizontal-group'>
<div className='sk-spinner small neutral' />
<div className='sk-label'>{status}</div>
</div>
</div>
)}
{!isAuthenticating && (
<div className='sk-panel-section no-bottom-pad'>
<label className='sk-panel-row justify-left'>
<div className='sk-horizontal-group tight'>
<input
type='checkbox'
checked={!isEphemeral}
onChange={() => setIsEphemeral(prevState => !prevState)}
/>
<p className='sk-p'>Stay signed in</p>
</div>
</label>
{notesAndTagsCount > 0 && (
<label className='sk-panel-row justify-left'>
<div className='sk-horizontal-group tight'>
<input
type='checkbox'
checked={shouldMergeLocal}
onChange={handleMergeLocalData}
/>
<p className='sk-p'>Merge local data ({notesAndTagsCount}) notes and tags</p>
</div>
</label>
)}
</div>
)}
</form>
</div>
)}
{!showLogin && !showRegister && (
<div>
{user && (
<div className='sk-panel-section'>
{syncError && (
<div className='sk-notification danger'>
<div className='sk-notification-title'>Sync Unreachable</div>
<div className='sk-notification-text'>
Hmm...we can't seem to sync your account.
The reason: {syncError}
</div>
<a
className='sk-a info-contrast sk-bold sk-panel-row'
href='https://standardnotes.org/help'
rel='noopener'
target='_blank'
>
Need help?
</a>
</div>
)}
<div className='sk-panel-row'>
<div className='sk-panel-column'>
<div className='sk-h1 sk-bold wrap'>
{user.email}
</div>
<div className='sk-subtitle neutral'>
{server}
</div>
</div>
</div>
<div className='sk-panel-row' />
<a className='sk-a info sk-panel-row condensed' onClick={openPasswordWizard}>
Change Password
</a>
<a className='sk-a info sk-panel-row condensed' onClick={openSessionsModal}>
Manage Sessions
</a>
</div>
)}
<div className='sk-panel-section'>
<div className='sk-panel-section-title'>
Encryption
</div>
{isEncryptionEnabled && (
<div className='sk-panel-section-subtitle info'>
{getEncryptionStatusForNotes()}
</div>
)}
<p className='sk-p'>
{encryptionStatusString}
</p>
</div>
)}
</div>
<div className='sk-panel-footer'>
<div className='sk-panel-row'>
<div className='sk-p left neutral'>
<span>{appVersion}</span>
{showBetaWarning && (
<span>
<a className='sk-a' onClick={disableBetaWarning}>Hide beta warning</a>
</span>
{hasProtections && (
<div className='sk-panel-section'>
<div className='sk-panel-section-title'>Protections</div>
{protectionsDisabledUntil && (
<div className='sk-panel-section-subtitle info'>
Protections are disabled until {protectionsDisabledUntil}
</div>
)}
{!protectionsDisabledUntil && (
<div className='sk-panel-section-subtitle info'>
Protections are enabled
</div>
)}
<p className='sk-p'>
Actions like viewing protected notes, exporting decrypted backups,
or revoking an active session, require additional authentication
like entering your account password or application passcode.
</p>
{protectionsDisabledUntil && (
<div className='sk-panel-row'>
<button className='sn-button small info' onClick={enableProtections}>
Enable protections
</button>
</div>
)}
</div>
)}
<div className='sk-panel-section'>
<div className='sk-panel-section-title'>Passcode Lock</div>
{!hasPasscode && (
<div>
{canAddPasscode && (
<>
{!showPasscodeForm && (
<div className='sk-panel-row'>
<button className='sn-button small info' onClick={handleAddPassCode}>
Add Passcode
</button>
</div>
)}
<p className='sk-p'>
Add a passcode to lock the application and
encrypt on-device key storage.
</p>
{keyStorageInfo && (
<p>{keyStorageInfo}</p>
)}
</>
)}
{!canAddPasscode && (
<p className='sk-p'>
Adding a passcode is not supported in temporary sessions. Please sign
out, then sign back in with the "Stay signed in" option checked.
</p>
)}
</div>
)}
{showPasscodeForm && (
<form className='sk-panel-form' onSubmit={submitPasscodeForm}>
<div className='sk-panel-row' />
<input
className='sk-input contrast'
type='password'
ref={passcodeInputRef}
value={passcode}
onChange={handlePasscodeChange}
placeholder='Passcode'
/>
<input
className='sk-input contrast'
type='password'
value={passcodeConfirmation}
onChange={handleConfirmPasscodeChange}
placeholder='Confirm Passcode'
/>
<button className='sn-button small info mt-2' onClick={submitPasscodeForm}>
Set Passcode
</button>
<button className='sn-button small outlined ml-2' onClick={() => setShowPasscodeForm(false)}>
Cancel
</button>
</form>
)}
{hasPasscode && !showPasscodeForm && (
<>
<div className='sk-panel-section-subtitle info'>Passcode lock is enabled</div>
<div className='sk-notification contrast'>
<div className='sk-notification-title'>Options</div>
<div className='sk-notification-text'>
<div className='sk-panel-row'>
<div className='sk-horizontal-group'>
<div className='sk-h4 sk-bold'>Autolock</div>
{passcodeAutoLockOptions.map(option => {
return (
<a
className={`sk-a info ${option.value === selectedAutoLockInterval ? 'boxed' : ''}`}
onClick={() => selectAutoLockInterval(option.value)}>
{option.label}
</a>
);
})}
</div>
</div>
<div className='sk-p'>The autolock timer begins when the window or tab loses focus.</div>
<div className='sk-panel-row' />
<a className='sk-a info sk-panel-row condensed' onClick={changePasscodePressed}>
Change Passcode
</a>
<a className='sk-a danger sk-panel-row condensed' onClick={removePasscodePressed}>
Remove Passcode
</a>
</div>
</div>
</>
)}
</div>
{(showLogin || showRegister) && (
<a className='sk-a right' onClick={hidePasswordForm}>Cancel</a>
{!isImportDataLoading && (
<div className='sk-panel-section'>
<div className='sk-panel-section-title'>Data Backups</div>
<div className='sk-p'>Download a backup of all your data.</div>
{isEncryptionEnabled && (
<form className='sk-panel-form sk-panel-row'>
<div className='sk-input-group'>
<label className='sk-horizontal-group tight'>
<input
type='radio'
onChange={() => setIsBackupEncrypted(true)}
checked={isBackupEncrypted}
/>
<p className='sk-p'>Encrypted</p>
</label>
<label className='sk-horizontal-group tight'>
<input
type='radio'
onChange={() => setIsBackupEncrypted(false)}
checked={!isBackupEncrypted}
/>
<p className='sk-p'>Decrypted</p>
</label>
</div>
</form>
)}
<div className='sk-panel-row' />
<div className='flex'>
<button className='sn-button small info' onClick={downloadDataArchive}>Download Backup</button>
<label className='sn-button small flex items-center info ml-2'>
<input
type='file'
onChange={importFileSelected}
style={{ display: 'none' }}
/>
Import Backup
</label>
</div>
{isDesktopApplication() && (
<p className='mt-5'>
Backups are automatically created on desktop and can be managed
via the "Backups" top-level menu.
</p>
)}
<div className='sk-panel-row' />
{isImportDataLoading && (
<div className='sk-spinner small info' />
)}
</div>
)}
{!showLogin && !showRegister && (
<a className='sk-a right danger capitalize' onClick={signOut}>
{user ? 'Sign out' : 'Clear session data'}
</a>
<div className='sk-panel-section'>
<div className='sk-panel-section-title'>Error Reporting</div>
<div className='sk-panel-section-subtitle info'>
Automatic error reporting is {isErrorReportingEnabled ? 'enabled' : 'disabled'}
</div>
<p className='sk-p'>
Help us improve Standard Notes by automatically submitting
anonymized error reports.
</p>
{errorReportingIdValue && (
<>
<p className='sk-p selectable'>
Your random identifier is
strong {errorReportingIdValue}
</p>
<p className='sk-p'>
Disabling error reporting will remove that identifier from your
local storage, and a new identifier will be created should you
decide to enable error reporting again in the future.
</p>
</>
)}
<div className='sk-panel-row'>
<button className='sn-button small info' onClick={toggleErrorReportingEnabled}>
{isErrorReportingEnabled ? 'Disable' : 'Enable'} Error Reporting
</button>
</div>
<div className='sk-panel-row'>
<a className='sk-a' onClick={openErrorReportingDialog}>What data is being sent?</a>
</div>
</div>
</div>
)}
</div>
<ConfirmSignoutContainer application={application} appState={appState} />
<div className='sk-panel-footer'>
<div className='sk-panel-row'>
<div className='sk-p left neutral'>
<span>{appVersion}</span>
{showBetaWarning && (
<span>
<a className='sk-a' onClick={disableBetaWarning}>Hide beta warning</a>
</span>
)}
</div>
{(showLogin || showRegister) && (
<a className='sk-a right' onClick={hidePasswordForm}>Cancel</a>
)}
{!showLogin && !showRegister && (
<a className='sk-a right danger capitalize' onClick={signOut}>
{user ? 'Sign out' : 'Clear session data'}
</a>
)}
</div>
</div>
</div>
@@ -986,7 +978,7 @@ const AccountMenu = observer(({ application, appState, closeAccountMenu }: Props
);
});
export const AccountMenuReact = toDirective<Props>(
export const AccountMenuDirective = toDirective<Props>(
AccountMenu,
{ closeAccountMenu: '&' }
);

View File

@@ -15,13 +15,10 @@ type Props = {
appState: AppState;
};
const ConfirmSignoutContainer = observer((props: Props) => {
export const ConfirmSignoutContainer = observer((props: Props) => {
if (!props.appState.accountMenu.signingOut) {
return null;
}
if (!props.appState.accountMenuReact.signingOut) {
return null;
}
return <ConfirmSignoutModal {...props} />;
});
@@ -33,14 +30,13 @@ const ConfirmSignoutModal = observer(({ application, appState }: Props) => {
const cancelRef = useRef<HTMLButtonElement>();
function close() {
appState.accountMenu.setSigningOut(false);
appState.accountMenuReact.setSigningOut(false);
}
const [localBackupsCount, setLocalBackupsCount] = useState(0);
useEffect(() => {
application.bridge.localBackupsCount().then(setLocalBackupsCount);
}, [appState.accountMenu.signingOut, appState.accountMenuReact.signingOut, application.bridge]);
}, [appState.accountMenu.signingOut, application.bridge]);
return (
<AlertDialog onDismiss={close} leastDestructiveRef={cancelRef}>

View File

@@ -21,7 +21,6 @@ const NoAccountWarning = observer(({ appState }: Props) => {
onClick={(event) => {
event.stopPropagation();
appState.accountMenu.setShow(true);
appState.accountMenuReact.setShow(true);
}}
>
Open Account menu

View File

@@ -16,7 +16,6 @@ function NoProtectionsNoteWarning({ appState, onViewNote }: Props) {
className="sn-button small info"
onClick={() => {
appState.accountMenu.setShow(true);
appState.accountMenuReact.setShow(true);
}}
>
Open account menu