You've already forked joplin
							
							
				mirror of
				https://github.com/laurent22/joplin.git
				synced 2025-10-31 00:07:48 +02:00 
			
		
		
		
	Deleted uneeded file
This commit is contained in:
		| @@ -62,568 +62,596 @@ describe('Synchronizer', function() { | |||||||
| 		done(); | 		done(); | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
| 	it('should create remote items', async (done) => { | 	// it('should create remote items', async (done) => { | ||||||
| 		let folder = await Folder.save({ title: "folder1" }); | 	// 	let folder = await Folder.save({ title: "folder1" }); | ||||||
| 		await Note.save({ title: "un", parent_id: folder.id }); | 	// 	await Note.save({ title: "un", parent_id: folder.id }); | ||||||
|  |  | ||||||
| 		let all = await allItems(); | 	// 	let all = await allItems(); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await localItemsSameAsRemote(all, expect); | 	// 	await localItemsSameAsRemote(all, expect); | ||||||
|  |  | ||||||
| 		done(); | 	// 	done(); | ||||||
| 	}); | 	// }); | ||||||
|  |  | ||||||
| 	it('should update remote item', async (done) => { | 	// it('should update remote item', async (done) => { | ||||||
| 		let folder = await Folder.save({ title: "folder1" }); | 	// 	let folder = await Folder.save({ title: "folder1" }); | ||||||
| 		let note = await Note.save({ title: "un", parent_id: folder.id }); | 	// 	let note = await Note.save({ title: "un", parent_id: folder.id }); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await Note.save({ title: "un UPDATE", id: note.id }); | 	// 	await Note.save({ title: "un UPDATE", id: note.id }); | ||||||
|  |  | ||||||
| 		let all = await allItems(); | 	// 	let all = await allItems(); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await localItemsSameAsRemote(all, expect); | 	// 	await localItemsSameAsRemote(all, expect); | ||||||
|  |  | ||||||
| 		done(); | 	// 	done(); | ||||||
| 	}); | 	// }); | ||||||
|  |  | ||||||
| 	it('should create local items', async (done) => { | 	// it('should create local items', async (done) => { | ||||||
| 		let folder = await Folder.save({ title: "folder1" }); | 	// 	let folder = await Folder.save({ title: "folder1" }); | ||||||
| 		await Note.save({ title: "un", parent_id: folder.id }); | 	// 	await Note.save({ title: "un", parent_id: folder.id }); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(2); | 	// 	await switchClient(2); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		let all = await allItems(); | 	// 	let all = await allItems(); | ||||||
| 		await localItemsSameAsRemote(all, expect); | 	// 	await localItemsSameAsRemote(all, expect); | ||||||
|  |  | ||||||
| 		done(); | 	// 	done(); | ||||||
| 	}); | 	// }); | ||||||
|  |  | ||||||
| 	it('should update local items', async (done) => { | 	// it('should update local items', async (done) => { | ||||||
| 		let folder1 = await Folder.save({ title: "folder1" }); | 	// 	let folder1 = await Folder.save({ title: "folder1" }); | ||||||
| 		let note1 = await Note.save({ title: "un", parent_id: folder1.id }); | 	// 	let note1 = await Note.save({ title: "un", parent_id: folder1.id }); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(2); | 	// 	await switchClient(2); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await sleep(0.1); | 	// 	await sleep(0.1); | ||||||
|  |  | ||||||
| 		let note2 = await Note.load(note1.id); | 	// 	let note2 = await Note.load(note1.id); | ||||||
| 		note2.title = "Updated on client 2"; | 	// 	note2.title = "Updated on client 2"; | ||||||
| 		await Note.save(note2); | 	// 	await Note.save(note2); | ||||||
| 		note2 = await Note.load(note2.id); | 	// 	note2 = await Note.load(note2.id); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(1); | 	// 	await switchClient(1); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		let all = await allItems(); | 	// 	let all = await allItems(); | ||||||
|  |  | ||||||
| 		await localItemsSameAsRemote(all, expect); | 	// 	await localItemsSameAsRemote(all, expect); | ||||||
|  |  | ||||||
| 		done(); | 	// 	done(); | ||||||
| 	}); | 	// }); | ||||||
|  |  | ||||||
| 	it('should resolve note conflicts', async (done) => { | 	// it('should resolve note conflicts', async (done) => { | ||||||
| 		let folder1 = await Folder.save({ title: "folder1" }); | 	// 	let folder1 = await Folder.save({ title: "folder1" }); | ||||||
| 		let note1 = await Note.save({ title: "un", parent_id: folder1.id }); | 	// 	let note1 = await Note.save({ title: "un", parent_id: folder1.id }); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(2); | 	// 	await switchClient(2); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
| 		let note2 = await Note.load(note1.id); | 	// 	let note2 = await Note.load(note1.id); | ||||||
| 		note2.title = "Updated on client 2"; | 	// 	note2.title = "Updated on client 2"; | ||||||
| 		await Note.save(note2); | 	// 	await Note.save(note2); | ||||||
| 		note2 = await Note.load(note2.id); | 	// 	note2 = await Note.load(note2.id); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(1); | 	// 	await switchClient(1); | ||||||
|  |  | ||||||
| 		let note2conf = await Note.load(note1.id); | 	// 	let note2conf = await Note.load(note1.id); | ||||||
| 		note2conf.title = "Updated on client 1"; | 	// 	note2conf.title = "Updated on client 1"; | ||||||
| 		await Note.save(note2conf); | 	// 	await Note.save(note2conf); | ||||||
| 		note2conf = await Note.load(note1.id); | 	// 	note2conf = await Note.load(note1.id); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
| 		let conflictedNotes = await Note.conflictedNotes(); | 	// 	let conflictedNotes = await Note.conflictedNotes(); | ||||||
| 		expect(conflictedNotes.length).toBe(1); | 	// 	expect(conflictedNotes.length).toBe(1); | ||||||
|  |  | ||||||
| 		// Other than the id (since the conflicted note is a duplicate), and the is_conflict property | 	// 	// Other than the id (since the conflicted note is a duplicate), and the is_conflict property | ||||||
| 		// the conflicted and original note must be the same in every way, to make sure no data has been lost. | 	// 	// the conflicted and original note must be the same in every way, to make sure no data has been lost. | ||||||
| 		let conflictedNote = conflictedNotes[0]; | 	// 	let conflictedNote = conflictedNotes[0]; | ||||||
| 		expect(conflictedNote.id == note2conf.id).toBe(false); | 	// 	expect(conflictedNote.id == note2conf.id).toBe(false); | ||||||
| 		for (let n in conflictedNote) { | 	// 	for (let n in conflictedNote) { | ||||||
| 			if (!conflictedNote.hasOwnProperty(n)) continue; | 	// 		if (!conflictedNote.hasOwnProperty(n)) continue; | ||||||
| 			if (n == 'id' || n == 'is_conflict') continue; | 	// 		if (n == 'id' || n == 'is_conflict') continue; | ||||||
| 			expect(conflictedNote[n]).toBe(note2conf[n], 'Property: ' + n); | 	// 		expect(conflictedNote[n]).toBe(note2conf[n], 'Property: ' + n); | ||||||
| 		} | 	// 	} | ||||||
|  |  | ||||||
| 		let noteUpdatedFromRemote = await Note.load(note1.id); | 	// 	let noteUpdatedFromRemote = await Note.load(note1.id); | ||||||
| 		for (let n in noteUpdatedFromRemote) { | 	// 	for (let n in noteUpdatedFromRemote) { | ||||||
| 			if (!noteUpdatedFromRemote.hasOwnProperty(n)) continue; | 	// 		if (!noteUpdatedFromRemote.hasOwnProperty(n)) continue; | ||||||
| 			expect(noteUpdatedFromRemote[n]).toBe(note2[n], 'Property: ' + n); | 	// 		expect(noteUpdatedFromRemote[n]).toBe(note2[n], 'Property: ' + n); | ||||||
| 		} | 	// 	} | ||||||
|  |  | ||||||
| 		done(); | 	// 	done(); | ||||||
| 	}); | 	// }); | ||||||
|  |  | ||||||
| 	it('should resolve folders conflicts', async (done) => { | 	// it('should resolve folders conflicts', async (done) => { | ||||||
| 		let folder1 = await Folder.save({ title: "folder1" }); | 	// 	let folder1 = await Folder.save({ title: "folder1" }); | ||||||
| 		let note1 = await Note.save({ title: "un", parent_id: folder1.id }); | 	// 	let note1 = await Note.save({ title: "un", parent_id: folder1.id }); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(2); // ---------------------------------- | 	// 	await switchClient(2); // ---------------------------------- | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await sleep(0.1); | 	// 	await sleep(0.1); | ||||||
|  |  | ||||||
| 		let folder1_modRemote = await Folder.load(folder1.id); | 	// 	let folder1_modRemote = await Folder.load(folder1.id); | ||||||
| 		folder1_modRemote.title = "folder1 UPDATE CLIENT 2"; | 	// 	folder1_modRemote.title = "folder1 UPDATE CLIENT 2"; | ||||||
| 		await Folder.save(folder1_modRemote); | 	// 	await Folder.save(folder1_modRemote); | ||||||
| 		folder1_modRemote = await Folder.load(folder1_modRemote.id); | 	// 	folder1_modRemote = await Folder.load(folder1_modRemote.id); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(1); // ---------------------------------- | 	// 	await switchClient(1); // ---------------------------------- | ||||||
|  |  | ||||||
| 		await sleep(0.1); | 	// 	await sleep(0.1); | ||||||
|  |  | ||||||
| 		let folder1_modLocal = await Folder.load(folder1.id); | 	// 	let folder1_modLocal = await Folder.load(folder1.id); | ||||||
| 		folder1_modLocal.title = "folder1 UPDATE CLIENT 1"; | 	// 	folder1_modLocal.title = "folder1 UPDATE CLIENT 1"; | ||||||
| 		await Folder.save(folder1_modLocal); | 	// 	await Folder.save(folder1_modLocal); | ||||||
| 		folder1_modLocal = await Folder.load(folder1.id); | 	// 	folder1_modLocal = await Folder.load(folder1.id); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		let folder1_final = await Folder.load(folder1.id); | 	// 	let folder1_final = await Folder.load(folder1.id); | ||||||
| 		expect(folder1_final.title).toBe(folder1_modRemote.title); | 	// 	expect(folder1_final.title).toBe(folder1_modRemote.title); | ||||||
|  |  | ||||||
| 		done(); | 	// 	done(); | ||||||
| 	}); | 	// }); | ||||||
|  |  | ||||||
| 	it('should delete remote notes', async (done) => { | 	// it('should delete remote notes', async (done) => { | ||||||
| 		let folder1 = await Folder.save({ title: "folder1" }); | 	// 	let folder1 = await Folder.save({ title: "folder1" }); | ||||||
| 		let note1 = await Note.save({ title: "un", parent_id: folder1.id }); | 	// 	let note1 = await Note.save({ title: "un", parent_id: folder1.id }); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(2); | 	// 	await switchClient(2); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await sleep(0.1); | 	// 	await sleep(0.1); | ||||||
|  |  | ||||||
| 		await Note.delete(note1.id); | 	// 	await Note.delete(note1.id); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		let files = await fileApi().list(); | 	// 	let files = await fileApi().list(); | ||||||
| 		files = files.items; | 	// 	files = files.items; | ||||||
|  |  | ||||||
| 		expect(files.length).toBe(1); | 	// 	expect(files.length).toBe(1); | ||||||
| 		expect(files[0].path).toBe(Folder.systemPath(folder1)); | 	// 	expect(files[0].path).toBe(Folder.systemPath(folder1)); | ||||||
|  |  | ||||||
| 		let deletedItems = await BaseItem.deletedItems(syncTargetId()); | 	// 	let deletedItems = await BaseItem.deletedItems(syncTargetId()); | ||||||
| 		expect(deletedItems.length).toBe(0); | 	// 	expect(deletedItems.length).toBe(0); | ||||||
|  |  | ||||||
| 		done(); | 	// 	done(); | ||||||
| 	}); | 	// }); | ||||||
|  |  | ||||||
| 	it('should delete local notes', async (done) => { | 	// it('should delete local notes', async (done) => { | ||||||
| 		let folder1 = await Folder.save({ title: "folder1" }); | 	// 	let folder1 = await Folder.save({ title: "folder1" }); | ||||||
| 		let note1 = await Note.save({ title: "un", parent_id: folder1.id }); | 	// 	let note1 = await Note.save({ title: "un", parent_id: folder1.id }); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(2); | 	// 	await switchClient(2); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
| 		await Note.delete(note1.id); | 	// 	await Note.delete(note1.id); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(1); | 	// 	await switchClient(1); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
| 		let items = await allItems(); | 	// 	let items = await allItems(); | ||||||
| 		expect(items.length).toBe(1); | 	// 	expect(items.length).toBe(1); | ||||||
| 		let deletedItems = await BaseItem.deletedItems(syncTargetId()); | 	// 	let deletedItems = await BaseItem.deletedItems(syncTargetId()); | ||||||
| 		expect(deletedItems.length).toBe(0); | 	// 	expect(deletedItems.length).toBe(0); | ||||||
| 		 | 		 | ||||||
| 		done(); | 	// 	done(); | ||||||
| 	}); | 	// }); | ||||||
|  |  | ||||||
| 	it('should delete remote folder', async (done) => { | 	// it('should delete remote folder', async (done) => { | ||||||
| 		let folder1 = await Folder.save({ title: "folder1" }); | 	// 	let folder1 = await Folder.save({ title: "folder1" }); | ||||||
| 		let folder2 = await Folder.save({ title: "folder2" }); | 	// 	let folder2 = await Folder.save({ title: "folder2" }); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(2); | 	// 	await switchClient(2); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await sleep(0.1); | 	// 	await sleep(0.1); | ||||||
|  |  | ||||||
| 		await Folder.delete(folder2.id); | 	// 	await Folder.delete(folder2.id); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		let all = await allItems(); | 	// 	let all = await allItems(); | ||||||
| 		localItemsSameAsRemote(all, expect); | 	// 	localItemsSameAsRemote(all, expect); | ||||||
| 		 | 		 | ||||||
| 		done(); | 	// 	done(); | ||||||
| 	}); | 	// }); | ||||||
|  |  | ||||||
| 	it('should delete local folder', async (done) => { | 	// it('should delete local folder', async (done) => { | ||||||
| 		let folder1 = await Folder.save({ title: "folder1" }); | 	// 	let folder1 = await Folder.save({ title: "folder1" }); | ||||||
| 		let folder2 = await Folder.save({ title: "folder2" }); | 	// 	let folder2 = await Folder.save({ title: "folder2" }); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(2); | 	// 	await switchClient(2); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await sleep(0.1); | 	// 	await sleep(0.1); | ||||||
|  |  | ||||||
| 		await Folder.delete(folder2.id); | 	// 	await Folder.delete(folder2.id); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(1); | 	// 	await switchClient(1); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		let items = await allItems(); | 	// 	let items = await allItems(); | ||||||
| 		localItemsSameAsRemote(items, expect); | 	// 	localItemsSameAsRemote(items, expect); | ||||||
| 		 | 		 | ||||||
| 		done(); | 	// 	done(); | ||||||
| 	}); | 	// }); | ||||||
|  |  | ||||||
| 	it('should resolve conflict if remote folder has been deleted, but note has been added to folder locally', async (done) => { | 	// it('should resolve conflict if remote folder has been deleted, but note has been added to folder locally', async (done) => { | ||||||
| 		let folder1 = await Folder.save({ title: "folder1" }); | 	// 	let folder1 = await Folder.save({ title: "folder1" }); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(2); | 	// 	await switchClient(2); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
| 		await Folder.delete(folder1.id); | 	// 	await Folder.delete(folder1.id); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(1); | 	// 	await switchClient(1); | ||||||
|  |  | ||||||
| 		let note = await Note.save({ title: "note1", parent_id: folder1.id }); | 	// 	let note = await Note.save({ title: "note1", parent_id: folder1.id }); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
| 		let items = await allItems();		 | 	// 	let items = await allItems();		 | ||||||
| 		expect(items.length).toBe(1); | 	// 	expect(items.length).toBe(1); | ||||||
| 		expect(items[0].title).toBe('note1'); | 	// 	expect(items[0].title).toBe('note1'); | ||||||
| 		expect(items[0].is_conflict).toBe(1); | 	// 	expect(items[0].is_conflict).toBe(1); | ||||||
| 		 | 		 | ||||||
| 		done(); | 	// 	done(); | ||||||
| 	}); | 	// }); | ||||||
|  |  | ||||||
| 	it('should resolve conflict if note has been deleted remotely and locally', async (done) => { | 	// it('should resolve conflict if note has been deleted remotely and locally', async (done) => { | ||||||
| 		let folder = await Folder.save({ title: "folder" }); | 	// 	let folder = await Folder.save({ title: "folder" }); | ||||||
| 		let note = await Note.save({ title: "note", parent_id: folder.title }); | 	// 	let note = await Note.save({ title: "note", parent_id: folder.title }); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(2); | 	// 	await switchClient(2); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
| 		await Note.delete(note.id); | 	// 	await Note.delete(note.id); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(1); | 	// 	await switchClient(1); | ||||||
|  |  | ||||||
| 		await Note.delete(note.id); | 	// 	await Note.delete(note.id); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		let items = await allItems(); | 	// 	let items = await allItems(); | ||||||
| 		expect(items.length).toBe(1); | 	// 	expect(items.length).toBe(1); | ||||||
| 		expect(items[0].title).toBe('folder'); | 	// 	expect(items[0].title).toBe('folder'); | ||||||
|  |  | ||||||
| 		localItemsSameAsRemote(items, expect); | 	// 	localItemsSameAsRemote(items, expect); | ||||||
| 		 | 		 | ||||||
| 		done(); | 	// 	done(); | ||||||
| 	}); | 	// }); | ||||||
|  |  | ||||||
| 	it('should cross delete all folders', async (done) => { | 	// it('should cross delete all folders', async (done) => { | ||||||
| 		// If client1 and 2 have two folders, client 1 deletes item 1 and client | 	// 	// If client1 and 2 have two folders, client 1 deletes item 1 and client | ||||||
| 		// 2 deletes item 2, they should both end up with no items after sync. | 	// 	// 2 deletes item 2, they should both end up with no items after sync. | ||||||
|  |  | ||||||
| 		let folder1 = await Folder.save({ title: "folder1" }); | 	// 	let folder1 = await Folder.save({ title: "folder1" }); | ||||||
| 		let folder2 = await Folder.save({ title: "folder2" }); | 	// 	let folder2 = await Folder.save({ title: "folder2" }); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(2); | 	// 	await switchClient(2); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await sleep(0.1); | 	// 	await sleep(0.1); | ||||||
|  |  | ||||||
| 		await Folder.delete(folder1.id); | 	// 	await Folder.delete(folder1.id); | ||||||
|  |  | ||||||
| 		await switchClient(1); | 	// 	await switchClient(1); | ||||||
|  |  | ||||||
| 		await Folder.delete(folder2.id); | 	// 	await Folder.delete(folder2.id); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(2); | 	// 	await switchClient(2); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		let items2 = await allItems(); | 	// 	let items2 = await allItems(); | ||||||
|  |  | ||||||
| 		await switchClient(1); | 	// 	await switchClient(1); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		let items1 = await allItems(); | 	// 	let items1 = await allItems(); | ||||||
|  |  | ||||||
| 		expect(items1.length).toBe(0); | 	// 	expect(items1.length).toBe(0); | ||||||
| 		expect(items1.length).toBe(items2.length); | 	// 	expect(items1.length).toBe(items2.length); | ||||||
| 		 | 		 | ||||||
| 		done(); | 	// 	done(); | ||||||
| 	}); | 	// }); | ||||||
|  |  | ||||||
| 	it('should handle conflict when remote note is deleted then local note is modified', async (done) => { | 	// it('should handle conflict when remote note is deleted then local note is modified', async (done) => { | ||||||
| 		let folder1 = await Folder.save({ title: "folder1" }); | 	// 	let folder1 = await Folder.save({ title: "folder1" }); | ||||||
| 		let note1 = await Note.save({ title: "un", parent_id: folder1.id }); | 	// 	let note1 = await Note.save({ title: "un", parent_id: folder1.id }); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(2); | 	// 	await switchClient(2); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await sleep(0.1); | 	// 	await sleep(0.1); | ||||||
|  |  | ||||||
| 		await Note.delete(note1.id); | 	// 	await Note.delete(note1.id); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(1); | 	// 	await switchClient(1); | ||||||
|  |  | ||||||
| 		let newTitle = 'Modified after having been deleted'; | 	// 	let newTitle = 'Modified after having been deleted'; | ||||||
| 		await Note.save({ id: note1.id, title: newTitle }); | 	// 	await Note.save({ id: note1.id, title: newTitle }); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		let conflictedNotes = await Note.conflictedNotes(); | 	// 	let conflictedNotes = await Note.conflictedNotes(); | ||||||
|  |  | ||||||
| 		expect(conflictedNotes.length).toBe(1); | 	// 	expect(conflictedNotes.length).toBe(1); | ||||||
| 		expect(conflictedNotes[0].title).toBe(newTitle); | 	// 	expect(conflictedNotes[0].title).toBe(newTitle); | ||||||
|  |  | ||||||
| 		let unconflictedNotes = await Note.unconflictedNotes(); | 	// 	let unconflictedNotes = await Note.unconflictedNotes(); | ||||||
|  |  | ||||||
| 		expect(unconflictedNotes.length).toBe(0); | 	// 	expect(unconflictedNotes.length).toBe(0); | ||||||
| 		 | 		 | ||||||
| 		done(); | 	// 	done(); | ||||||
| 	}); | 	// }); | ||||||
|  |  | ||||||
| 	it('should handle conflict when remote folder is deleted then local folder is renamed', async (done) => { | 	// it('should handle conflict when remote folder is deleted then local folder is renamed', async (done) => { | ||||||
| 		let folder1 = await Folder.save({ title: "folder1" }); | 	// 	let folder1 = await Folder.save({ title: "folder1" }); | ||||||
| 		let folder2 = await Folder.save({ title: "folder2" }); | 	// 	let folder2 = await Folder.save({ title: "folder2" }); | ||||||
| 		let note1 = await Note.save({ title: "un", parent_id: folder1.id }); | 	// 	let note1 = await Note.save({ title: "un", parent_id: folder1.id }); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(2); | 	// 	await switchClient(2); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await sleep(0.1); | 	// 	await sleep(0.1); | ||||||
|  |  | ||||||
| 		await Folder.delete(folder1.id); | 	// 	await Folder.delete(folder1.id); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(1); | 	// 	await switchClient(1); | ||||||
|  |  | ||||||
| 		await sleep(0.1); | 	// 	await sleep(0.1); | ||||||
|  |  | ||||||
| 		let newTitle = 'Modified after having been deleted'; | 	// 	let newTitle = 'Modified after having been deleted'; | ||||||
| 		await Folder.save({ id: folder1.id, title: newTitle }); | 	// 	await Folder.save({ id: folder1.id, title: newTitle }); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		let items = await allItems(); | 	// 	let items = await allItems(); | ||||||
|  |  | ||||||
| 		expect(items.length).toBe(1); | 	// 	expect(items.length).toBe(1); | ||||||
| 		 | 		 | ||||||
| 		done(); | 	// 	done(); | ||||||
| 	}); | 	// }); | ||||||
|  |  | ||||||
| 	it('should allow duplicate folder titles', async (done) => { | 	// it('should allow duplicate folder titles', async (done) => { | ||||||
| 		let localF1 = await Folder.save({ title: "folder" }); | 	// 	let localF1 = await Folder.save({ title: "folder" }); | ||||||
|  |  | ||||||
| 		await switchClient(2); | 	// 	await switchClient(2); | ||||||
|  |  | ||||||
| 		let remoteF2 = await Folder.save({ title: "folder" }); | 	// 	let remoteF2 = await Folder.save({ title: "folder" }); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(1); | 	// 	await switchClient(1); | ||||||
|  |  | ||||||
| 		await sleep(0.1); | 	// 	await sleep(0.1); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		let localF2 = await Folder.load(remoteF2.id); | 	// 	let localF2 = await Folder.load(remoteF2.id); | ||||||
|  |  | ||||||
| 		expect(localF2.title == remoteF2.title).toBe(true); | 	// 	expect(localF2.title == remoteF2.title).toBe(true); | ||||||
|  |  | ||||||
| 		// Then that folder that has been renamed locally should be set in such a way | 	// 	// Then that folder that has been renamed locally should be set in such a way | ||||||
| 		// that synchronizing it applies the title change remotely, and that new title | 	// 	// that synchronizing it applies the title change remotely, and that new title | ||||||
| 		// should be retrieved by client 2. | 	// 	// should be retrieved by client 2. | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(2); | 	// 	await switchClient(2); | ||||||
| 		await sleep(0.1); | 	// 	await sleep(0.1); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		remoteF2 = await Folder.load(remoteF2.id); | 	// 	remoteF2 = await Folder.load(remoteF2.id); | ||||||
|  |  | ||||||
| 		expect(remoteF2.title == localF2.title).toBe(true); | 	// 	expect(remoteF2.title == localF2.title).toBe(true); | ||||||
|  |  | ||||||
| 		done(); | 	// 	done(); | ||||||
| 	}); | 	// }); | ||||||
|  |  | ||||||
| 	it('should sync tags', async (done) => { | 	// it('should sync tags', async (done) => { | ||||||
| 		let f1 = await Folder.save({ title: "folder" }); | 	// 	let f1 = await Folder.save({ title: "folder" }); | ||||||
| 		let n1 = await Note.save({ title: "mynote" }); | 	// 	let n1 = await Note.save({ title: "mynote" }); | ||||||
| 		let n2 = await Note.save({ title: "mynote2" }); | 	// 	let n2 = await Note.save({ title: "mynote2" }); | ||||||
| 		let tag = await Tag.save({ title: 'mytag' }); | 	// 	let tag = await Tag.save({ title: 'mytag' }); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(2); | 	// 	await switchClient(2); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
| 		let remoteTag = await Tag.loadByTitle(tag.title); | 	// 	let remoteTag = await Tag.loadByTitle(tag.title); | ||||||
| 		expect(!!remoteTag).toBe(true); | 	// 	expect(!!remoteTag).toBe(true); | ||||||
| 		expect(remoteTag.id).toBe(tag.id); | 	// 	expect(remoteTag.id).toBe(tag.id); | ||||||
| 		await Tag.addNote(remoteTag.id, n1.id); | 	// 	await Tag.addNote(remoteTag.id, n1.id); | ||||||
| 		await Tag.addNote(remoteTag.id, n2.id); | 	// 	await Tag.addNote(remoteTag.id, n2.id); | ||||||
| 		let noteIds = await Tag.noteIds(tag.id); | 	// 	let noteIds = await Tag.noteIds(tag.id); | ||||||
| 		expect(noteIds.length).toBe(2); | 	// 	expect(noteIds.length).toBe(2); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(1); | 	// 	await switchClient(1); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
| 		let remoteNoteIds = await Tag.noteIds(tag.id); | 	// 	let remoteNoteIds = await Tag.noteIds(tag.id); | ||||||
| 		expect(remoteNoteIds.length).toBe(2); | 	// 	expect(remoteNoteIds.length).toBe(2); | ||||||
| 		await Tag.removeNote(tag.id, n1.id); | 	// 	await Tag.removeNote(tag.id, n1.id); | ||||||
| 		remoteNoteIds = await Tag.noteIds(tag.id); | 	// 	remoteNoteIds = await Tag.noteIds(tag.id); | ||||||
| 		expect(remoteNoteIds.length).toBe(1); | 	// 	expect(remoteNoteIds.length).toBe(1); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(2); | 	// 	await switchClient(2); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
| 		noteIds = await Tag.noteIds(tag.id); | 	// 	noteIds = await Tag.noteIds(tag.id); | ||||||
| 		expect(noteIds.length).toBe(1); | 	// 	expect(noteIds.length).toBe(1); | ||||||
| 		expect(remoteNoteIds[0]).toBe(noteIds[0]); | 	// 	expect(remoteNoteIds[0]).toBe(noteIds[0]); | ||||||
|  |  | ||||||
| 		done(); | 	// 	done(); | ||||||
| 	}); | 	// }); | ||||||
|  |  | ||||||
| 	it('should not sync notes with conflicts', async (done) => { | 	// it('should not sync notes with conflicts', async (done) => { | ||||||
| 		let f1 = await Folder.save({ title: "folder" }); | 	// 	let f1 = await Folder.save({ title: "folder" }); | ||||||
| 		let n1 = await Note.save({ title: "mynote", parent_id: f1.id, is_conflict: 1 }); | 	// 	let n1 = await Note.save({ title: "mynote", parent_id: f1.id, is_conflict: 1 }); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(2); | 	// 	await switchClient(2); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
| 		let notes = await Note.all(); | 	// 	let notes = await Note.all(); | ||||||
| 		let folders = await Folder.all() | 	// 	let folders = await Folder.all() | ||||||
| 		expect(notes.length).toBe(0); | 	// 	expect(notes.length).toBe(0); | ||||||
| 		expect(folders.length).toBe(1); | 	// 	expect(folders.length).toBe(1); | ||||||
|  |  | ||||||
| 		done(); | 	// 	done(); | ||||||
| 	}); | 	// }); | ||||||
|  |  | ||||||
| 	it('should not try to delete on remote conflicted notes that have been deleted', async (done) => { | 	// it('should not try to delete on remote conflicted notes that have been deleted', async (done) => { | ||||||
| 		let f1 = await Folder.save({ title: "folder" }); | 	// 	let f1 = await Folder.save({ title: "folder" }); | ||||||
| 		let n1 = await Note.save({ title: "mynote", parent_id: f1.id }); | 	// 	let n1 = await Note.save({ title: "mynote", parent_id: f1.id }); | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(2); | 	// 	await switchClient(2); | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 	// 	await synchronizer().start(); | ||||||
| 		await Note.save({ id: n1.id, is_conflict: 1 }); | 	// 	await Note.save({ id: n1.id, is_conflict: 1 }); | ||||||
| 		await Note.delete(n1.id); | 	// 	await Note.delete(n1.id); | ||||||
| 		const deletedItems = await BaseItem.deletedItems(syncTargetId()); | 	// 	const deletedItems = await BaseItem.deletedItems(syncTargetId()); | ||||||
|  |  | ||||||
| 		expect(deletedItems.length).toBe(0); | 	// 	expect(deletedItems.length).toBe(0); | ||||||
|  |  | ||||||
| 		done(); | 	// 	done(); | ||||||
| 	}); | 	// }); | ||||||
|  |  | ||||||
| 	it('should not consider it is a conflict if neither the title nor body of the note have changed', async (done) => { | 	// it('should not consider it is a conflict if neither the title nor body of the note have changed', async (done) => { | ||||||
| 		// That was previously a common conflict: | 	// 	// That was previously a common conflict: | ||||||
| 		// - Client 1 mark todo as "done", and sync | 	// 	// - Client 1 mark todo as "done", and sync | ||||||
| 		// - Client 2 doesn't sync, mark todo as "done" todo. Then sync. | 	// 	// - Client 2 doesn't sync, mark todo as "done" todo. Then sync. | ||||||
| 		// In theory it is a conflict because the todo_completed dates are different | 	// 	// In theory it is a conflict because the todo_completed dates are different | ||||||
| 		// but in practice it doesn't matter, we can just take the date when the | 	// 	// but in practice it doesn't matter, we can just take the date when the | ||||||
| 		// todo was marked as "done" the first time. | 	// 	// todo was marked as "done" the first time. | ||||||
|  |  | ||||||
|  | 	// 	let folder1 = await Folder.save({ title: "folder1" }); | ||||||
|  | 	// 	let note1 = await Note.save({ title: "un", is_todo: 1, parent_id: folder1.id }); | ||||||
|  | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
|  | 	// 	await switchClient(2); | ||||||
|  |  | ||||||
|  | 	// 	await synchronizer().start(); | ||||||
|  | 	// 	let note2 = await Note.load(note1.id); | ||||||
|  | 	// 	note2.todo_completed = time.unixMs()-1; | ||||||
|  | 	// 	await Note.save(note2); | ||||||
|  | 	// 	note2 = await Note.load(note2.id); | ||||||
|  | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
|  | 	// 	await switchClient(1); | ||||||
|  |  | ||||||
|  | 	// 	let note2conf = await Note.load(note1.id); | ||||||
|  | 	// 	note2conf.todo_completed = time.unixMs(); | ||||||
|  | 	// 	await Note.save(note2conf); | ||||||
|  | 	// 	note2conf = await Note.load(note1.id); | ||||||
|  | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
|  | 	// 	let conflictedNotes = await Note.conflictedNotes(); | ||||||
|  | 	// 	expect(conflictedNotes.length).toBe(0); | ||||||
|  |  | ||||||
|  | 	// 	let notes = await Note.all(); | ||||||
|  | 	// 	expect(notes.length).toBe(1); | ||||||
|  | 	// 	expect(notes[0].id).toBe(note1.id); | ||||||
|  | 	// 	expect(notes[0].todo_completed).toBe(note2.todo_completed); | ||||||
|  |  | ||||||
|  | 	// 	done(); | ||||||
|  | 	// }); | ||||||
|  |  | ||||||
|  | 	// it('items should be downloaded again when user cancels in the middle of delta operation', async (done) => { | ||||||
|  | 	// 	let folder1 = await Folder.save({ title: "folder1" }); | ||||||
|  | 	// 	let note1 = await Note.save({ title: "un", is_todo: 1, parent_id: folder1.id }); | ||||||
|  | 	// 	await synchronizer().start(); | ||||||
|  |  | ||||||
|  | 	// 	await switchClient(2); | ||||||
|  |  | ||||||
|  | 	// 	synchronizer().debugFlags_ = ['cancelDeltaLoop2'];		 | ||||||
|  | 	// 	let context = await synchronizer().start(); | ||||||
|  | 	// 	let notes = await Note.all(); | ||||||
|  | 	// 	expect(notes.length).toBe(0); | ||||||
|  |  | ||||||
|  | 	// 	synchronizer().debugFlags_ = []; | ||||||
|  | 	// 	await synchronizer().start({ context: context }); | ||||||
|  | 	// 	notes = await Note.all(); | ||||||
|  | 	// 	expect(notes.length).toBe(1); | ||||||
|  |  | ||||||
|  | 	// 	done(); | ||||||
|  | 	// }); | ||||||
|  |  | ||||||
|  | 	it('should result in the same state if items are synchronised twice with no changes in between', async (done) => { | ||||||
| 		let folder1 = await Folder.save({ title: "folder1" }); | 		let folder1 = await Folder.save({ title: "folder1" }); | ||||||
| 		let note1 = await Note.save({ title: "un", is_todo: 1, parent_id: folder1.id }); | 		let note1 = await Note.save({ title: "un", is_todo: 1, parent_id: folder1.id }); | ||||||
| 		await synchronizer().start(); |  | ||||||
|  |  | ||||||
| 		await switchClient(2); |  | ||||||
|  |  | ||||||
| 		await synchronizer().start(); | 		await synchronizer().start(); | ||||||
| 		let note2 = await Note.load(note1.id); |  | ||||||
| 		note2.todo_completed = time.unixMs()-1; | 		await Note.save({id: note1.id, body: "changed", type_: note1.type_ }); | ||||||
| 		await Note.save(note2); | 		note1 = await Note.load(note1.id); | ||||||
| 		note2 = await Note.load(note2.id); |  | ||||||
| 		await synchronizer().start(); | 		await synchronizer().start(); | ||||||
|  |  | ||||||
| 		await switchClient(1); | 		await Note.save({id: note1.id, body: "changed 2", type_: note1.type_ }); | ||||||
|  | 		note1 = await Note.load(note1.id); | ||||||
|  |  | ||||||
| 		let note2conf = await Note.load(note1.id); |  | ||||||
| 		note2conf.todo_completed = time.unixMs(); |  | ||||||
| 		await Note.save(note2conf); |  | ||||||
| 		note2conf = await Note.load(note1.id); |  | ||||||
| 		await synchronizer().start(); | 		await synchronizer().start(); | ||||||
|  |  | ||||||
|  | 		let noteNew1 = await Note.load(note1.id); | ||||||
|  |  | ||||||
|  | 		//console.info(noteNew1); | ||||||
|  |  | ||||||
| 		let conflictedNotes = await Note.conflictedNotes(); | 		let conflictedNotes = await Note.conflictedNotes(); | ||||||
| 		expect(conflictedNotes.length).toBe(0); | 		expect(conflictedNotes.length).toBe(0); | ||||||
|  |  | ||||||
| 		let notes = await Note.all(); | 		expect(BaseModel.modelsAreSame(note1, noteNew1)).toBe(true); | ||||||
| 		expect(notes.length).toBe(1); |  | ||||||
| 		expect(notes[0].id).toBe(note1.id); |  | ||||||
| 		expect(notes[0].todo_completed).toBe(note2.todo_completed); |  | ||||||
|  |  | ||||||
| 		done(); |  | ||||||
| 	}); |  | ||||||
|  |  | ||||||
| 	it('items should be downloaded again when user cancels in the middle of delta operation', async (done) => { |  | ||||||
| 		let folder1 = await Folder.save({ title: "folder1" }); |  | ||||||
| 		let note1 = await Note.save({ title: "un", is_todo: 1, parent_id: folder1.id }); |  | ||||||
| 		await synchronizer().start(); |  | ||||||
|  |  | ||||||
| 		await switchClient(2); |  | ||||||
|  |  | ||||||
| 		synchronizer().debugFlags_ = ['cancelDeltaLoop2'];		 |  | ||||||
| 		let context = await synchronizer().start(); |  | ||||||
| 		let notes = await Note.all(); |  | ||||||
| 		expect(notes.length).toBe(0); |  | ||||||
|  |  | ||||||
| 		synchronizer().debugFlags_ = []; |  | ||||||
| 		await synchronizer().start({ context: context }); |  | ||||||
| 		notes = await Note.all(); |  | ||||||
| 		expect(notes.length).toBe(1); |  | ||||||
|  |  | ||||||
| 		done(); | 		done(); | ||||||
| 	}); | 	}); | ||||||
|   | |||||||
| @@ -201,11 +201,11 @@ class BaseModel { | |||||||
| 		let output = {}; | 		let output = {}; | ||||||
| 		let type = null; | 		let type = null; | ||||||
| 		for (let n in newModel) { | 		for (let n in newModel) { | ||||||
|  | 			if (!newModel.hasOwnProperty(n)) continue; | ||||||
| 			if (n == 'type_') { | 			if (n == 'type_') { | ||||||
| 				type = n; | 				type = newModel[n]; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (!newModel.hasOwnProperty(n)) continue; |  | ||||||
| 			if (!(n in oldModel) || newModel[n] !== oldModel[n]) { | 			if (!(n in oldModel) || newModel[n] !== oldModel[n]) { | ||||||
| 				output[n] = newModel[n]; | 				output[n] = newModel[n]; | ||||||
| 			} | 			} | ||||||
| @@ -214,6 +214,12 @@ class BaseModel { | |||||||
| 		return output; | 		return output; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	static modelsAreSame(oldModel, newModel) { | ||||||
|  | 		const diff = this.diffObjects(oldModel, newModel); | ||||||
|  | 		delete diff.type_; | ||||||
|  | 		return !Object.getOwnPropertyNames(diff).length; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	static saveQuery(o, options) { | 	static saveQuery(o, options) { | ||||||
| 		let temp = {} | 		let temp = {} | ||||||
| 		let fieldNames = this.fieldNames(); | 		let fieldNames = this.fieldNames(); | ||||||
|   | |||||||
| @@ -221,6 +221,8 @@ class Synchronizer { | |||||||
| 						} | 						} | ||||||
| 					} else { | 					} else { | ||||||
| 						if (remote.updated_time > local.sync_time) { | 						if (remote.updated_time > local.sync_time) { | ||||||
|  | 							console.info('CONFLICT', local.sync_time, remote.updated_time); | ||||||
|  |  | ||||||
| 							// Since, in this loop, we are only dealing with items that require sync, if the | 							// Since, in this loop, we are only dealing with items that require sync, if the | ||||||
| 							// remote has been modified after the sync time, it means both items have been | 							// remote has been modified after the sync time, it means both items have been | ||||||
| 							// modified and so there's a conflict. | 							// modified and so there's a conflict. | ||||||
| @@ -266,6 +268,8 @@ class Synchronizer { | |||||||
| 						// await this.api().setTimestamp(tempPath, local.updated_time); | 						// await this.api().setTimestamp(tempPath, local.updated_time); | ||||||
| 						// await this.api().move(tempPath, path); | 						// await this.api().move(tempPath, path); | ||||||
|  |  | ||||||
|  | 						console.info('Update remote: ', local); | ||||||
|  |  | ||||||
| 						await this.api().put(path, content); | 						await this.api().put(path, content); | ||||||
| 						await this.api().setTimestamp(path, local.updated_time); | 						await this.api().setTimestamp(path, local.updated_time); | ||||||
| 						await ItemClass.saveSyncTime(syncTargetId, local, time.unixMs()); | 						await ItemClass.saveSyncTime(syncTargetId, local, time.unixMs()); | ||||||
| @@ -421,6 +425,11 @@ class Synchronizer { | |||||||
| 						let ItemClass = BaseItem.itemClass(content); | 						let ItemClass = BaseItem.itemClass(content); | ||||||
| 						content = ItemClass.filter(content); | 						content = ItemClass.filter(content); | ||||||
|  |  | ||||||
|  | 						// 2017-12-03: This was added because the new user_updated_time and user_created_time properties were added | ||||||
|  | 						// to the items. However changing the database is not enough since remote items that haven't been synced yet | ||||||
|  | 						// will not have these properties and, since they are required, it would cause a problem. So this check | ||||||
|  | 						// if they are present and, if not, set them to a reasonable default. | ||||||
|  | 						// Let's leave these two lines for 6 months, by which time all the clients should have been synced. | ||||||
| 						if (!content.user_updated_time) content.user_updated_time = content.updated_time; | 						if (!content.user_updated_time) content.user_updated_time = content.updated_time; | ||||||
| 						if (!content.user_created_time) content.user_created_time = content.created_time; | 						if (!content.user_created_time) content.user_created_time = content.created_time; | ||||||
|  |  | ||||||
| @@ -448,6 +457,9 @@ class Synchronizer { | |||||||
| 							await this.api().get(remoteResourceContentPath, { path: localResourceContentPath, target: 'file' }); | 							await this.api().get(remoteResourceContentPath, { path: localResourceContentPath, target: 'file' }); | ||||||
| 						} | 						} | ||||||
|  |  | ||||||
|  | 						// if (!newContent.user_updated_time) newContent.user_updated_time = newContent.updated_time; | ||||||
|  | 						// if (!newContent.user_created_time) newContent.user_created_time = newContent.created_time; | ||||||
|  |  | ||||||
| 						await ItemClass.save(newContent, options); | 						await ItemClass.save(newContent, options); | ||||||
|  |  | ||||||
| 					} else if (action == 'deleteLocal') { | 					} else if (action == 'deleteLocal') { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user