diff --git a/CliClient/tests/synchronizer.js b/CliClient/tests/synchronizer.js index e356ae0621..e691f0b526 100644 --- a/CliClient/tests/synchronizer.js +++ b/CliClient/tests/synchronizer.js @@ -31,7 +31,7 @@ async function localItemsSameAsRemote(locals, expect) { expect(remote.updated_time).toBe(dbItem.updated_time); let remoteContent = await fileApi().get(path); - remoteContent = dbItem.type_ == BaseModel.ITEM_TYPE_NOTE ? Note.unserialize(remoteContent) : Folder.unserialize(remoteContent); + remoteContent = dbItem.type_ == BaseModel.MODEL_TYPE_NOTE ? Note.unserialize(remoteContent) : Folder.unserialize(remoteContent); expect(remoteContent.title).toBe(dbItem.title); } } catch (error) { @@ -48,139 +48,139 @@ describe('Synchronizer', function() { done(); }); - // it('should create remote items', async (done) => { - // let folder = await Folder.save({ title: "folder1" }); - // await Note.save({ title: "un", parent_id: folder.id }); + it('should create remote items', async (done) => { + let folder = await Folder.save({ title: "folder1" }); + await Note.save({ title: "un", parent_id: folder.id }); - // let all = await Folder.all(true); + let all = await Folder.all(true); - // await synchronizer().start(); + await synchronizer().start(); - // await localItemsSameAsRemote(all, expect); + await localItemsSameAsRemote(all, expect); - // done(); - // }); + done(); + }); - // it('should update remote item', async (done) => { - // let folder = await Folder.save({ title: "folder1" }); - // let note = await Note.save({ title: "un", parent_id: folder.id }); - // await synchronizer().start(); + it('should update remote item', async (done) => { + let folder = await Folder.save({ title: "folder1" }); + let note = await Note.save({ title: "un", parent_id: folder.id }); + await synchronizer().start(); - // await sleep(0.1); + await sleep(0.1); - // await Note.save({ title: "un UPDATE", id: note.id }); + await Note.save({ title: "un UPDATE", id: note.id }); - // let all = await Folder.all(true); - // await synchronizer().start(); + let all = await Folder.all(true); + await synchronizer().start(); - // await localItemsSameAsRemote(all, expect); + await localItemsSameAsRemote(all, expect); - // done(); - // }); + done(); + }); - // it('should create local items', async (done) => { - // let folder = await Folder.save({ title: "folder1" }); - // await Note.save({ title: "un", parent_id: folder.id }); - // await synchronizer().start(); + it('should create local items', async (done) => { + let folder = await Folder.save({ title: "folder1" }); + await Note.save({ title: "un", parent_id: folder.id }); + await synchronizer().start(); - // switchClient(2); + switchClient(2); - // await synchronizer().start(); + await synchronizer().start(); - // let all = await Folder.all(true); - // await localItemsSameAsRemote(all, expect); + let all = await Folder.all(true); + await localItemsSameAsRemote(all, expect); - // done(); - // }); + done(); + }); - // it('should update local items', async (done) => { - // let folder1 = await Folder.save({ title: "folder1" }); - // let note1 = await Note.save({ title: "un", parent_id: folder1.id }); - // await synchronizer().start(); + it('should update local items', async (done) => { + let folder1 = await Folder.save({ title: "folder1" }); + let note1 = await Note.save({ title: "un", parent_id: folder1.id }); + await synchronizer().start(); - // switchClient(2); + switchClient(2); - // await synchronizer().start(); + await synchronizer().start(); - // await sleep(0.1); + await sleep(0.1); - // let note2 = await Note.load(note1.id); - // note2.title = "Updated on client 2"; - // await Note.save(note2); + let note2 = await Note.load(note1.id); + note2.title = "Updated on client 2"; + await Note.save(note2); - // note2 = await Note.load(note2.id); + note2 = await Note.load(note2.id); - // await synchronizer().start(); + await synchronizer().start(); - // let files = await fileApi().list(); + let files = await fileApi().list(); - // switchClient(1); + switchClient(1); - // await synchronizer().start(); + await synchronizer().start(); - // note1 = await Note.load(note1.id); + note1 = await Note.load(note1.id); - // expect(!!note1).toBe(true); - // expect(note1.title).toBe(note2.title); - // expect(note1.body).toBe(note2.body); + expect(!!note1).toBe(true); + expect(note1.title).toBe(note2.title); + expect(note1.body).toBe(note2.body); - // done(); - // }); + done(); + }); - // it('should resolve note conflicts', async (done) => { - // let folder1 = await Folder.save({ title: "folder1" }); - // let note1 = await Note.save({ title: "un", parent_id: folder1.id }); - // await synchronizer().start(); + it('should resolve note conflicts', async (done) => { + let folder1 = await Folder.save({ title: "folder1" }); + let note1 = await Note.save({ title: "un", parent_id: folder1.id }); + await synchronizer().start(); - // switchClient(2); + switchClient(2); - // await synchronizer().start(); + await synchronizer().start(); - // await sleep(0.1); + await sleep(0.1); - // let note2 = await Note.load(note1.id); - // note2.title = "Updated on client 2"; - // await Note.save(note2); - // note2 = await Note.load(note2.id); + let note2 = await Note.load(note1.id); + note2.title = "Updated on client 2"; + await Note.save(note2); + note2 = await Note.load(note2.id); - // await synchronizer().start(); + await synchronizer().start(); - // switchClient(1); + switchClient(1); - // await sleep(0.1); + await sleep(0.1); - // let note2conf = await Note.load(note1.id); - // note2conf.title = "Updated on client 1"; - // await Note.save(note2conf); - // note2conf = await Note.load(note1.id); + let note2conf = await Note.load(note1.id); + note2conf.title = "Updated on client 1"; + await Note.save(note2conf); + note2conf = await Note.load(note1.id); - // await synchronizer().start(); + await synchronizer().start(); - // let conflictFolder = await Folder.conflictFolder(); - // let conflictedNotes = await Note.all(conflictFolder.id); + let conflictFolder = await Folder.conflictFolder(); + let conflictedNotes = await Note.all(conflictFolder.id); - // expect(conflictedNotes.length).toBe(1); + expect(conflictedNotes.length).toBe(1); - // // Other than the id (since the conflicted note is a duplicate), parent_id (which is now the Conflicts folder) and sync_time, - // // the note must be the same in every way, to make sure no data has been lost. - // let conflictedNote = conflictedNotes[0]; - // expect(conflictedNote.id == note2conf.id).toBe(false); - // expect(conflictedNote.parent_id == note2conf.parent_id).toBe(false); - // for (let n in conflictedNote) { - // if (!conflictedNote.hasOwnProperty(n)) continue; - // if (n == 'id' || n == 'parent_id') continue; - // expect(conflictedNote[n]).toBe(note2conf[n], 'Property: ' + n); - // } + // Other than the id (since the conflicted note is a duplicate), parent_id (which is now the Conflicts folder) and sync_time, + // the note must be the same in every way, to make sure no data has been lost. + let conflictedNote = conflictedNotes[0]; + expect(conflictedNote.id == note2conf.id).toBe(false); + expect(conflictedNote.parent_id == note2conf.parent_id).toBe(false); + for (let n in conflictedNote) { + if (!conflictedNote.hasOwnProperty(n)) continue; + if (n == 'id' || n == 'parent_id') continue; + expect(conflictedNote[n]).toBe(note2conf[n], 'Property: ' + n); + } - // let noteUpdatedFromRemote = await Note.load(note1.id); - // for (let n in noteUpdatedFromRemote) { - // if (!noteUpdatedFromRemote.hasOwnProperty(n)) continue; - // if (n == 'sync_time') continue; - // expect(noteUpdatedFromRemote[n]).toBe(note2[n], 'Property: ' + n); - // } + let noteUpdatedFromRemote = await Note.load(note1.id); + for (let n in noteUpdatedFromRemote) { + if (!noteUpdatedFromRemote.hasOwnProperty(n)) continue; + if (n == 'sync_time') continue; + expect(noteUpdatedFromRemote[n]).toBe(note2[n], 'Property: ' + n); + } - // done(); - // }); + done(); + }); it('should resolve folders conflicts', async (done) => { let folder1 = await Folder.save({ title: "folder1" }); @@ -214,29 +214,6 @@ describe('Synchronizer', function() { let folder1_final = await Folder.load(folder1.id); expect(folder1_final.title).toBe(folder1_modRemote.title); - // let conflictFolder = await Folder.conflictFolder(); - // let conflictedNotes = await Note.all(conflictFolder.id); - - // expect(conflictedNotes.length).toBe(1); - - // // Other than the id (since the conflicted note is a duplicate), parent_id (which is now the Conflicts folder) and sync_time, - // // the note must be the same in every way, to make sure no data has been lost. - // let conflictedNote = conflictedNotes[0]; - // expect(conflictedNote.id == note2conf.id).toBe(false); - // expect(conflictedNote.parent_id == note2conf.parent_id).toBe(false); - // for (let n in conflictedNote) { - // if (!conflictedNote.hasOwnProperty(n)) continue; - // if (n == 'id' || n == 'parent_id') continue; - // expect(conflictedNote[n]).toBe(note2conf[n], 'Property: ' + n); - // } - - // let noteUpdatedFromRemote = await Note.load(note1.id); - // for (let n in noteUpdatedFromRemote) { - // if (!noteUpdatedFromRemote.hasOwnProperty(n)) continue; - // if (n == 'sync_time') continue; - // expect(noteUpdatedFromRemote[n]).toBe(note2[n], 'Property: ' + n); - // } - done(); }); diff --git a/ReactNativeClient/src/base-model.js b/ReactNativeClient/src/base-model.js index d78184c502..ad81aab5b6 100644 --- a/ReactNativeClient/src/base-model.js +++ b/ReactNativeClient/src/base-model.js @@ -67,8 +67,8 @@ class BaseModel { static identifyItemType(item) { if (!item) throw new Error('Cannot identify undefined item'); - if ('body' in item || ('parent_id' in item && !!item.parent_id)) return BaseModel.ITEM_TYPE_NOTE; - if ('sync_time' in item) return BaseModel.ITEM_TYPE_FOLDER; + if ('body' in item || ('parent_id' in item && !!item.parent_id)) return BaseModel.MODEL_TYPE_NOTE; + if ('sync_time' in item) return BaseModel.MODEL_TYPE_FOLDER; throw new Error('Cannot identify item: ' + JSON.stringify(item)); } @@ -268,8 +268,9 @@ class BaseModel { } -BaseModel.ITEM_TYPE_NOTE = 1; -BaseModel.ITEM_TYPE_FOLDER = 2; +BaseModel.MODEL_TYPE_NOTE = 1; +BaseModel.MODEL_TYPE_FOLDER = 2; +BaseModel.MODEL_TYPE_SETTING = 3; BaseModel.tableInfo_ = null; BaseModel.tableKeys_ = null; BaseModel.db_ = null; diff --git a/ReactNativeClient/src/models/base-item.js b/ReactNativeClient/src/models/base-item.js index 4d9ca9a49e..4483517001 100644 --- a/ReactNativeClient/src/models/base-item.js +++ b/ReactNativeClient/src/models/base-item.js @@ -22,10 +22,10 @@ class BaseItem extends BaseModel { if (typeof item === 'object') { if (!('type_' in item)) throw new Error('Item does not have a type_ property'); - return item.type_ == BaseModel.ITEM_TYPE_NOTE ? Note : Folder; + return item.type_ == BaseModel.MODEL_TYPE_NOTE ? Note : Folder; } else { - if (Number(item) === BaseModel.ITEM_TYPE_NOTE) return Note; - if (Number(item) === BaseModel.ITEM_TYPE_FOLDER) return Folder; + if (Number(item) === BaseModel.MODEL_TYPE_NOTE) return Note; + if (Number(item) === BaseModel.MODEL_TYPE_FOLDER) return Folder; throw new Error('Unknown type: ' + item); } } @@ -119,7 +119,7 @@ class BaseItem extends BaseModel { if (!output.type_) throw new Error('Missing required property: type_: ' + content); output.type_ = Number(output.type_); - if (output.type_ == BaseModel.ITEM_TYPE_NOTE) output.body = body.join("\n"); + if (output.type_ == BaseModel.MODEL_TYPE_NOTE) output.body = body.join("\n"); for (let n in output) { if (!output.hasOwnProperty(n)) continue; diff --git a/ReactNativeClient/src/models/folder.js b/ReactNativeClient/src/models/folder.js index 43dca75902..e4728485ac 100644 --- a/ReactNativeClient/src/models/folder.js +++ b/ReactNativeClient/src/models/folder.js @@ -19,7 +19,7 @@ class Folder extends BaseItem { } static itemType() { - return BaseModel.ITEM_TYPE_FOLDER; + return BaseModel.MODEL_TYPE_FOLDER; } static trackChanges() { diff --git a/ReactNativeClient/src/models/note.js b/ReactNativeClient/src/models/note.js index cf5b1eb57b..bf4640e9d0 100644 --- a/ReactNativeClient/src/models/note.js +++ b/ReactNativeClient/src/models/note.js @@ -17,7 +17,7 @@ class Note extends BaseItem { } static itemType() { - return BaseModel.ITEM_TYPE_NOTE; + return BaseModel.MODEL_TYPE_NOTE; } static trackChanges() { diff --git a/ReactNativeClient/src/models/setting.js b/ReactNativeClient/src/models/setting.js index a335799b47..678be35d06 100644 --- a/ReactNativeClient/src/models/setting.js +++ b/ReactNativeClient/src/models/setting.js @@ -8,6 +8,10 @@ class Setting extends BaseModel { return 'settings'; } + static itemType() { + return BaseModel.MODEL_TYPE_SETTING; + } + static defaultSetting(key) { if (!(key in this.defaults_)) throw new Error('Unknown key: ' + key); let output = Object.assign({}, this.defaults_[key]); @@ -26,8 +30,9 @@ class Setting extends BaseModel { } static load() { + this.cancelScheduleUpdate(); this.cache_ = []; - return this.db().selectAll('SELECT * FROM settings').then((rows) => { + return this.modelSelectAll('SELECT * FROM settings').then((rows) => { this.cache_ = rows; }); } @@ -113,6 +118,11 @@ class Setting extends BaseModel { }, 500); } + static cancelScheduleUpdate() { + if (this.updateTimeoutId_) clearTimeout(this.updateTimeoutId_); + this.updateTimeoutId_ = null; + } + } Setting.defaults_ = { diff --git a/ReactNativeClient/src/synchronizer.js b/ReactNativeClient/src/synchronizer.js index 31c69b4557..9af8bd4c5d 100644 --- a/ReactNativeClient/src/synchronizer.js +++ b/ReactNativeClient/src/synchronizer.js @@ -54,7 +54,7 @@ class Synchronizer { // Since, in this loop, we are only dealing with notes that require sync, if the // remote has been modified after the sync time, it means both notes have been // modified and so there's a conflict. - action = local.type_ == BaseModel.ITEM_TYPE_NOTE ? 'noteConflict' : 'folderConflict'; + action = local.type_ == BaseModel.MODEL_TYPE_NOTE ? 'noteConflict' : 'folderConflict'; } else { action = 'updateRemote'; } diff --git a/ReactNativeClient/src/synchronizer_old.js b/ReactNativeClient/src/synchronizer_old.js index aa583599e7..0f733c38b7 100644 --- a/ReactNativeClient/src/synchronizer_old.js +++ b/ReactNativeClient/src/synchronizer_old.js @@ -27,7 +27,7 @@ class Synchronizer { } loadParentAndItem(change) { - if (change.item_type == BaseModel.ITEM_TYPE_NOTE) { + if (change.item_type == BaseModel.MODEL_TYPE_NOTE) { return Note.load(change.item_id).then((note) => { return Folder.load(note.parent_id).then((folder) => { return Promise.resolve({ parent: folder, item: note }); @@ -52,10 +52,10 @@ class Synchronizer { let ItemClass = null; let path = null; - if (c.item_type == BaseModel.ITEM_TYPE_FOLDER) { + if (c.item_type == BaseModel.MODEL_TYPE_FOLDER) { ItemClass = Folder; path = 'folders'; - } else if (c.item_type == BaseModel.ITEM_TYPE_NOTE) { + } else if (c.item_type == BaseModel.MODEL_TYPE_NOTE) { ItemClass = Note; path = 'notes'; } diff --git a/ReactNativeClient/src/synchronizer_old2.js b/ReactNativeClient/src/synchronizer_old2.js index 950e5c51bf..39f0c59ed2 100644 --- a/ReactNativeClient/src/synchronizer_old2.js +++ b/ReactNativeClient/src/synchronizer_old2.js @@ -38,7 +38,7 @@ class Synchronizer { } loadParentAndItem(change) { - if (change.item_type == BaseModel.ITEM_TYPE_NOTE) { + if (change.item_type == BaseModel.MODEL_TYPE_NOTE) { return Note.load(change.item_id).then((note) => { if (!note) return { parent:null, item: null }; @@ -107,7 +107,7 @@ class Synchronizer { if (!dbItem) return null; return { - type: dbItem.type_ == BaseModel.ITEM_TYPE_FOLDER ? 'folder' : 'note', + type: dbItem.type_ == BaseModel.MODEL_TYPE_FOLDER ? 'folder' : 'note', path: Folder.systemPath(dbItem), syncTime: dbItem.sync_time, updated_time: dbItem.updated_time, @@ -119,7 +119,7 @@ class Synchronizer { if (!remoteItem) return null; return { - type: remoteItem.content.type_ == BaseModel.ITEM_TYPE_FOLDER ? 'folder' : 'note', + type: remoteItem.content.type_ == BaseModel.MODEL_TYPE_FOLDER ? 'folder' : 'note', path: remoteItem.path, syncTime: 0, updated_time: remoteItem.updated_time,