mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Desktop: Group config options into sections
This commit is contained in:
parent
394cc78851
commit
beaba2be55
@ -43,6 +43,45 @@ class ConfigScreenComponent extends React.Component {
|
||||
return output;
|
||||
}
|
||||
|
||||
sectionToComponent(key, section, settings) {
|
||||
const theme = themeStyle(this.props.theme);
|
||||
const settingComps = [];
|
||||
|
||||
for (let i = 0; i < section.metadatas.length; i++) {
|
||||
const md = section.metadatas[i];
|
||||
|
||||
const settingComp = this.settingToComponent(md.key, settings[md.key]);
|
||||
settingComps.push(settingComp);
|
||||
}
|
||||
|
||||
const sectionStyle = {
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: theme.dividerColor,
|
||||
borderTopStyle: 'solid',
|
||||
marginBottom: 20,
|
||||
};
|
||||
|
||||
if (section.name === 'general') {
|
||||
sectionStyle.borderTopWidth = 0;
|
||||
}
|
||||
|
||||
const noteComp = section.name !== 'general' ? null : (
|
||||
<div style={Object.assign({}, theme.textStyle, {marginBottom: 10})}>
|
||||
{_('Notes and settings are stored in: %s', pathUtils.toSystemSlashes(Setting.value('profileDir'), process.platform))}
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div key={key} style={sectionStyle}>
|
||||
<h2 style={theme.headerStyle}>{Setting.sectionNameToLabel(section.name)}</h2>
|
||||
{noteComp}
|
||||
<div>
|
||||
{settingComps}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
settingToComponent(key, value) {
|
||||
const theme = themeStyle(this.props.theme);
|
||||
|
||||
@ -172,19 +211,20 @@ class ConfigScreenComponent extends React.Component {
|
||||
const theme = themeStyle(this.props.theme);
|
||||
const style = Object.assign({
|
||||
backgroundColor: theme.backgroundColor
|
||||
}, this.props.style, { overflow: 'auto' });
|
||||
const settings = this.state.settings;
|
||||
}, this.props.style, { overflowX: 'hidden', overflowY: 'auto' });
|
||||
let settings = this.state.settings;
|
||||
|
||||
const headerStyle = Object.assign({}, theme.headerStyle, { width: style.width });
|
||||
|
||||
const containerStyle = Object.assign({}, theme.containerStyle, { padding: 10 });
|
||||
const containerStyle = Object.assign({}, theme.containerStyle, { padding: 10, paddingTop: 0 });
|
||||
|
||||
const buttonStyle = Object.assign({}, theme.buttonStyle, {
|
||||
display: this.state.changedSettingKeys.length ? 'inline-block' : 'none',
|
||||
marginRight: 10,
|
||||
});
|
||||
|
||||
const settingComps = shared.settingsToComponents(this, 'desktop', settings);
|
||||
//const settingComps = shared.settingsToComponents(this, 'desktop', settings);
|
||||
const settingComps = shared.settingsToComponents2(this, 'desktop', settings);
|
||||
|
||||
const syncTargetMd = SyncTargetRegistry.idToMetadata(settings['sync.target']);
|
||||
|
||||
@ -208,9 +248,6 @@ class ConfigScreenComponent extends React.Component {
|
||||
<div style={style}>
|
||||
<Header style={headerStyle} />
|
||||
<div style={containerStyle}>
|
||||
<div style={Object.assign({}, theme.textStyle, {marginBottom: 20})}>
|
||||
{_('Notes and settings are stored in: %s', pathUtils.toSystemSlashes(Setting.value('profileDir'), process.platform))}
|
||||
</div>
|
||||
{ settingComps }
|
||||
<button onClick={() => {this.onSaveClick()}} style={buttonStyle}>{_('OK')}</button>
|
||||
<button onClick={() => {this.onCancelClick()}} style={buttonStyle}>{_('Cancel')}</button>
|
||||
|
@ -36,7 +36,9 @@ globalStyle.lineInput = {
|
||||
fontFamily: globalStyle.fontFamily,
|
||||
};
|
||||
|
||||
globalStyle.headerStyle = {};
|
||||
globalStyle.headerStyle = {
|
||||
fontFamily: globalStyle.fontFamily,
|
||||
};
|
||||
|
||||
globalStyle.inputStyle = {
|
||||
border: '1px solid',
|
||||
|
@ -79,4 +79,31 @@ shared.settingsToComponents = function(comp, device, settings) {
|
||||
return settingComps
|
||||
}
|
||||
|
||||
shared.settingsToComponents2 = function(comp, device, settings) {
|
||||
const keys = Setting.keys(true, device);
|
||||
const sectionComps = [];
|
||||
const metadatas = [];
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i];
|
||||
if (!Setting.isPublic(key)) continue;
|
||||
|
||||
const md = Setting.settingMetadata(key);
|
||||
if (md.show && !md.show(settings)) continue;
|
||||
|
||||
metadatas.push(md);
|
||||
}
|
||||
|
||||
const sections = Setting.groupMetadatasBySections(metadatas);
|
||||
|
||||
for (let i = 0; i < sections.length; i++) {
|
||||
const section = sections[i];
|
||||
const sectionComp = comp.sectionToComponent(section.name, section, settings);
|
||||
if (!sectionComp) continue;
|
||||
sectionComps.push(sectionComp);
|
||||
}
|
||||
|
||||
return sectionComps
|
||||
}
|
||||
|
||||
module.exports = shared;
|
@ -53,15 +53,15 @@ class Setting extends BaseModel {
|
||||
options[Setting.TIME_FORMAT_2] = time.formatMsToLocal(now, Setting.TIME_FORMAT_2);
|
||||
return options;
|
||||
}},
|
||||
'theme': { value: Setting.THEME_LIGHT, type: Setting.TYPE_INT, public: true, appTypes: ['mobile', 'desktop'], isEnum: true, label: () => _('Theme'), options: () => {
|
||||
'theme': { value: Setting.THEME_LIGHT, type: Setting.TYPE_INT, public: true, appTypes: ['mobile', 'desktop'], isEnum: true, label: () => _('Theme'), section: 'appearance', options: () => {
|
||||
let output = {};
|
||||
output[Setting.THEME_LIGHT] = _('Light');
|
||||
output[Setting.THEME_DARK] = _('Dark');
|
||||
return output;
|
||||
}},
|
||||
'uncompletedTodosOnTop': { value: true, type: Setting.TYPE_BOOL, public: true, appTypes: ['cli'], label: () => _('Uncompleted to-dos on top') },
|
||||
'showCompletedTodos': { value: true, type: Setting.TYPE_BOOL, public: true, appTypes: ['cli'], label: () => _('Show completed to-dos') },
|
||||
'notes.sortOrder.field': { value: 'user_updated_time', type: Setting.TYPE_STRING, isEnum: true, public: true, appTypes: ['cli'], label: () => _('Sort notes by'), options: () => {
|
||||
'uncompletedTodosOnTop': { value: true, type: Setting.TYPE_BOOL, section: 'note', public: true, appTypes: ['cli'], label: () => _('Uncompleted to-dos on top') },
|
||||
'showCompletedTodos': { value: true, type: Setting.TYPE_BOOL, section: 'note', public: true, appTypes: ['cli'], label: () => _('Show completed to-dos') },
|
||||
'notes.sortOrder.field': { value: 'user_updated_time', type: Setting.TYPE_STRING, section: 'note', isEnum: true, public: true, appTypes: ['cli'], label: () => _('Sort notes by'), options: () => {
|
||||
const Note = require('lib/models/Note');
|
||||
const noteSortFields = ['user_updated_time', 'user_created_time', 'title'];
|
||||
const options = {};
|
||||
@ -70,15 +70,15 @@ class Setting extends BaseModel {
|
||||
}
|
||||
return options;
|
||||
}},
|
||||
'notes.sortOrder.reverse': { value: true, type: Setting.TYPE_BOOL, public: true, label: () => _('Reverse sort order'), appTypes: ['cli'] },
|
||||
'trackLocation': { value: true, type: Setting.TYPE_BOOL, public: true, label: () => _('Save geo-location with notes') },
|
||||
'newTodoFocus': { value: 'title', type: Setting.TYPE_STRING, isEnum: true, public: true, appTypes: ['desktop'], label: () => _('When creating a new to-do:'), options: () => {
|
||||
'notes.sortOrder.reverse': { value: true, type: Setting.TYPE_BOOL, section: 'note', public: true, label: () => _('Reverse sort order'), appTypes: ['cli'] },
|
||||
'trackLocation': { value: true, type: Setting.TYPE_BOOL, section: 'note', public: true, label: () => _('Save geo-location with notes') },
|
||||
'newTodoFocus': { value: 'title', type: Setting.TYPE_STRING, section: 'note', isEnum: true, public: true, appTypes: ['desktop'], label: () => _('When creating a new to-do:'), options: () => {
|
||||
return {
|
||||
'title': _('Focus title'),
|
||||
'body': _('Focus body'),
|
||||
};
|
||||
}},
|
||||
'newNoteFocus': { value: 'body', type: Setting.TYPE_STRING, isEnum: true, public: true, appTypes: ['desktop'], label: () => _('When creating a new note:'), options: () => {
|
||||
'newNoteFocus': { value: 'body', type: Setting.TYPE_STRING, section: 'note', isEnum: true, public: true, appTypes: ['desktop'], label: () => _('When creating a new note:'), options: () => {
|
||||
return {
|
||||
'title': _('Focus title'),
|
||||
'body': _('Focus body'),
|
||||
@ -89,11 +89,11 @@ class Setting extends BaseModel {
|
||||
// http://www.webupd8.org/2017/04/fix-appindicator-not-working-for.html
|
||||
// Might be fixed in Electron 18.x but no non-beta release yet. So for now
|
||||
// by default we disable it on Linux.
|
||||
'showTrayIcon': { value: platform !== 'linux', type: Setting.TYPE_BOOL, public: true, appTypes: ['desktop'], label: () => _('Show tray icon'), description: () => {
|
||||
'showTrayIcon': { value: platform !== 'linux', type: Setting.TYPE_BOOL, section:'application', public: true, appTypes: ['desktop'], label: () => _('Show tray icon'), description: () => {
|
||||
return platform === 'linux' ? _('Note: Does not work in all desktop environments.') : _('This will allow Joplin to run in the background. It is recommended to enable this setting so that your notes are constantly being synchronised, thus reducing the number of conflicts.');
|
||||
}},
|
||||
|
||||
'startMinimized': { value: false, type: Setting.TYPE_BOOL, public: true, appTypes: ['desktop'], label: () => _('Start application minimised in the tray icon') },
|
||||
'startMinimized': { value: false, type: Setting.TYPE_BOOL, section:'application', public: true, appTypes: ['desktop'], label: () => _('Start application minimised in the tray icon') },
|
||||
|
||||
'collapsedFolderIds': { value: [], type: Setting.TYPE_ARRAY, public: false },
|
||||
|
||||
@ -101,13 +101,13 @@ class Setting extends BaseModel {
|
||||
'encryption.enabled': { value: false, type: Setting.TYPE_BOOL, public: false },
|
||||
'encryption.activeMasterKeyId': { value: '', type: Setting.TYPE_STRING, public: false },
|
||||
'encryption.passwordCache': { value: {}, type: Setting.TYPE_OBJECT, public: false, secure: true },
|
||||
'style.zoom': {value: 100, type: Setting.TYPE_INT, public: true, appTypes: ['desktop'], label: () => _('Global zoom percentage'), minimum: 50, maximum: 500, step: 10},
|
||||
'style.editor.fontSize': {value: 12, type: Setting.TYPE_INT, public: true, appTypes: ['desktop'], label: () => _('Editor font size'), minimum: 4, maximum: 50, step: 1},
|
||||
'style.editor.fontFamily': {value: "", type: Setting.TYPE_STRING, public: true, appTypes: ['desktop'], label: () => _('Editor font family'), description: () => _('This must be *monospace* font or it will not work properly. If the font is incorrect or empty, it will default to a generic monospace font.')},
|
||||
'autoUpdateEnabled': { value: true, type: Setting.TYPE_BOOL, public: true, appTypes: ['desktop'], label: () => _('Automatically update the application') },
|
||||
'autoUpdate.includePreReleases': { value: false, type: Setting.TYPE_BOOL, public: true, appTypes: ['desktop'], label: () => _('Get pre-releases when checking for updates'), description: () => _('See the pre-release page for more details: %s', 'https://joplin.cozic.net/prereleases') },
|
||||
'style.zoom': {value: 100, type: Setting.TYPE_INT, public: true, appTypes: ['desktop'], section: 'appearance', label: () => _('Global zoom percentage'), minimum: 50, maximum: 500, step: 10},
|
||||
'style.editor.fontSize': {value: 12, type: Setting.TYPE_INT, public: true, appTypes: ['desktop'], section: 'appearance', label: () => _('Editor font size'), minimum: 4, maximum: 50, step: 1},
|
||||
'style.editor.fontFamily': {value: "", type: Setting.TYPE_STRING, public: true, appTypes: ['desktop'], section: 'appearance', label: () => _('Editor font family'), description: () => _('This must be *monospace* font or it will not work properly. If the font is incorrect or empty, it will default to a generic monospace font.')},
|
||||
'autoUpdateEnabled': { value: true, type: Setting.TYPE_BOOL, section:'application', public: true, appTypes: ['desktop'], label: () => _('Automatically update the application') },
|
||||
'autoUpdate.includePreReleases': { value: false, type: Setting.TYPE_BOOL, section:'application', public: true, appTypes: ['desktop'], label: () => _('Get pre-releases when checking for updates'), description: () => _('See the pre-release page for more details: %s', 'https://joplin.cozic.net/prereleases') },
|
||||
'clipperServer.autoStart': { value: false, type: Setting.TYPE_BOOL, public: false },
|
||||
'sync.interval': { value: 300, type: Setting.TYPE_INT, isEnum: true, public: true, label: () => _('Synchronisation interval'), options: () => {
|
||||
'sync.interval': { value: 300, type: Setting.TYPE_INT, section:'sync', isEnum: true, public: true, label: () => _('Synchronisation interval'), options: () => {
|
||||
return {
|
||||
0: _('Disabled'),
|
||||
300: _('%d minutes', 5),
|
||||
@ -124,11 +124,11 @@ class Setting extends BaseModel {
|
||||
'folderHeaderIsExpanded': { value: true, type: Setting.TYPE_BOOL, public: false, appTypes: ['desktop'] },
|
||||
'editor': { value: '', type: Setting.TYPE_STRING, public: true, appTypes: ['cli', 'desktop'], label: () => _('Text editor command'), description: () => _('The editor command (may include arguments) that will be used to open a note. If none is provided it will try to auto-detect the default editor.') },
|
||||
'showAdvancedOptions': { value: false, type: Setting.TYPE_BOOL, public: true, appTypes: ['mobile' ], label: () => _('Show advanced options') },
|
||||
'sync.target': { value: SyncTargetRegistry.nameToId('dropbox'), type: Setting.TYPE_INT, isEnum: true, public: true, label: () => _('Synchronisation target'), description: (appType) => { return appType !== 'cli' ? null : _('The target to synchonise to. Each sync target may have additional parameters which are named as `sync.NUM.NAME` (all documented below).') }, options: () => {
|
||||
'sync.target': { value: SyncTargetRegistry.nameToId('dropbox'), type: Setting.TYPE_INT, isEnum: true, public: true, section:'sync', label: () => _('Synchronisation target'), description: (appType) => { return appType !== 'cli' ? null : _('The target to synchonise to. Each sync target may have additional parameters which are named as `sync.NUM.NAME` (all documented below).') }, options: () => {
|
||||
return SyncTargetRegistry.idAndLabelPlainObject();
|
||||
}},
|
||||
|
||||
'sync.2.path': { value: '', type: Setting.TYPE_STRING, show: (settings) => {
|
||||
'sync.2.path': { value: '', type: Setting.TYPE_STRING, section:'sync', show: (settings) => {
|
||||
try {
|
||||
return settings['sync.target'] == SyncTargetRegistry.nameToId('filesystem')
|
||||
} catch (error) {
|
||||
@ -138,13 +138,13 @@ class Setting extends BaseModel {
|
||||
return value ? rtrimSlashes(value) : '';
|
||||
}, public: true, label: () => _('Directory to synchronise with (absolute path)'), description: (appType) => { return appType !== 'cli' ? null : _('The path to synchronise with when file system synchronisation is enabled. See `sync.target`.'); } },
|
||||
|
||||
'sync.5.path': { value: '', type: Setting.TYPE_STRING, show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('nextcloud') }, public: true, label: () => _('Nextcloud WebDAV URL'), description: () => _('Attention: If you change this location, make sure you copy all your content to it before syncing, otherwise all files will be removed! See the FAQ for more details: %s', 'https://joplin.cozic.net/faq/') },
|
||||
'sync.5.username': { value: '', type: Setting.TYPE_STRING, show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('nextcloud') }, public: true, label: () => _('Nextcloud username') },
|
||||
'sync.5.password': { value: '', type: Setting.TYPE_STRING, show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('nextcloud') }, public: true, label: () => _('Nextcloud password'), secure: true },
|
||||
'sync.5.path': { value: '', type: Setting.TYPE_STRING, section:'sync', show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('nextcloud') }, public: true, label: () => _('Nextcloud WebDAV URL'), description: () => _('Attention: If you change this location, make sure you copy all your content to it before syncing, otherwise all files will be removed! See the FAQ for more details: %s', 'https://joplin.cozic.net/faq/') },
|
||||
'sync.5.username': { value: '', type: Setting.TYPE_STRING, section:'sync', show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('nextcloud') }, public: true, label: () => _('Nextcloud username') },
|
||||
'sync.5.password': { value: '', type: Setting.TYPE_STRING, section:'sync', show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('nextcloud') }, public: true, label: () => _('Nextcloud password'), secure: true },
|
||||
|
||||
'sync.6.path': { value: '', type: Setting.TYPE_STRING, show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('webdav') }, public: true, label: () => _('WebDAV URL'), description: () => _('Attention: If you change this location, make sure you copy all your content to it before syncing, otherwise all files will be removed! See the FAQ for more details: %s', 'https://joplin.cozic.net/faq/') },
|
||||
'sync.6.username': { value: '', type: Setting.TYPE_STRING, show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('webdav') }, public: true, label: () => _('WebDAV username') },
|
||||
'sync.6.password': { value: '', type: Setting.TYPE_STRING, show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('webdav') }, public: true, label: () => _('WebDAV password'), secure: true },
|
||||
'sync.6.path': { value: '', type: Setting.TYPE_STRING, section:'sync', show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('webdav') }, public: true, label: () => _('WebDAV URL'), description: () => _('Attention: If you change this location, make sure you copy all your content to it before syncing, otherwise all files will be removed! See the FAQ for more details: %s', 'https://joplin.cozic.net/faq/') },
|
||||
'sync.6.username': { value: '', type: Setting.TYPE_STRING, section:'sync', show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('webdav') }, public: true, label: () => _('WebDAV username') },
|
||||
'sync.6.password': { value: '', type: Setting.TYPE_STRING, section:'sync', show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('webdav') }, public: true, label: () => _('WebDAV password'), secure: true },
|
||||
|
||||
'sync.3.auth': { value: '', type: Setting.TYPE_STRING, public: false },
|
||||
'sync.4.auth': { value: '', type: Setting.TYPE_STRING, public: false },
|
||||
@ -157,8 +157,8 @@ class Setting extends BaseModel {
|
||||
'sync.6.context': { value: '', type: Setting.TYPE_STRING, public: false },
|
||||
'sync.7.context': { value: '', type: Setting.TYPE_STRING, public: false },
|
||||
|
||||
'net.customCertificates': { value: '', type: Setting.TYPE_STRING, show: (settings) => { return [SyncTargetRegistry.nameToId('nextcloud'), SyncTargetRegistry.nameToId('webdav')].indexOf(settings['sync.target']) >= 0 }, public: true, appTypes: ['desktop', 'cli'], label: () => _('Custom TLS certificates'), description: () => _('Comma-separated list of paths to directories to load the certificates from, or path to individual cert files. For example: /my/cert_dir, /other/custom.pem. Note that if you make changes to the TLS settings, you must save your changes before clicking on "Check synchronisation configuration".') },
|
||||
'net.ignoreTlsErrors': { value: false, type: Setting.TYPE_BOOL, show: (settings) => { return [SyncTargetRegistry.nameToId('nextcloud'), SyncTargetRegistry.nameToId('webdav')].indexOf(settings['sync.target']) >= 0 }, public: true, appTypes: ['desktop', 'cli'], label: () => _('Ignore TLS certificate errors') },
|
||||
'net.customCertificates': { value: '', type: Setting.TYPE_STRING, section:'sync', show: (settings) => { return [SyncTargetRegistry.nameToId('nextcloud'), SyncTargetRegistry.nameToId('webdav')].indexOf(settings['sync.target']) >= 0 }, public: true, appTypes: ['desktop', 'cli'], label: () => _('Custom TLS certificates'), description: () => _('Comma-separated list of paths to directories to load the certificates from, or path to individual cert files. For example: /my/cert_dir, /other/custom.pem. Note that if you make changes to the TLS settings, you must save your changes before clicking on "Check synchronisation configuration".') },
|
||||
'net.ignoreTlsErrors': { value: false, type: Setting.TYPE_BOOL, section:'sync', show: (settings) => { return [SyncTargetRegistry.nameToId('nextcloud'), SyncTargetRegistry.nameToId('webdav')].indexOf(settings['sync.target']) >= 0 }, public: true, appTypes: ['desktop', 'cli'], label: () => _('Ignore TLS certificate errors') },
|
||||
|
||||
'api.token': { value: null, type: Setting.TYPE_STRING, public: false },
|
||||
|
||||
@ -527,6 +527,36 @@ class Setting extends BaseModel {
|
||||
if (typeId === Setting.TYPE_OBJECT) return 'object';
|
||||
}
|
||||
|
||||
static groupMetadatasBySections(metadatas) {
|
||||
let sections = [];
|
||||
const generalSection = { name: 'general', metadatas: [] };
|
||||
const nameToSections = {};
|
||||
nameToSections['general'] = generalSection;
|
||||
sections.push(generalSection);
|
||||
for (let i = 0; i < metadatas.length; i++) {
|
||||
const md = metadatas[i];
|
||||
if (!md.section) {
|
||||
generalSection.metadatas.push(md);
|
||||
} else {
|
||||
if (!nameToSections[md.section]) {
|
||||
nameToSections[md.section] = { name: md.section, metadatas: [] };
|
||||
sections.push(nameToSections[md.section]);
|
||||
}
|
||||
nameToSections[md.section].metadatas.push(md);
|
||||
}
|
||||
}
|
||||
return sections;
|
||||
}
|
||||
|
||||
static sectionNameToLabel(name) {
|
||||
if (name === 'general') return _('General');
|
||||
if (name === 'sync') return _('Synchronisation');
|
||||
if (name === 'appearance') return _('Appearance');
|
||||
if (name === 'note') return _('Note');
|
||||
if (name === 'application') return _('Application');
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Setting.TYPE_INT = 1;
|
||||
|
Loading…
Reference in New Issue
Block a user