mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
various changes
This commit is contained in:
parent
32e9b1ada7
commit
8578642307
@ -1,3 +1,5 @@
|
|||||||
|
require('source-map-support').install();
|
||||||
|
|
||||||
import { FileApi } from 'src/file-api.js';
|
import { FileApi } from 'src/file-api.js';
|
||||||
import { FileApiDriverLocal } from 'src/file-api-driver-local.js';
|
import { FileApiDriverLocal } from 'src/file-api-driver-local.js';
|
||||||
import { Database } from 'src/database.js';
|
import { Database } from 'src/database.js';
|
||||||
@ -5,6 +7,7 @@ import { DatabaseDriverNode } from 'src/database-driver-node.js';
|
|||||||
import { BaseModel } from 'src/base-model.js';
|
import { BaseModel } from 'src/base-model.js';
|
||||||
import { Folder } from 'src/models/folder.js';
|
import { Folder } from 'src/models/folder.js';
|
||||||
import { Note } from 'src/models/note.js';
|
import { Note } from 'src/models/note.js';
|
||||||
|
import { Setting } from 'src/models/setting.js';
|
||||||
import { Synchronizer } from 'src/synchronizer.js';
|
import { Synchronizer } from 'src/synchronizer.js';
|
||||||
import { uuid } from 'src/uuid.js';
|
import { uuid } from 'src/uuid.js';
|
||||||
import { sprintf } from 'sprintf-js';
|
import { sprintf } from 'sprintf-js';
|
||||||
@ -53,7 +56,9 @@ let synchronizer = new Synchronizer(db, fileApi);
|
|||||||
|
|
||||||
db.open({ name: '/home/laurent/Temp/test.sqlite3' }).then(() => {
|
db.open({ name: '/home/laurent/Temp/test.sqlite3' }).then(() => {
|
||||||
BaseModel.db_ = db;
|
BaseModel.db_ = db;
|
||||||
|
}).then(() => {
|
||||||
|
return Setting.load();
|
||||||
|
}).then(() => {
|
||||||
let commands = [];
|
let commands = [];
|
||||||
let currentFolder = null;
|
let currentFolder = null;
|
||||||
|
|
||||||
@ -291,6 +296,7 @@ db.open({ name: '/home/laurent/Temp/test.sqlite3' }).then(() => {
|
|||||||
|
|
||||||
commands.push({
|
commands.push({
|
||||||
usage: 'ls [list-title]',
|
usage: 'ls [list-title]',
|
||||||
|
alias: 'll',
|
||||||
description: 'Lists items in [list-title].',
|
description: 'Lists items in [list-title].',
|
||||||
action: function (args, end) {
|
action: function (args, end) {
|
||||||
let folderTitle = args['list-title'];
|
let folderTitle = args['list-title'];
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
"promise": "^7.1.1",
|
"promise": "^7.1.1",
|
||||||
"react": "16.0.0-alpha.6",
|
"react": "16.0.0-alpha.6",
|
||||||
"sax": "^1.2.2",
|
"sax": "^1.2.2",
|
||||||
|
"source-map-support": "^0.4.15",
|
||||||
"sprintf-js": "^1.1.1",
|
"sprintf-js": "^1.1.1",
|
||||||
"sqlite3": "^3.1.8",
|
"sqlite3": "^3.1.8",
|
||||||
"string-to-stream": "^1.1.0",
|
"string-to-stream": "^1.1.0",
|
||||||
@ -29,7 +30,7 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"babelbuild": "babel app -d build",
|
"babelbuild": "babel app -d build",
|
||||||
"build": "babel-changed app -d build && babel-changed app/src/models -d build/src/models && babel-changed app/src/services -d build/src/services",
|
"build": "babel-changed app -d build --source-maps && babel-changed app/src/models -d build/src/models --source-maps && babel-changed app/src/services -d build/src/services --source-maps",
|
||||||
"clean": "babel-changed --reset"
|
"clean": "babel-changed --reset"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,6 @@ class BaseModel {
|
|||||||
|
|
||||||
static load(id) {
|
static load(id) {
|
||||||
return this.loadByField('id', id);
|
return this.loadByField('id', id);
|
||||||
//return this.db().selectOne('SELECT * FROM ' + this.tableName() + ' WHERE id = ?', [id]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static loadByField(fieldName, fieldValue) {
|
static loadByField(fieldName, fieldValue) {
|
||||||
@ -139,7 +138,7 @@ class BaseModel {
|
|||||||
|
|
||||||
query.id = itemId;
|
query.id = itemId;
|
||||||
|
|
||||||
Log.info('Saving', o);
|
Log.info('Saving', JSON.stringify(o));
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
@ -283,6 +283,7 @@ class Database {
|
|||||||
}
|
}
|
||||||
|
|
||||||
refreshTableFields() {
|
refreshTableFields() {
|
||||||
|
Log.info('Initializing tables...');
|
||||||
let queries = [];
|
let queries = [];
|
||||||
queries.push(this.wrapQuery('DELETE FROM table_fields'));
|
queries.push(this.wrapQuery('DELETE FROM table_fields'));
|
||||||
|
|
||||||
|
@ -25,15 +25,29 @@ class FileApiDriverLocal {
|
|||||||
return Math.round(m.toDate().getTime() / 1000);
|
return Math.round(m.toDate().getTime() / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
metadataFromStats_(name, stats) {
|
metadataFromStats_(path, stats) {
|
||||||
return {
|
return {
|
||||||
name: name,
|
path: path,
|
||||||
createdTime: this.statTimeToUnixTimestamp_(stats.birthtime),
|
createdTime: this.statTimeToUnixTimestamp_(stats.birthtime),
|
||||||
updatedTime: this.statTimeToUnixTimestamp_(stats.mtime),
|
updatedTime: this.statTimeToUnixTimestamp_(stats.mtime),
|
||||||
|
createdTimeOrig: stats.birthtime,
|
||||||
|
updatedTimeOrig: stats.mtime,
|
||||||
isDir: stats.isDirectory(),
|
isDir: stats.isDirectory(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setFileTimestamp(path, timestamp) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
fs.utimes(path, timestamp, timestamp, (error) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
list(path) {
|
list(path) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
fs.readdir(path, (error, items) => {
|
fs.readdir(path, (error, items) => {
|
||||||
|
@ -35,6 +35,10 @@ class FileApi {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setFileTimestamp(path, timestamp) {
|
||||||
|
return this.driver_.setFileTimestamp(this.baseDir_ + '/' + path, timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
mkdir(path) {
|
mkdir(path) {
|
||||||
return this.driver_.mkdir(this.baseDir_ + '/' + path);
|
return this.driver_.mkdir(this.baseDir_ + '/' + path);
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,6 @@ class Change extends BaseModel {
|
|||||||
static deleteMultiple(ids) {
|
static deleteMultiple(ids) {
|
||||||
if (ids.length == 0) return Promise.resolve();
|
if (ids.length == 0) return Promise.resolve();
|
||||||
|
|
||||||
console.warn('TODO: deleteMultiple: CHECK THAT IT WORKS');
|
|
||||||
|
|
||||||
let queries = [];
|
let queries = [];
|
||||||
for (let i = 0; i < ids.length; i++) {
|
for (let i = 0; i < ids.length; i++) {
|
||||||
queries.push(['DELETE FROM changes WHERE id = ?', [ids[i]]]);
|
queries.push(['DELETE FROM changes WHERE id = ?', [ids[i]]]);
|
||||||
|
@ -4,6 +4,7 @@ import { promiseChain } from 'src/promise-chain.js';
|
|||||||
import { Note } from 'src/models/note.js';
|
import { Note } from 'src/models/note.js';
|
||||||
import { folderItemFilename } from 'src/string-utils.js'
|
import { folderItemFilename } from 'src/string-utils.js'
|
||||||
import { _ } from 'src/locale.js';
|
import { _ } from 'src/locale.js';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
class Folder extends BaseModel {
|
class Folder extends BaseModel {
|
||||||
|
|
||||||
@ -19,6 +20,40 @@ class Folder extends BaseModel {
|
|||||||
return this.filename(folder);
|
return this.filename(folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static systemMetadataPath(parent, folder) {
|
||||||
|
return this.systemPath(parent, folder) + '/.folder.md';
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: share with Note class
|
||||||
|
static toFriendlyString_format(propName, propValue) {
|
||||||
|
if (['created_time', 'updated_time'].indexOf(propName) >= 0) {
|
||||||
|
if (!propValue) return '';
|
||||||
|
propValue = moment.unix(propValue).format('YYYY-MM-DD hh:mm:ss');
|
||||||
|
} else if (propValue === null || propValue === undefined) {
|
||||||
|
propValue = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return propValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: share with Note class
|
||||||
|
static toFriendlyString(folder) {
|
||||||
|
let shownKeys = ['created_time', 'updated_time'];
|
||||||
|
let output = [];
|
||||||
|
|
||||||
|
output.push(folder.title);
|
||||||
|
output.push('');
|
||||||
|
output.push(''); // For consistency with the notes, leave an empty line where the body should be
|
||||||
|
output.push('');
|
||||||
|
for (let i = 0; i < shownKeys.length; i++) {
|
||||||
|
let v = folder[shownKeys[i]];
|
||||||
|
v = this.toFriendlyString_format(shownKeys[i], v);
|
||||||
|
output.push(shownKeys[i] + ': ' + v);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output.join("\n");
|
||||||
|
}
|
||||||
|
|
||||||
static useUuid() {
|
static useUuid() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,8 @@ Setting.defaults_ = {
|
|||||||
'sessionId': { value: '', type: 'string' },
|
'sessionId': { value: '', type: 'string' },
|
||||||
'user.email': { value: '', type: 'string' },
|
'user.email': { value: '', type: 'string' },
|
||||||
'user.session': { value: '', type: 'string' },
|
'user.session': { value: '', type: 'string' },
|
||||||
'sync.lastRevId': { value: 0, type: 'int' },
|
'sync.lastRevId': { value: 0, type: 'int' }, // DEPRECATED
|
||||||
|
'sync.lastUpdateTime': { value: 0, type: 'int' },
|
||||||
};
|
};
|
||||||
|
|
||||||
export { Setting };
|
export { Setting };
|
@ -10,8 +10,9 @@ import { Registry } from 'src/registry.js';
|
|||||||
class NoteFolderService extends BaseService {
|
class NoteFolderService extends BaseService {
|
||||||
|
|
||||||
static save(type, item, oldItem) {
|
static save(type, item, oldItem) {
|
||||||
|
let diff = null;
|
||||||
if (oldItem) {
|
if (oldItem) {
|
||||||
let diff = BaseModel.diffObjects(oldItem, item);
|
diff = BaseModel.diffObjects(oldItem, item);
|
||||||
if (!Object.getOwnPropertyNames(diff).length) {
|
if (!Object.getOwnPropertyNames(diff).length) {
|
||||||
Log.info('Item not changed - not saved');
|
Log.info('Item not changed - not saved');
|
||||||
return Promise.resolve(item);
|
return Promise.resolve(item);
|
||||||
@ -27,9 +28,16 @@ class NoteFolderService extends BaseService {
|
|||||||
|
|
||||||
let isNew = !item.id;
|
let isNew = !item.id;
|
||||||
let output = null;
|
let output = null;
|
||||||
return ItemClass.save(item).then((item) => {
|
|
||||||
output = item;
|
let toSave = item;
|
||||||
if (isNew && type == 'note') return Note.updateGeolocation(item.id);
|
if (diff !== null) {
|
||||||
|
toSave = diff;
|
||||||
|
toSave.id = item.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ItemClass.save(toSave).then((savedItem) => {
|
||||||
|
output = Object.assign(item, savedItem);
|
||||||
|
if (isNew && type == 'note') return Note.updateGeolocation(output.id);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
// Registry.synchronizer().start();
|
// Registry.synchronizer().start();
|
||||||
return output;
|
return output;
|
||||||
|
@ -114,9 +114,10 @@ function escapeFilename(s, maxLength = 32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function folderItemFilename(item) {
|
function folderItemFilename(item) {
|
||||||
let output = escapeFilename(item.title).trim();
|
return item.id;
|
||||||
if (!output.length) output = '_';
|
// let output = escapeFilename(item.title).trim();
|
||||||
return output + '.' + item.id.substr(0, 7);
|
// if (!output.length) output = '_';
|
||||||
|
// return output + '.' + item.id.substr(0, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { removeDiacritics, escapeFilename, folderItemFilename };
|
export { removeDiacritics, escapeFilename, folderItemFilename };
|
@ -46,15 +46,15 @@ class Synchronizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
remoteFileByName(remoteFiles, name) {
|
remoteFileByPath(remoteFiles, path) {
|
||||||
for (let i = 0; i < remoteFiles.length; i++) {
|
for (let i = 0; i < remoteFiles.length; i++) {
|
||||||
if (remoteFiles[i].name == name) return remoteFiles[i];
|
if (remoteFiles[i].path == path) return remoteFiles[i];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
conflictDir(remoteFiles) {
|
conflictDir(remoteFiles) {
|
||||||
let d = this.remoteFileByName('Conflicts');
|
let d = this.remoteFileByPath('Conflicts');
|
||||||
if (!d) {
|
if (!d) {
|
||||||
return this.api().mkdir('Conflicts').then(() => {
|
return this.api().mkdir('Conflicts').then(() => {
|
||||||
return 'Conflicts';
|
return 'Conflicts';
|
||||||
@ -69,11 +69,11 @@ class Synchronizer {
|
|||||||
if (item.isDir) return Promise.resolve();
|
if (item.isDir) return Promise.resolve();
|
||||||
|
|
||||||
return this.conflictDir().then((conflictDirPath) => {
|
return this.conflictDir().then((conflictDirPath) => {
|
||||||
let p = path.basename(item.name).split('.');
|
let p = path.basename(item.path).split('.');
|
||||||
let pos = item.isDir ? p.length - 1 : p.length - 2;
|
let pos = item.isDir ? p.length - 1 : p.length - 2;
|
||||||
p.splice(pos, 0, moment().format('YYYYMMDDThhmmss'));
|
p.splice(pos, 0, moment().format('YYYYMMDDThhmmss'));
|
||||||
let newName = p.join('.');
|
let newPath = p.join('.');
|
||||||
return this.api().move(item.name, conflictDirPath + '/' + newName);
|
return this.api().move(item.path, conflictDirPath + '/' + newPath);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,6 +86,7 @@ class Synchronizer {
|
|||||||
}).then((changes) => {
|
}).then((changes) => {
|
||||||
let mergedChanges = Change.mergeChanges(changes);
|
let mergedChanges = Change.mergeChanges(changes);
|
||||||
let chain = [];
|
let chain = [];
|
||||||
|
const lastSyncTime = Setting.value('sync.lastUpdateTime');
|
||||||
for (let i = 0; i < mergedChanges.length; i++) {
|
for (let i = 0; i < mergedChanges.length; i++) {
|
||||||
let c = mergedChanges[i];
|
let c = mergedChanges[i];
|
||||||
chain.push(() => {
|
chain.push(() => {
|
||||||
@ -102,11 +103,13 @@ class Synchronizer {
|
|||||||
p = Promise.resolve();
|
p = Promise.resolve();
|
||||||
} else if (c.type == Change.TYPE_CREATE) {
|
} else if (c.type == Change.TYPE_CREATE) {
|
||||||
p = this.loadParentAndItem(c).then((result) => {
|
p = this.loadParentAndItem(c).then((result) => {
|
||||||
if (!result.item) return; // Change refers to an object that doesn't exist (has probably been deleted directly in the database)
|
let item = result.item;
|
||||||
|
let parent = result.parent;
|
||||||
|
if (!item) return; // Change refers to an object that doesn't exist (has probably been deleted directly in the database)
|
||||||
|
|
||||||
let path = ItemClass.systemPath(result.parent, result.item);
|
let path = ItemClass.systemPath(parent, item);
|
||||||
|
|
||||||
let remoteFile = this.remoteFileByName(remoteFiles, path);
|
let remoteFile = this.remoteFileByPath(remoteFiles, path);
|
||||||
let p = null;
|
let p = null;
|
||||||
if (remoteFile) {
|
if (remoteFile) {
|
||||||
p = this.moveConflict(remoteFile);
|
p = this.moveConflict(remoteFile);
|
||||||
@ -116,7 +119,39 @@ class Synchronizer {
|
|||||||
|
|
||||||
return p.then(() => {
|
return p.then(() => {
|
||||||
if (c.item_type == BaseModel.ITEM_TYPE_FOLDER) {
|
if (c.item_type == BaseModel.ITEM_TYPE_FOLDER) {
|
||||||
return this.api().mkdir(path);
|
return this.api().mkdir(path).then(() => {
|
||||||
|
return this.api().put(Folder.systemMetadataPath(parent, item), Folder.toFriendlyString(item));
|
||||||
|
}).then(() => {
|
||||||
|
return this.api().setFileTimestamp(Folder.systemMetadataPath(parent, item), item.updated_time);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return this.api().put(path, Note.toFriendlyString(item)).then(() => {
|
||||||
|
return this.api().setFileTimestamp(path, item.updated_time);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else if (c.type == Change.TYPE_UPDATE) {
|
||||||
|
p = this.loadParentAndItem(c).then((result) => {
|
||||||
|
if (!result.item) return; // Change refers to an object that doesn't exist (has probably been deleted directly in the database)
|
||||||
|
|
||||||
|
let path = ItemClass.systemPath(result.parent, result.item);
|
||||||
|
|
||||||
|
let remoteFile = this.remoteFileByPath(remoteFiles, path);
|
||||||
|
let p = null;
|
||||||
|
if (remoteFile && remoteFile.updatedTime > lastSyncTime) {
|
||||||
|
console.info('CONFLICT:', lastSyncTime, remoteFile);
|
||||||
|
//console.info(moment.unix(remoteFile.updatedTime), moment.unix(result.item.updated_time));
|
||||||
|
p = this.moveConflict(remoteFile);
|
||||||
|
} else {
|
||||||
|
p = Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
console.info('Uploading change:', JSON.stringify(result.item));
|
||||||
|
|
||||||
|
return p.then(() => {
|
||||||
|
if (c.item_type == BaseModel.ITEM_TYPE_FOLDER) {
|
||||||
|
return this.api().put(Folder.systemMetadataPath(result.parent, result.item), Folder.toFriendlyString(result.item));
|
||||||
} else {
|
} else {
|
||||||
return this.api().put(path, Note.toFriendlyString(result.item));
|
return this.api().put(path, Note.toFriendlyString(result.item));
|
||||||
}
|
}
|
||||||
@ -124,7 +159,6 @@ class Synchronizer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: handle UPDATE
|
|
||||||
// TODO: handle DELETE
|
// TODO: handle DELETE
|
||||||
|
|
||||||
return p.then(() => {
|
return p.then(() => {
|
||||||
@ -142,11 +176,17 @@ class Synchronizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return promiseChain(chain);
|
return promiseChain(chain);
|
||||||
|
// }).then(() => {
|
||||||
|
// console.info(remoteFiles);
|
||||||
|
// for (let i = 0; i < remoteFiles.length; i++) {
|
||||||
|
// const remoteFile = remoteFiles[i];
|
||||||
|
|
||||||
|
// }
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
Log.warn('Synchronization was interrupted due to an error:', error);
|
Log.error('Synchronization was interrupted due to an error:', error);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
Log.info('IDs to delete: ', processedChangeIds);
|
//Log.info('IDs to delete: ', processedChangeIds);
|
||||||
// Change.deleteMultiple(processedChangeIds);
|
//return Change.deleteMultiple(processedChangeIds);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.processState('downloadChanges');
|
this.processState('downloadChanges');
|
||||||
});
|
});
|
||||||
@ -240,63 +280,126 @@ class Synchronizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
processState_downloadChanges() {
|
processState_downloadChanges() {
|
||||||
let maxRevId = null;
|
// return this.api().list('', true).then((items) => {
|
||||||
let hasMore = false;
|
// remoteFiles = items;
|
||||||
this.api().get('synchronizer', { rev_id: Setting.value('sync.lastRevId') }).then((syncOperations) => {
|
// return Change.all();
|
||||||
hasMore = syncOperations.has_more;
|
|
||||||
let chain = [];
|
|
||||||
for (let i = 0; i < syncOperations.items.length; i++) {
|
|
||||||
let syncOp = syncOperations.items[i];
|
|
||||||
if (syncOp.id > maxRevId) maxRevId = syncOp.id;
|
|
||||||
|
|
||||||
let ItemClass = null;
|
|
||||||
if (syncOp.item_type == 'folder') {
|
|
||||||
ItemClass = Folder;
|
|
||||||
} else if (syncOp.item_type == 'note') {
|
|
||||||
ItemClass = Note;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (syncOp.type == 'create') {
|
// let maxRevId = null;
|
||||||
chain.push(() => {
|
// let hasMore = false;
|
||||||
let item = ItemClass.fromApiResult(syncOp.item);
|
// this.api().get('synchronizer', { rev_id: Setting.value('sync.lastRevId') }).then((syncOperations) => {
|
||||||
// TODO: automatically handle NULL fields by checking type and default value of field
|
// hasMore = syncOperations.has_more;
|
||||||
if ('parent_id' in item && !item.parent_id) item.parent_id = '';
|
// let chain = [];
|
||||||
return ItemClass.save(item, { isNew: true, trackChanges: false });
|
// for (let i = 0; i < syncOperations.items.length; i++) {
|
||||||
});
|
// let syncOp = syncOperations.items[i];
|
||||||
}
|
// if (syncOp.id > maxRevId) maxRevId = syncOp.id;
|
||||||
|
|
||||||
if (syncOp.type == 'update') {
|
// let ItemClass = null;
|
||||||
chain.push(() => {
|
// if (syncOp.item_type == 'folder') {
|
||||||
return ItemClass.load(syncOp.item_id).then((item) => {
|
// ItemClass = Folder;
|
||||||
if (!item) return;
|
// } else if (syncOp.item_type == 'note') {
|
||||||
item = ItemClass.applyPatch(item, syncOp.item);
|
// ItemClass = Note;
|
||||||
return ItemClass.save(item, { trackChanges: false });
|
// }
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (syncOp.type == 'delete') {
|
// if (syncOp.type == 'create') {
|
||||||
chain.push(() => {
|
// chain.push(() => {
|
||||||
return ItemClass.delete(syncOp.item_id, { trackChanges: false });
|
// let item = ItemClass.fromApiResult(syncOp.item);
|
||||||
});
|
// // TODO: automatically handle NULL fields by checking type and default value of field
|
||||||
}
|
// if ('parent_id' in item && !item.parent_id) item.parent_id = '';
|
||||||
}
|
// return ItemClass.save(item, { isNew: true, trackChanges: false });
|
||||||
return promiseChain(chain);
|
// });
|
||||||
}).then(() => {
|
// }
|
||||||
Log.info('All items synced. has_more = ', hasMore);
|
|
||||||
if (maxRevId) {
|
// if (syncOp.type == 'update') {
|
||||||
Setting.setValue('sync.lastRevId', maxRevId);
|
// chain.push(() => {
|
||||||
return Setting.saveAll();
|
// return ItemClass.load(syncOp.item_id).then((item) => {
|
||||||
}
|
// if (!item) return;
|
||||||
}).then(() => {
|
// item = ItemClass.applyPatch(item, syncOp.item);
|
||||||
if (hasMore) {
|
// return ItemClass.save(item, { trackChanges: false });
|
||||||
this.processState('downloadChanges');
|
// });
|
||||||
} else {
|
// });
|
||||||
this.processState('idle');
|
// }
|
||||||
}
|
|
||||||
}).catch((error) => {
|
// if (syncOp.type == 'delete') {
|
||||||
Log.warn('Sync error', error);
|
// chain.push(() => {
|
||||||
});
|
// return ItemClass.delete(syncOp.item_id, { trackChanges: false });
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return promiseChain(chain);
|
||||||
|
// }).then(() => {
|
||||||
|
// Log.info('All items synced. has_more = ', hasMore);
|
||||||
|
// if (maxRevId) {
|
||||||
|
// Setting.setValue('sync.lastRevId', maxRevId);
|
||||||
|
// return Setting.saveAll();
|
||||||
|
// }
|
||||||
|
// }).then(() => {
|
||||||
|
// if (hasMore) {
|
||||||
|
// this.processState('downloadChanges');
|
||||||
|
// } else {
|
||||||
|
// this.processState('idle');
|
||||||
|
// }
|
||||||
|
// }).catch((error) => {
|
||||||
|
// Log.warn('Sync error', error);
|
||||||
|
// });
|
||||||
|
|
||||||
|
// let maxRevId = null;
|
||||||
|
// let hasMore = false;
|
||||||
|
// this.api().get('synchronizer', { rev_id: Setting.value('sync.lastRevId') }).then((syncOperations) => {
|
||||||
|
// hasMore = syncOperations.has_more;
|
||||||
|
// let chain = [];
|
||||||
|
// for (let i = 0; i < syncOperations.items.length; i++) {
|
||||||
|
// let syncOp = syncOperations.items[i];
|
||||||
|
// if (syncOp.id > maxRevId) maxRevId = syncOp.id;
|
||||||
|
|
||||||
|
// let ItemClass = null;
|
||||||
|
// if (syncOp.item_type == 'folder') {
|
||||||
|
// ItemClass = Folder;
|
||||||
|
// } else if (syncOp.item_type == 'note') {
|
||||||
|
// ItemClass = Note;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (syncOp.type == 'create') {
|
||||||
|
// chain.push(() => {
|
||||||
|
// let item = ItemClass.fromApiResult(syncOp.item);
|
||||||
|
// // TODO: automatically handle NULL fields by checking type and default value of field
|
||||||
|
// if ('parent_id' in item && !item.parent_id) item.parent_id = '';
|
||||||
|
// return ItemClass.save(item, { isNew: true, trackChanges: false });
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (syncOp.type == 'update') {
|
||||||
|
// chain.push(() => {
|
||||||
|
// return ItemClass.load(syncOp.item_id).then((item) => {
|
||||||
|
// if (!item) return;
|
||||||
|
// item = ItemClass.applyPatch(item, syncOp.item);
|
||||||
|
// return ItemClass.save(item, { trackChanges: false });
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (syncOp.type == 'delete') {
|
||||||
|
// chain.push(() => {
|
||||||
|
// return ItemClass.delete(syncOp.item_id, { trackChanges: false });
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return promiseChain(chain);
|
||||||
|
// }).then(() => {
|
||||||
|
// Log.info('All items synced. has_more = ', hasMore);
|
||||||
|
// if (maxRevId) {
|
||||||
|
// Setting.setValue('sync.lastRevId', maxRevId);
|
||||||
|
// return Setting.saveAll();
|
||||||
|
// }
|
||||||
|
// }).then(() => {
|
||||||
|
// if (hasMore) {
|
||||||
|
// this.processState('downloadChanges');
|
||||||
|
// } else {
|
||||||
|
// this.processState('idle');
|
||||||
|
// }
|
||||||
|
// }).catch((error) => {
|
||||||
|
// Log.warn('Sync error', error);
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
processState(state) {
|
processState(state) {
|
||||||
|
Loading…
Reference in New Issue
Block a user