diff --git a/ReactNativeClient/lib/components/global-style.js b/ReactNativeClient/lib/components/global-style.js
index 4b2ddcc57..1c1c000b3 100644
--- a/ReactNativeClient/lib/components/global-style.js
+++ b/ReactNativeClient/lib/components/global-style.js
@@ -15,6 +15,7 @@ const globalStyle = {
dividerColor: "#dddddd",
strongDividerColor: "#aaaaaa",
selectedColor: '#e5e5e5',
+ headerBackgroundColor: '#F0F0F0',
disabledOpacity: 0.2,
colorUrl: '#7B81FF',
textSelectionColor: "#0096FF",
@@ -84,6 +85,16 @@ function addExtraStyles(style) {
fontSize: style.fontSize,
};
+ style.headerStyle = {
+ color: style.color,
+ fontSize: style.fontSize * 1.2,
+ fontWeight: 'bold',
+ };
+
+ style.headerWrapperStyle = {
+ backgroundColor: style.headerBackgroundColor,
+ };
+
return style;
}
@@ -105,6 +116,7 @@ function themeStyle(theme) {
output.strongDividerColor = '#888888';
output.selectedColor = '#333333';
output.textSelectionColor = '#00AEFF';
+ output.headerBackgroundColor = '#2D3136';
output.raisedBackgroundColor = "#0F2051";
output.raisedColor = "#788BC3";
diff --git a/ReactNativeClient/lib/components/screens/config.js b/ReactNativeClient/lib/components/screens/config.js
index 015763961..deb869426 100644
--- a/ReactNativeClient/lib/components/screens/config.js
+++ b/ReactNativeClient/lib/components/screens/config.js
@@ -62,7 +62,6 @@ class ConfigScreenComponent extends BaseScreenComponent {
paddingRight: theme.marginRight,
},
settingText: {
- fontWeight: 'bold',
color: theme.color,
fontSize: theme.fontSize,
flex: 1,
@@ -73,6 +72,10 @@ class ConfigScreenComponent extends BaseScreenComponent {
fontSize: theme.fontSize,
flex: 1,
},
+ sliderUnits: {
+ color: theme.color,
+ fontSize: theme.fontSize,
+ },
settingDescriptionText: {
color: theme.color,
fontSize: theme.fontSize,
@@ -114,6 +117,8 @@ class ConfigScreenComponent extends BaseScreenComponent {
styles.linkText.flex = 0;
styles.linkText.fontWeight = 'normal';
+ styles.headerWrapperStyle = Object.assign({}, styles.settingContainer, theme.headerWrapperStyle)
+
styles.switchSettingControl = Object.assign({}, styles.settingControl);
delete styles.switchSettingControl.color;
//styles.switchSettingControl.width = '20%';
@@ -123,6 +128,61 @@ class ConfigScreenComponent extends BaseScreenComponent {
return this.styles_[themeId];
}
+ renderHeader(key, title) {
+ const theme = themeStyle(this.props.theme);
+ return (
+
+ {title}
+
+ );
+ }
+
+ 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];
+
+ if (section.name === 'sync' && md.key === 'sync.resourceDownloadMode') {
+ const syncTargetMd = SyncTargetRegistry.idToMetadata(settings['sync.target']);
+
+ if (syncTargetMd.supportsConfigCheck) {
+ const messages = shared.checkSyncConfigMessages(this);
+ const statusComp = !messages.length ? null : (
+
+ {messages[0]}
+ {messages.length >= 1 ? ({messages[1]}) : null}
+ );
+
+ settingComps.push(
+
+
+
+
+ { statusComp }
+
+ );
+ }
+ }
+
+ const settingComp = this.settingToComponent(md.key, settings[md.key]);
+ settingComps.push(settingComp);
+ }
+
+ const headerWrapperStyle = this.styles().headerWrapperStyle;
+
+ return (
+
+ {this.renderHeader(section.name, Setting.sectionNameToLabel(section.name))}
+
+ {settingComps}
+
+
+ );
+ }
+
settingToComponent(key, value) {
const themeId = this.props.theme;
const theme = themeStyle(themeId);
@@ -149,8 +209,8 @@ class ConfigScreenComponent extends BaseScreenComponent {
const containerStyle = !settingDescription ? this.styles().settingContainer : this.styles().settingContainerNoBottomBorder;
return (
-
-
+
+
{md.label()}
{md.label()}
- updateSettingValue(key, value)} />
- {unitLabel}
+ updateSettingValue(key, value)} />
+ {unitLabel}
);
@@ -196,7 +256,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
return (
{md.label()}
- updateSettingValue(key, value)} secureTextEntry={!!md.secure} />
+ updateSettingValue(key, value)} secureTextEntry={!!md.secure} />
);
} else {
@@ -209,32 +269,14 @@ class ConfigScreenComponent extends BaseScreenComponent {
render() {
const settings = this.state.settings;
- const settingComps = shared.settingsToComponents(this, 'mobile', settings);
+ const settingComps = shared.settingsToComponents2(this, 'mobile', settings);
- const syncTargetMd = SyncTargetRegistry.idToMetadata(settings['sync.target']);
-
- if (syncTargetMd.supportsConfigCheck) {
- const messages = shared.checkSyncConfigMessages(this);
- const statusComp = !messages.length ? null : (
-
- {messages[0]}
- {messages.length >= 1 ? ({messages[1]}) : null}
- );
-
- settingComps.push(
-
-
-
-
- { statusComp }
-
- );
- }
+ settingComps.push(this.renderHeader('moreInfo', _('More information')));
if (Platform.OS === 'android' && Platform.Version >= 23) {
// Note: `PermissionsAndroid` doesn't work so we have to ask the user to manually
// set these permissions. https://stackoverflow.com/questions/49771084/permission-always-returns-never-ask-again
+
settingComps.push(
diff --git a/ReactNativeClient/lib/models/Setting.js b/ReactNativeClient/lib/models/Setting.js
index d39bfdbf8..a65e8a8ba 100644
--- a/ReactNativeClient/lib/models/Setting.js
+++ b/ReactNativeClient/lib/models/Setting.js
@@ -32,6 +32,50 @@ class Setting extends BaseModel {
// public for the mobile and desktop apps because they are handled separately in menus.
this.metadata_ = {
+ '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, section:'sync', show: (settings) => {
+ try {
+ return settings['sync.target'] == SyncTargetRegistry.nameToId('filesystem')
+ } catch (error) {
+ return false;
+ }
+ }, filter: (value) => {
+ return value ? rtrimSlashes(value) : '';
+ }, public: true, label: () => _('Directory to synchronise with (absolute path)'), description: () => emptyDirWarning },
+
+ '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: () => emptyDirWarning },
+ '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, section:'sync', show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('webdav') }, public: true, label: () => _('WebDAV URL'), description: () => emptyDirWarning },
+ '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 },
+ 'sync.7.auth': { value: '', type: Setting.TYPE_STRING, public: false },
+ 'sync.1.context': { value: '', type: Setting.TYPE_STRING, public: false },
+ 'sync.2.context': { value: '', type: Setting.TYPE_STRING, public: false },
+ 'sync.3.context': { value: '', type: Setting.TYPE_STRING, public: false },
+ 'sync.4.context': { value: '', type: Setting.TYPE_STRING, public: false },
+ 'sync.5.context': { value: '', type: Setting.TYPE_STRING, public: false },
+ 'sync.6.context': { value: '', type: Setting.TYPE_STRING, public: false },
+ 'sync.7.context': { value: '', type: Setting.TYPE_STRING, public: false },
+
+ 'sync.resourceDownloadMode': { value: 'always', type: Setting.TYPE_STRING, section: 'sync', public: true, isEnum: true, appTypes: ['mobile', 'desktop'], label: () => _('Attachment download behaviour'), description: () => _('In "Manual" mode, attachments are downloaded only when you click on them. In "Auto", they are downloaded when you open the note. In "Always", all the attachments are downloaded whether you open the note or not.'), options: () => {
+ return {
+ 'always': _('Always'),
+ 'manual': _('Manual'),
+ 'auto': _('Auto'),
+ };
+ }},
+
+ 'sync.maxConcurrentConnections': {value: 5, type: Setting.TYPE_INT, public: true, section: 'sync', label: () => _('Max concurrent connections'), minimum: 1, maximum: 20, step: 1},
+
+
'activeFolderId': { value: '', type: Setting.TYPE_STRING, public: false },
'firstStart': { value: true, type: Setting.TYPE_BOOL, public: false },
'locale': { value: defaultLocale(), type: Setting.TYPE_STRING, isEnum: true, public: true, label: () => _('Language'), options: () => {
@@ -151,48 +195,6 @@ class Setting extends BaseModel {
'folderHeaderIsExpanded': { value: true, type: Setting.TYPE_BOOL, public: false, appTypes: ['desktop'] },
'editor': { value: '', type: Setting.TYPE_STRING, subType: 'file_path_and_args', 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, 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.resourceDownloadMode': { value: 'always', type: Setting.TYPE_STRING, section: 'sync', public: true, isEnum: true, appTypes: ['mobile', 'desktop'], label: () => _('Attachment download behaviour'), description: () => _('In "Manual" mode, attachments are downloaded only when you click on them. In "Auto", they are downloaded when you open the note. In "Always", all the attachments are downloaded whether you open the note or not.'), options: () => {
- return {
- 'always': _('Always'),
- 'manual': _('Manual'),
- 'auto': _('Auto'),
- };
- }},
-
- 'sync.maxConcurrentConnections': {value: 5, type: Setting.TYPE_INT, public: true, section: 'sync', label: () => _('Max concurrent connections'), minimum: 1, maximum: 20, step: 1},
-
- 'sync.2.path': { value: '', type: Setting.TYPE_STRING, section:'sync', show: (settings) => {
- try {
- return settings['sync.target'] == SyncTargetRegistry.nameToId('filesystem')
- } catch (error) {
- return false;
- }
- }, filter: (value) => {
- return value ? rtrimSlashes(value) : '';
- }, public: true, label: () => _('Directory to synchronise with (absolute path)'), description: () => emptyDirWarning },
-
- '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: () => emptyDirWarning },
- '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, section:'sync', show: (settings) => { return settings['sync.target'] == SyncTargetRegistry.nameToId('webdav') }, public: true, label: () => _('WebDAV URL'), description: () => emptyDirWarning },
- '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 },
- 'sync.7.auth': { value: '', type: Setting.TYPE_STRING, public: false },
- 'sync.1.context': { value: '', type: Setting.TYPE_STRING, public: false },
- 'sync.2.context': { value: '', type: Setting.TYPE_STRING, public: false },
- 'sync.3.context': { value: '', type: Setting.TYPE_STRING, public: false },
- 'sync.4.context': { value: '', type: Setting.TYPE_STRING, public: false },
- 'sync.5.context': { value: '', type: Setting.TYPE_STRING, public: false },
- '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, 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') },