You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-08-13 22:12:50 +02:00
Better handling of settings
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { View, StyleSheet, Picker, Text, Button } from 'react-native';
|
import { View, Switch, StyleSheet, Picker, Text, Button } from 'react-native';
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import { ScreenHeader } from 'lib/components/screen-header.js';
|
import { ScreenHeader } from 'lib/components/screen-header.js';
|
||||||
import { _, setLocale } from 'lib/locale.js';
|
import { _, setLocale } from 'lib/locale.js';
|
||||||
@@ -21,7 +21,7 @@ let styles = {
|
|||||||
color: globalStyle.color,
|
color: globalStyle.color,
|
||||||
},
|
},
|
||||||
settingControl: {
|
settingControl: {
|
||||||
color: globalStyle.color,
|
//color: globalStyle.color,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
|
|||||||
|
|
||||||
const value = this.state.values[key];
|
const value = this.state.values[key];
|
||||||
|
|
||||||
if (setting.type == 'enum') {
|
if (setting.isEnum) {
|
||||||
let items = [];
|
let items = [];
|
||||||
const settingOptions = setting.options();
|
const settingOptions = setting.options();
|
||||||
for (let k in settingOptions) {
|
for (let k in settingOptions) {
|
||||||
@@ -80,7 +80,14 @@ class ConfigScreenComponent extends BaseScreenComponent {
|
|||||||
</Picker>
|
</Picker>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
} else {
|
} else if (setting.type == Setting.TYPE_BOOL) {
|
||||||
|
return (
|
||||||
|
<View key={key} style={styles.settingContainer}>
|
||||||
|
<Text key="label" style={styles.settingText}>{setting.label()}</Text>
|
||||||
|
<Switch key="control" style={styles.settingControl} value={value} onValueChange={(value) => updateSettingValue(key, value)} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
//throw new Error('Unsupported setting type: ' + setting.type);
|
//throw new Error('Unsupported setting type: ' + setting.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -230,8 +230,6 @@ class Database {
|
|||||||
s.push('`' + n + '`=?');
|
s.push('`' + n + '`=?');
|
||||||
}
|
}
|
||||||
where = s.join(' AND ');
|
where = s.join(' AND ');
|
||||||
// params.push(where.id);
|
|
||||||
// where = 'id=?';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -240,6 +238,23 @@ class Database {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alterColumnQueries(tableName, fieldsAfter) {
|
||||||
|
let sql = `
|
||||||
|
CREATE TEMPORARY TABLE _BACKUP_TABLE_NAME_(_FIELDS_AFTER_);
|
||||||
|
INSERT INTO _BACKUP_TABLE_NAME_ SELECT _FIELDS_AFTER_ FROM _TABLE_NAME_;
|
||||||
|
DROP TABLE _TABLE_NAME_;
|
||||||
|
CREATE TABLE _TABLE_NAME_(_FIELDS_AFTER_);
|
||||||
|
INSERT INTO _TABLE_NAME_ SELECT _FIELDS_AFTER_ FROM _BACKUP_TABLE_NAME_;
|
||||||
|
DROP TABLE _BACKUP_TABLE_NAME_;
|
||||||
|
`;
|
||||||
|
|
||||||
|
sql = sql.replace(/_BACKUP_TABLE_NAME_/g, this.escapeField(tableName + '_backup'));
|
||||||
|
sql = sql.replace(/_TABLE_NAME_/g, this.escapeField(tableName));
|
||||||
|
sql = sql.replace(/_FIELDS_AFTER_/g, this.escapeFields(fieldsAfter).join(','));
|
||||||
|
|
||||||
|
return sql.trim().split("\n");
|
||||||
|
}
|
||||||
|
|
||||||
wrapQueries(queries) {
|
wrapQueries(queries) {
|
||||||
let output = [];
|
let output = [];
|
||||||
for (let i = 0; i < queries.length; i++) {
|
for (let i = 0; i < queries.length; i++) {
|
||||||
|
@@ -193,7 +193,7 @@ class JoplinDatabase extends Database {
|
|||||||
// 1. Add the new version number to the existingDatabaseVersions array
|
// 1. Add the new version number to the existingDatabaseVersions array
|
||||||
// 2. Add the upgrade logic to the "switch (targetVersion)" statement below
|
// 2. Add the upgrade logic to the "switch (targetVersion)" statement below
|
||||||
|
|
||||||
const existingDatabaseVersions = [1, 2];
|
const existingDatabaseVersions = [1, 2, 3];
|
||||||
|
|
||||||
let currentVersionIndex = existingDatabaseVersions.indexOf(fromVersion);
|
let currentVersionIndex = existingDatabaseVersions.indexOf(fromVersion);
|
||||||
if (currentVersionIndex == existingDatabaseVersions.length - 1) return false;
|
if (currentVersionIndex == existingDatabaseVersions.length - 1) return false;
|
||||||
@@ -220,6 +220,10 @@ class JoplinDatabase extends Database {
|
|||||||
queries.push({ sql: "CREATE INDEX deleted_items_sync_target ON deleted_items (sync_target)" });
|
queries.push({ sql: "CREATE INDEX deleted_items_sync_target ON deleted_items (sync_target)" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (targetVersion == 3) {
|
||||||
|
queries = this.alterColumnQueries('settings', ['key', 'value']);
|
||||||
|
}
|
||||||
|
|
||||||
queries.push({ sql: 'UPDATE version SET version = ?', params: [targetVersion] });
|
queries.push({ sql: 'UPDATE version SET version = ?', params: [targetVersion] });
|
||||||
await this.transactionExecBatch(queries);
|
await this.transactionExecBatch(queries);
|
||||||
|
|
||||||
@@ -251,7 +255,6 @@ class JoplinDatabase extends Database {
|
|||||||
this.logger().info('Database is new - creating the schema...');
|
this.logger().info('Database is new - creating the schema...');
|
||||||
|
|
||||||
let queries = this.wrapQueries(this.sqlStringToLines(structureSql));
|
let queries = this.wrapQueries(this.sqlStringToLines(structureSql));
|
||||||
queries.push(this.wrapQuery('INSERT INTO settings (`key`, `value`, `type`) VALUES ("clientId", "' + uuid.create() + '", "' + Database.enumId('settings', 'string') + '")'));
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.transactionExecBatch(queries);
|
await this.transactionExecBatch(queries);
|
||||||
|
@@ -151,6 +151,7 @@ class Note extends BaseItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static async updateGeolocation(noteId) {
|
static async updateGeolocation(noteId) {
|
||||||
|
if (!Setting.value('trackLocation')) return;
|
||||||
if (!Note.updateGeolocationEnabled_) return;
|
if (!Note.updateGeolocationEnabled_) return;
|
||||||
|
|
||||||
let startWait = time.unixMs();
|
let startWait = time.unixMs();
|
||||||
|
@@ -44,11 +44,15 @@ class Setting extends BaseModel {
|
|||||||
return this.modelSelectAll('SELECT * FROM settings').then((rows) => {
|
return this.modelSelectAll('SELECT * FROM settings').then((rows) => {
|
||||||
this.cache_ = rows;
|
this.cache_ = rows;
|
||||||
|
|
||||||
// TEMPORARY TO CONVERT ALL CLIENT SETTINGS
|
|
||||||
for (let i = 0; i < this.cache_.length; i++) {
|
for (let i = 0; i < this.cache_.length; i++) {
|
||||||
if (this.cache_[i].key == 'sync.target' && this.cache_[i].value == 'onedrive') {
|
let c = this.cache_[i];
|
||||||
this.cache_[i].value = 3;
|
|
||||||
}
|
if (c.key == 'clientId') continue; // For older clients
|
||||||
|
if (c.key == 'sync.onedrive.auth') continue; // For older clients
|
||||||
|
|
||||||
|
c.value = this.formatValue(c.key, c.value);
|
||||||
|
|
||||||
|
this.cache_[i] = c;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -66,27 +70,34 @@ class Setting extends BaseModel {
|
|||||||
if (c.key == key) {
|
if (c.key == key) {
|
||||||
const md = this.settingMetadata(key);
|
const md = this.settingMetadata(key);
|
||||||
|
|
||||||
if (md.type == 'enum') {
|
if (md.isEnum === true) {
|
||||||
if (!this.isAllowedEnumOption(key, value)) {
|
if (!this.isAllowedEnumOption(key, value)) {
|
||||||
throw new Error(_('Invalid option value: "%s". Possible values are: %s.', value, this.enumOptionsDoc(key)));
|
throw new Error(_('Invalid option value: "%s". Possible values are: %s.', value, this.enumOptionsDoc(key)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c.value === value) return;
|
if (c.value === value) return;
|
||||||
c.value = value;
|
|
||||||
|
this.logger().info('Setting: ' + key + ' = ' + value);
|
||||||
|
|
||||||
|
c.value = this.formatValue(key, value);
|
||||||
this.scheduleUpdate();
|
this.scheduleUpdate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let s = this.settingMetadata(key);
|
this.cache_.push({
|
||||||
s.value = value;
|
key: key,
|
||||||
this.cache_.push(s);
|
value: this.formatValue(key, value),
|
||||||
|
});
|
||||||
|
|
||||||
this.scheduleUpdate();
|
this.scheduleUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
static formatValue(type, value) {
|
static formatValue(key, value) {
|
||||||
if (type == 'int') return Math.floor(Number(value));
|
const md = this.settingMetadata(key);
|
||||||
|
if (md.type == Setting.TYPE_INT) return Math.floor(Number(value));
|
||||||
|
if (md.type == Setting.TYPE_BOOL) return !!value;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,20 +110,19 @@ class Setting extends BaseModel {
|
|||||||
|
|
||||||
if (!this.cache_) throw new Error('Settings have not been initialized!');
|
if (!this.cache_) throw new Error('Settings have not been initialized!');
|
||||||
|
|
||||||
const md = this.settingMetadata(key);
|
|
||||||
|
|
||||||
for (let i = 0; i < this.cache_.length; i++) {
|
for (let i = 0; i < this.cache_.length; i++) {
|
||||||
if (this.cache_[i].key == key) {
|
if (this.cache_[i].key == key) {
|
||||||
return this.formatValue(md.type, this.cache_[i].value);
|
return this.cache_[i].value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.formatValue(md.type, md.value);
|
const md = this.settingMetadata(key);
|
||||||
|
return md.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isEnum(key) {
|
static isEnum(key) {
|
||||||
const md = this.settingMetadata(key);
|
const md = this.settingMetadata(key);
|
||||||
return md.type == 'enum';
|
return md.isEnum === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enumOptionValues(key) {
|
static enumOptionValues(key) {
|
||||||
@@ -185,13 +195,7 @@ class Setting extends BaseModel {
|
|||||||
let queries = [];
|
let queries = [];
|
||||||
queries.push('DELETE FROM settings');
|
queries.push('DELETE FROM settings');
|
||||||
for (let i = 0; i < this.cache_.length; i++) {
|
for (let i = 0; i < this.cache_.length; i++) {
|
||||||
let s = Object.assign({}, this.cache_[i]);
|
queries.push(Database.insertQuery(this.tableName(), this.cache_[i]));
|
||||||
delete s.public;
|
|
||||||
delete s.appTypes;
|
|
||||||
delete s.label;
|
|
||||||
delete s.options;
|
|
||||||
s.value = this.formatValue(s.type, s.value);
|
|
||||||
queries.push(Database.insertQuery(this.tableName(), s));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return BaseModel.db().transactionExecBatch(queries).then(() => {
|
return BaseModel.db().transactionExecBatch(queries).then(() => {
|
||||||
@@ -233,28 +237,33 @@ Setting.SYNC_TARGET_MEMORY = 1;
|
|||||||
Setting.SYNC_TARGET_FILESYSTEM = 2;
|
Setting.SYNC_TARGET_FILESYSTEM = 2;
|
||||||
Setting.SYNC_TARGET_ONEDRIVE = 3;
|
Setting.SYNC_TARGET_ONEDRIVE = 3;
|
||||||
|
|
||||||
|
Setting.TYPE_INT = 1;
|
||||||
|
Setting.TYPE_STRING = 2;
|
||||||
|
Setting.TYPE_BOOL = 3;
|
||||||
|
|
||||||
Setting.metadata_ = {
|
Setting.metadata_ = {
|
||||||
'activeFolderId': { value: '', type: 'string', public: false },
|
'activeFolderId': { value: '', type: Setting.TYPE_STRING, public: false },
|
||||||
'firstStart': { value: 1, type: 'int', public: false },
|
'firstStart': { value: true, type: Setting.TYPE_BOOL, public: false },
|
||||||
'sync.2.path': { value: '', type: 'string', public: true, appTypes: ['cli'] },
|
'sync.2.path': { value: '', type: Setting.TYPE_STRING, public: true, appTypes: ['cli'] },
|
||||||
'sync.3.auth': { value: '', type: 'string', public: false },
|
'sync.3.auth': { value: '', type: Setting.TYPE_STRING, public: false },
|
||||||
'sync.target': { value: Setting.SYNC_TARGET_ONEDRIVE, type: 'enum', public: true, label: () => _('Synchronisation target'), options: () => {
|
'sync.target': { value: Setting.SYNC_TARGET_ONEDRIVE, type: Setting.TYPE_INT, isEnum: true, public: true, label: () => _('Synchronisation target'), options: () => {
|
||||||
let output = {};
|
let output = {};
|
||||||
output[Setting.SYNC_TARGET_MEMORY] = 'Memory';
|
output[Setting.SYNC_TARGET_MEMORY] = 'Memory';
|
||||||
output[Setting.SYNC_TARGET_FILESYSTEM] = _('File system');
|
output[Setting.SYNC_TARGET_FILESYSTEM] = _('File system');
|
||||||
output[Setting.SYNC_TARGET_ONEDRIVE] = _('OneDrive');
|
output[Setting.SYNC_TARGET_ONEDRIVE] = _('OneDrive');
|
||||||
return output;
|
return output;
|
||||||
}},
|
}},
|
||||||
'sync.context': { value: '', type: 'string', public: false },
|
'sync.context': { value: '', type: Setting.TYPE_STRING, public: false },
|
||||||
'editor': { value: '', type: 'string', public: true, appTypes: ['cli'] },
|
'editor': { value: '', type: Setting.TYPE_STRING, public: true, appTypes: ['cli'] },
|
||||||
'locale': { value: defaultLocale(), type: 'enum', public: true, label: () => _('Language'), options: () => {
|
'locale': { value: defaultLocale(), type: Setting.TYPE_STRING, isEnum: true, public: true, label: () => _('Language'), options: () => {
|
||||||
return supportedLocalesToLanguages();
|
return supportedLocalesToLanguages();
|
||||||
}},
|
}},
|
||||||
'todoFilter': { value: 'all', type: 'enum', public: true, appTypes: ['mobile'], label: () => _('Todo filter'), options: () => ({
|
'todoFilter': { value: 'all', type: Setting.TYPE_STRING, isEnum: true, public: true, appTypes: ['mobile'], label: () => _('Todo filter'), options: () => ({
|
||||||
all: _('Show all'),
|
all: _('Show all'),
|
||||||
recent: _('Non-completed and recently completed ones'),
|
recent: _('Non-completed and recently completed ones'),
|
||||||
nonCompleted: _('Non-completed ones only'),
|
nonCompleted: _('Non-completed ones only'),
|
||||||
})},
|
})},
|
||||||
|
'trackLocation': { value: true, type: Setting.TYPE_BOOL, public: true, label: () => _('Save location with notes') },
|
||||||
};
|
};
|
||||||
|
|
||||||
// Contains constants that are set by the application and
|
// Contains constants that are set by the application and
|
||||||
|
Reference in New Issue
Block a user