Skip to content

Commit

Permalink
Desktop: Resolves #8380: Always show reencrypt button (#8555)
Browse files Browse the repository at this point in the history
  • Loading branch information
personalizedrefrigerator committed Aug 8, 2023
1 parent 5f7e130 commit 8696052
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 41 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Expand Up @@ -133,6 +133,7 @@ packages/app-desktop/gui/ClipperConfigScreen.js
packages/app-desktop/gui/ConfigScreen/ButtonBar.js
packages/app-desktop/gui/ConfigScreen/ConfigScreen.js
packages/app-desktop/gui/ConfigScreen/Sidebar.js
packages/app-desktop/gui/ConfigScreen/controls/ToggleAdvancedSettingsButton.js
packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginBox.js
packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginsStates.js
packages/app-desktop/gui/ConfigScreen/controls/plugins/SearchPlugins.js
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -119,6 +119,7 @@ packages/app-desktop/gui/ClipperConfigScreen.js
packages/app-desktop/gui/ConfigScreen/ButtonBar.js
packages/app-desktop/gui/ConfigScreen/ConfigScreen.js
packages/app-desktop/gui/ConfigScreen/Sidebar.js
packages/app-desktop/gui/ConfigScreen/controls/ToggleAdvancedSettingsButton.js
packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginBox.js
packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginsStates.js
packages/app-desktop/gui/ConfigScreen/controls/plugins/SearchPlugins.js
Expand Down
15 changes: 5 additions & 10 deletions packages/app-desktop/gui/ConfigScreen/ConfigScreen.tsx
Expand Up @@ -19,6 +19,7 @@ import PluginService from '@joplin/lib/services/plugins/PluginService';
import { getDefaultPluginsInstallState, updateDefaultPluginsInstallState } from '@joplin/lib/services/plugins/defaultPlugins/defaultPluginsUtils';
import getDefaultPluginsInfo from '@joplin/lib/services/plugins/defaultPlugins/desktopDefaultPluginsInfo';
import JoplinCloudConfigScreen from '../JoplinCloudConfigScreen';
import ToggleAdvancedSettingsButton from './controls/ToggleAdvancedSettingsButton';
const { KeymapConfigScreen } = require('../KeymapConfig/KeymapConfigScreen');

