You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-09-16 08:56:40 +02:00
Handle user timestamp
This commit is contained in:
@@ -321,6 +321,14 @@ msgid ""
|
|||||||
"will be shared with any third party."
|
"will be shared with any third party."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#, javascript-format
|
||||||
|
msgid "Unknown log level: %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, javascript-format
|
||||||
|
msgid "Unknown level ID: %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"Cannot refresh token: authentication data is missing. Starting the "
|
"Cannot refresh token: authentication data is missing. Starting the "
|
||||||
"synchronisation again may fix the problem."
|
"synchronisation again may fix the problem."
|
||||||
|
@@ -364,6 +364,14 @@ msgid ""
|
|||||||
"will be shared with any third party."
|
"will be shared with any third party."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#, fuzzy, javascript-format
|
||||||
|
msgid "Unknown log level: %s"
|
||||||
|
msgstr "Paramètre inconnu : %s"
|
||||||
|
|
||||||
|
#, fuzzy, javascript-format
|
||||||
|
msgid "Unknown level ID: %s"
|
||||||
|
msgstr "Paramètre inconnu : %s"
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"Cannot refresh token: authentication data is missing. Starting the "
|
"Cannot refresh token: authentication data is missing. Starting the "
|
||||||
"synchronisation again may fix the problem."
|
"synchronisation again may fix the problem."
|
||||||
|
@@ -321,6 +321,14 @@ msgid ""
|
|||||||
"will be shared with any third party."
|
"will be shared with any third party."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#, javascript-format
|
||||||
|
msgid "Unknown log level: %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#, javascript-format
|
||||||
|
msgid "Unknown level ID: %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"Cannot refresh token: authentication data is missing. Starting the "
|
"Cannot refresh token: authentication data is missing. Starting the "
|
||||||
"synchronisation again may fix the problem."
|
"synchronisation again may fix the problem."
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
"url": "https://github.com/laurent22/joplin"
|
"url": "https://github.com/laurent22/joplin"
|
||||||
},
|
},
|
||||||
"url": "git://github.com/laurent22/joplin.git",
|
"url": "git://github.com/laurent22/joplin.git",
|
||||||
"version": "0.9.7",
|
"version": "0.9.8",
|
||||||
"bin": {
|
"bin": {
|
||||||
"joplin": "./main.js"
|
"joplin": "./main.js"
|
||||||
},
|
},
|
||||||
|
@@ -1 +1 @@
|
|||||||
bd9c058875b3fa6fb7091aa9f3ee0e74
|
28897a284082f5be431a27ee5b1a26cb
|
@@ -217,8 +217,14 @@ class BaseModel {
|
|||||||
let query = {};
|
let query = {};
|
||||||
let modelId = o.id;
|
let modelId = o.id;
|
||||||
|
|
||||||
|
const timeNow = time.unixMs();
|
||||||
|
|
||||||
if (options.autoTimestamp && this.hasField('updated_time')) {
|
if (options.autoTimestamp && this.hasField('updated_time')) {
|
||||||
o.updated_time = time.unixMs();
|
o.updated_time = timeNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.autoTimestamp && this.hasField('user_updated_time')) {
|
||||||
|
o.user_updated_time = timeNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.isNew) {
|
if (options.isNew) {
|
||||||
@@ -228,7 +234,11 @@ class BaseModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!o.created_time && this.hasField('created_time')) {
|
if (!o.created_time && this.hasField('created_time')) {
|
||||||
o.created_time = time.unixMs();
|
o.created_time = timeNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!o.user_created_time && this.hasField('user_created_time')) {
|
||||||
|
o.user_created_time = timeNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
query = Database.insertQuery(this.tableName(), o);
|
query = Database.insertQuery(this.tableName(), o);
|
||||||
@@ -266,6 +276,8 @@ class BaseModel {
|
|||||||
o.id = modelId;
|
o.id = modelId;
|
||||||
if ('updated_time' in saveQuery.modObject) o.updated_time = saveQuery.modObject.updated_time;
|
if ('updated_time' in saveQuery.modObject) o.updated_time = saveQuery.modObject.updated_time;
|
||||||
if ('created_time' in saveQuery.modObject) o.created_time = saveQuery.modObject.created_time;
|
if ('created_time' in saveQuery.modObject) o.created_time = saveQuery.modObject.created_time;
|
||||||
|
if ('user_updated_time' in saveQuery.modObject) o.user_updated_time = saveQuery.modObject.user_updated_time;
|
||||||
|
if ('user_created_time' in saveQuery.modObject) o.user_created_time = saveQuery.modObject.user_created_time;
|
||||||
o = this.addModelMd(o);
|
o = this.addModelMd(o);
|
||||||
return this.filter(o);
|
return this.filter(o);
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
|
@@ -61,7 +61,7 @@ class NoteListComponent extends Component {
|
|||||||
for (let i = 0; i < notes.length; i++) {
|
for (let i = 0; i < notes.length; i++) {
|
||||||
const note = notes[i];
|
const note = notes[i];
|
||||||
if (note.is_todo) {
|
if (note.is_todo) {
|
||||||
if (todoFilter == 'recent' && note.updated_time < notRecentTime && !!note.todo_completed) continue;
|
if (todoFilter == 'recent' && note.user_updated_time < notRecentTime && !!note.todo_completed) continue;
|
||||||
if (todoFilter == 'nonCompleted' && !!note.todo_completed) continue;
|
if (todoFilter == 'nonCompleted' && !!note.todo_completed) continue;
|
||||||
}
|
}
|
||||||
output.push(note);
|
output.push(note);
|
||||||
|
@@ -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 = [0, 1, 2, 3, 4];
|
const existingDatabaseVersions = [0, 1, 2, 3, 4, 5];
|
||||||
|
|
||||||
let currentVersionIndex = existingDatabaseVersions.indexOf(fromVersion);
|
let currentVersionIndex = existingDatabaseVersions.indexOf(fromVersion);
|
||||||
if (currentVersionIndex == existingDatabaseVersions.length - 1) return false;
|
if (currentVersionIndex == existingDatabaseVersions.length - 1) return false;
|
||||||
@@ -233,6 +233,18 @@ class JoplinDatabase extends Database {
|
|||||||
queries.push('DELETE FROM settings WHERE `key` = "sync.context"');
|
queries.push('DELETE FROM settings WHERE `key` = "sync.context"');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (targetVersion == 5) {
|
||||||
|
const tableNames = ['notes', 'folders', 'tags', 'note_tags', 'resources'];
|
||||||
|
for (let i = 0; i < tableNames.length; i++) {
|
||||||
|
const n = tableNames[i];
|
||||||
|
queries.push('ALTER TABLE ' + n + ' ADD COLUMN user_created_time INT NOT NULL DEFAULT 0');
|
||||||
|
queries.push('ALTER TABLE ' + n + ' ADD COLUMN user_updated_time INT NOT NULL DEFAULT 0');
|
||||||
|
queries.push('UPDATE ' + n + ' SET user_created_time = created_time');
|
||||||
|
queries.push('UPDATE ' + n + ' SET user_updated_time = updated_time');
|
||||||
|
queries.push('CREATE INDEX ' + n + '_user_updated_time ON ' + n + ' (user_updated_time)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
@@ -144,7 +144,29 @@ class Logger {
|
|||||||
if (s == 'warn') return Logger.LEVEL_WARN;
|
if (s == 'warn') return Logger.LEVEL_WARN;
|
||||||
if (s == 'info') return Logger.LEVEL_INFO;
|
if (s == 'info') return Logger.LEVEL_INFO;
|
||||||
if (s == 'debug') return Logger.LEVEL_DEBUG;
|
if (s == 'debug') return Logger.LEVEL_DEBUG;
|
||||||
throw new Error('Unknown log level: %s', s);
|
throw new Error(_('Unknown log level: %s', s));
|
||||||
|
}
|
||||||
|
|
||||||
|
static levelIdToString(id) {
|
||||||
|
if (id == Logger.LEVEL_NONE) return 'none';
|
||||||
|
if (id == Logger.LEVEL_ERROR) return 'error';
|
||||||
|
if (id == Logger.LEVEL_WARN) return 'warn';
|
||||||
|
if (id == Logger.LEVEL_INFO) return 'info';
|
||||||
|
if (id == Logger.LEVEL_DEBUG) return 'debug';
|
||||||
|
throw new Error(_('Unknown level ID: %s', id));
|
||||||
|
}
|
||||||
|
|
||||||
|
static levelIds() {
|
||||||
|
return [Logger.LEVEL_NONE, Logger.LEVEL_ERROR, Logger.LEVEL_WARN, Logger.LEVEL_INFO, Logger.LEVEL_DEBUG];
|
||||||
|
}
|
||||||
|
|
||||||
|
static levelEnum() {
|
||||||
|
let output = {};
|
||||||
|
const ids = this.levelIds();
|
||||||
|
for (let i = 0; i < ids.length; i++) {
|
||||||
|
output[ids[i]] = this.levelIdToString(ids[i]);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -180,7 +180,7 @@ class BaseItem extends BaseModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static serialize_format(propName, propValue) {
|
static serialize_format(propName, propValue) {
|
||||||
if (['created_time', 'updated_time', 'sync_time'].indexOf(propName) >= 0) {
|
if (['created_time', 'updated_time', 'sync_time', 'user_updated_time', 'user_created_time'].indexOf(propName) >= 0) {
|
||||||
if (!propValue) return '';
|
if (!propValue) return '';
|
||||||
propValue = moment.unix(propValue / 1000).utc().format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z';
|
propValue = moment.unix(propValue / 1000).utc().format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z';
|
||||||
} else if (propValue === null || propValue === undefined) {
|
} else if (propValue === null || propValue === undefined) {
|
||||||
@@ -195,7 +195,7 @@ class BaseItem extends BaseModel {
|
|||||||
|
|
||||||
let ItemClass = this.itemClass(type);
|
let ItemClass = this.itemClass(type);
|
||||||
|
|
||||||
if (['created_time', 'updated_time'].indexOf(propName) >= 0) {
|
if (['created_time', 'updated_time', 'user_created_time', 'user_updated_time'].indexOf(propName) >= 0) {
|
||||||
if (!propValue) return 0;
|
if (!propValue) return 0;
|
||||||
propValue = moment(propValue, 'YYYY-MM-DDTHH:mm:ss.SSSZ').format('x');
|
propValue = moment(propValue, 'YYYY-MM-DDTHH:mm:ss.SSSZ').format('x');
|
||||||
} else {
|
} else {
|
||||||
|
@@ -91,6 +91,7 @@ class Folder extends BaseItem {
|
|||||||
id: this.conflictFolderId(),
|
id: this.conflictFolderId(),
|
||||||
title: this.conflictFolderTitle(),
|
title: this.conflictFolderTitle(),
|
||||||
updated_time: time.unixMs(),
|
updated_time: time.unixMs(),
|
||||||
|
user_updated_time: time.unixMs(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -95,7 +95,7 @@ class Note extends BaseItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static previewFields() {
|
static previewFields() {
|
||||||
return ['id', 'title', 'body', 'is_todo', 'todo_completed', 'parent_id', 'updated_time'];
|
return ['id', 'title', 'body', 'is_todo', 'todo_completed', 'parent_id', 'updated_time', 'user_updated_time'];
|
||||||
}
|
}
|
||||||
|
|
||||||
static previewFieldsSql() {
|
static previewFieldsSql() {
|
||||||
@@ -122,7 +122,7 @@ class Note extends BaseItem {
|
|||||||
// is used to sort already loaded notes.
|
// is used to sort already loaded notes.
|
||||||
|
|
||||||
if (!options) options = {};
|
if (!options) options = {};
|
||||||
if (!options.order) options.order = [{ by: 'updated_time', dir: 'DESC' }];
|
if (!options.order) options.order = [{ by: 'user_updated_time', dir: 'DESC' }];
|
||||||
if (!options.conditions) options.conditions = [];
|
if (!options.conditions) options.conditions = [];
|
||||||
if (!options.conditionsParams) options.conditionsParams = [];
|
if (!options.conditionsParams) options.conditionsParams = [];
|
||||||
if (!options.fields) options.fields = this.previewFields();
|
if (!options.fields) options.fields = this.previewFields();
|
||||||
@@ -269,11 +269,17 @@ class Note extends BaseItem {
|
|||||||
static async moveToFolder(noteId, folderId) {
|
static async moveToFolder(noteId, folderId) {
|
||||||
if (folderId == Folder.conflictFolderId()) throw new Error(_('Cannot move note to "%s" notebook', Folder.conflictFolderIdTitle()));
|
if (folderId == Folder.conflictFolderId()) throw new Error(_('Cannot move note to "%s" notebook', Folder.conflictFolderIdTitle()));
|
||||||
|
|
||||||
return Note.save({
|
// When moving a note to a different folder, the user timestamp is not updated.
|
||||||
|
// However updated_time is updated so that the note can be synced later on.
|
||||||
|
|
||||||
|
const modifiedNote = {
|
||||||
id: noteId,
|
id: noteId,
|
||||||
parent_id: folderId,
|
parent_id: folderId,
|
||||||
is_conflict: 0,
|
is_conflict: 0,
|
||||||
});
|
updated_time: time.unixMs(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return Note.save(modifiedNote, { autoTimestamp: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
static toggleIsTodo(note) {
|
static toggleIsTodo(note) {
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import { BaseModel } from 'lib/base-model.js';
|
import { BaseModel } from 'lib/base-model.js';
|
||||||
import { Database } from 'lib/database.js';
|
import { Database } from 'lib/database.js';
|
||||||
|
import { Logger } from 'lib/logger.js';
|
||||||
import { _, supportedLocalesToLanguages, defaultLocale } from 'lib/locale.js';
|
import { _, supportedLocalesToLanguages, defaultLocale } from 'lib/locale.js';
|
||||||
|
|
||||||
class Setting extends BaseModel {
|
class Setting extends BaseModel {
|
||||||
@@ -318,6 +319,9 @@ Setting.metadata_ = {
|
|||||||
'locale': { value: defaultLocale(), type: Setting.TYPE_STRING, isEnum: true, public: true, label: () => _('Language'), options: () => {
|
'locale': { value: defaultLocale(), type: Setting.TYPE_STRING, isEnum: true, public: true, label: () => _('Language'), options: () => {
|
||||||
return supportedLocalesToLanguages();
|
return supportedLocalesToLanguages();
|
||||||
}},
|
}},
|
||||||
|
// 'logLevel': { value: Logger.LEVEL_INFO, type: Setting.TYPE_STRING, isEnum: true, public: true, label: () => _('Log level'), options: () => {
|
||||||
|
// return Logger.levelEnum();
|
||||||
|
// }},
|
||||||
// Not used for now:
|
// Not used for now:
|
||||||
'todoFilter': { value: 'all', type: Setting.TYPE_STRING, isEnum: true, public: false, appTypes: ['mobile'], label: () => _('Todo filter'), options: () => ({
|
'todoFilter': { value: 'all', type: Setting.TYPE_STRING, isEnum: true, public: false, appTypes: ['mobile'], label: () => _('Todo filter'), options: () => ({
|
||||||
all: _('Show all'),
|
all: _('Show all'),
|
||||||
|
@@ -49,7 +49,7 @@ let defaultState = {
|
|||||||
screens: {},
|
screens: {},
|
||||||
historyCanGoBack: false,
|
historyCanGoBack: false,
|
||||||
notesOrder: [
|
notesOrder: [
|
||||||
{ by: 'updated_time', dir: 'DESC' },
|
{ by: 'user_updated_time', dir: 'DESC' },
|
||||||
],
|
],
|
||||||
syncStarted: false,
|
syncStarted: false,
|
||||||
syncReport: {},
|
syncReport: {},
|
||||||
|
Reference in New Issue
Block a user