const settingKeyToControl: any = {
Expand Down Expand Up @@ -208,17 +209,11 @@ class ConfigScreenComponent extends React.Component<any, any> {
const advancedSettingsSectionStyle = { display: 'none' };

if (advancedSettingComps.length) {
const iconName = this.state.showAdvancedSettings ? 'fa fa-angle-down' : 'fa fa-angle-right';
// const advancedSettingsButtonStyle = { ...theme.buttonStyle, marginBottom: 10 };
advancedSettingsButton = (
<div style={{ marginBottom: 10 }}>
<Button
level={ButtonLevel.Secondary}
onClick={() => shared.advancedSettingsButton_click(this)}
iconName={iconName}
title={_('Show Advanced Settings')}
/>
</div>
<ToggleAdvancedSettingsButton
onClick={() => shared.advancedSettingsButton_click(this)}
advancedSettingsVisible={this.state.showAdvancedSettings}
/>
);
advancedSettingsSectionStyle.display = this.state.showAdvancedSettings ? 'block' : 'none';
}
Expand Down
@@ -0,0 +1,24 @@

import * as React from 'react';
import Button, { ButtonLevel } from '../../Button/Button';
import { _ } from '@joplin/lib/locale';

interface Props {
onClick: ()=> void;
advancedSettingsVisible: boolean;
}

const ToggleAdvancedSettingsButton: React.FunctionComponent<Props> = props => {
const iconName = props.advancedSettingsVisible ? 'fa fa-angle-down' : 'fa fa-angle-right';
return (
<div style={{ marginBottom: 10 }}>
<Button
level={ButtonLevel.Secondary}
onClick={props.onClick}
iconName={iconName}
title={_('Show Advanced Settings')}
/>
</div>
);
};
export default ToggleAdvancedSettingsButton;
Expand Up @@ -10,12 +10,13 @@ import { MasterKeyEntity } from '@joplin/lib/services/e2ee/types';
import { getEncryptionEnabled, masterKeyEnabled, SyncInfo } from '@joplin/lib/services/synchronizer/syncInfoUtils';
import { getDefaultMasterKey, getMasterPasswordStatusMessage, masterPasswordIsValid, toggleAndSetupEncryption } from '@joplin/lib/services/e2ee/utils';
import Button, { ButtonLevel } from '../Button/Button';
import { useCallback, useMemo } from 'react';
import { useCallback, useMemo, useState } from 'react';
import { connect } from 'react-redux';
import { AppState } from '../../app.reducer';
import Setting from '@joplin/lib/models/Setting';
import CommandService from '@joplin/lib/services/CommandService';
import { PublicPrivateKeyPair } from '@joplin/lib/services/e2ee/ppk';
import ToggleAdvancedSettingsButton from '../ConfigScreen/controls/ToggleAdvancedSettingsButton';

interface Props {
themeId: any;
Expand Down Expand Up @@ -83,34 +84,6 @@ const EncryptionConfigScreen = (props: Props) => {
);
};

const renderReencryptData = () => {
if (!shim.isElectron()) return null;
if (!props.shouldReencrypt) return null;

const theme = themeStyle(props.themeId);
const buttonLabel = _('Re-encrypt data');

const intro = props.shouldReencrypt ? _('The default encryption method has been changed to a more secure one and it is recommended that you apply it to your data.') : _('You may use the tool below to re-encrypt your data, for example if you know that some of your notes are encrypted with an obsolete encryption method.');

let t = `${intro}\n\n${_('In order to do so, your entire data set will have to be encrypted and synchronised, so it is best to run it overnight.\n\nTo start, please follow these instructions:\n\n1. Synchronise all your devices.\n2. Click "%s".\n3. Let it run to completion. While it runs, avoid changing any note on your other devices, to avoid conflicts.\n4. Once sync is done on this device, sync all your other devices and let it run to completion.\n\nImportant: you only need to run this ONCE on one device.', buttonLabel)}`;

t = t.replace(/\n\n/g, '</p><p>');
t = t.replace(/\n/g, '<br>');
t = `<p>${t}</p>`;

return (
<div>
<h2>{_('Re-encryption')}</h2>
<p style={theme.textStyle} dangerouslySetInnerHTML={{ __html: t }}></p>
<span style={{ marginRight: 10 }}>
<button onClick={() => void reencryptData()} style={theme.buttonStyle}>{buttonLabel}</button>
</span>

{ !props.shouldReencrypt ? null : <button onClick={() => dontReencryptData()} style={theme.buttonStyle}>{_('Ignore')}</button> }
</div>
);
};

const renderMasterKey = (mk: MasterKeyEntity) => {
const theme = themeStyle(props.themeId);

Expand Down Expand Up @@ -239,7 +212,6 @@ const EncryptionConfigScreen = (props: Props) => {
/>
);
const needUpgradeSection = renderNeedUpgradeSection();
const reencryptDataSection = renderReencryptData();

return (
<div className="section">
Expand All @@ -254,7 +226,6 @@ const EncryptionConfigScreen = (props: Props) => {
{decryptedItemsInfo}
{toggleButton}
{needUpgradeSection}
{props.shouldReencrypt ? reencryptDataSection : null}
</div>
</div>
);
Expand Down Expand Up @@ -338,6 +309,56 @@ const EncryptionConfigScreen = (props: Props) => {
return nonExistingMasterKeySection;
};

const renderReencryptData = () => {
if (!shim.isElectron()) return null;
if (!props.encryptionEnabled) return null;

const theme = themeStyle(props.themeId);
const buttonLabel = _('Re-encrypt data');

const intro = props.shouldReencrypt ? _('The default encryption method has been changed to a more secure one and it is recommended that you apply it to your data.') : _('You may use the tool below to re-encrypt your data, for example if you know that some of your notes are encrypted with an obsolete encryption method.');

let t = `${intro}\n\n${_('In order to do so, your entire data set will have to be encrypted and synchronised, so it is best to run it overnight.\n\nTo start, please follow these instructions:\n\n1. Synchronise all your devices.\n2. Click "%s".\n3. Let it run to completion. While it runs, avoid changing any note on your other devices, to avoid conflicts.\n4. Once sync is done on this device, sync all your other devices and let it run to completion.\n\nImportant: you only need to run this ONCE on one device.', buttonLabel)}`;

t = t.replace(/\n\n/g, '</p><p>');
t = t.replace(/\n/g, '<br>');
t = `<p>${t}</p>`;

return (
<div>
<h2>{_('Re-encryption')}</h2>
<p style={theme.textStyle} dangerouslySetInnerHTML={{ __html: t }}></p>
<span style={{ marginRight: 10 }}>
<button onClick={() => void reencryptData()} style={theme.buttonStyle}>{buttonLabel}</button>
</span>

{ !props.shouldReencrypt ? null : <button onClick={() => dontReencryptData()} style={theme.buttonStyle}>{_('Ignore')}</button> }
</div>
);
};

// If the user should re-encrypt, ensure that the section is visible initially.
const [showAdvanced, setShowAdvanced] = useState<boolean>(props.shouldReencrypt);
const toggleAdvanced = useCallback(() => {
setShowAdvanced(!showAdvanced);
}, [showAdvanced]);

const renderAdvancedSection = () => {
const reEncryptSection = renderReencryptData();

if (!reEncryptSection) return null;


return (
<div>
<ToggleAdvancedSettingsButton
onClick={toggleAdvanced}
advancedSettingsVisible={showAdvanced}/>
{ showAdvanced ? reEncryptSection : null }
</div>
);
};

return (
<div className="config-screen-content">
{renderDebugSection()}
Expand All @@ -346,6 +367,7 @@ const EncryptionConfigScreen = (props: Props) => {
{renderMasterKeySection(props.masterKeys.filter(mk => masterKeyEnabled(mk)), true)}
{renderMasterKeySection(props.masterKeys.filter(mk => !masterKeyEnabled(mk)), false)}
{renderNonExistingMasterKeysSection()}
{renderAdvancedSection()}
</div>
);
};
Expand Down

0 comments on commit 8696052

Please sign in to comment.