1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-01-02 12:47:41 +02:00

Merge branch 'dev' of github.com:laurent22/joplin into dev

This commit is contained in:
Laurent Cozic 2021-06-12 09:57:54 +02:00
commit 3b6a66a016
7 changed files with 61 additions and 6 deletions

View File

@ -343,7 +343,7 @@ export default class JoplinDatabase extends Database {
// must be set in the synchronizer too.
// Note: v16 and v17 don't do anything. They were used to debug an issue.
const existingDatabaseVersions = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38];
const existingDatabaseVersions = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39];
let currentVersionIndex = existingDatabaseVersions.indexOf(fromVersion);
@ -888,6 +888,10 @@ export default class JoplinDatabase extends Database {
GROUP BY tags.id`);
}
if (targetVersion == 39) {
queries.push('ALTER TABLE `notes` ADD COLUMN conflict_original_id TEXT NOT NULL DEFAULT ""');
}
const updateVersionQuery = { sql: 'UPDATE version SET version = ?', params: [targetVersion] };
queries.push(updateVersionQuery);

View File

@ -610,10 +610,7 @@ export default class Synchronizer {
// ------------------------------------------------------------------------------
if (mustHandleConflict) {
const conflictedNote = Object.assign({}, local);
delete conflictedNote.id;
conflictedNote.is_conflict = 1;
await Note.save(conflictedNote, { autoTimestamp: false, changeSource: ItemChange.SOURCE_SYNC });
await Note.createConflictNote(local, ItemChange.SOURCE_SYNC);
}
} else if (action == 'resourceConflict') {
// ------------------------------------------------------------------------------

View File

@ -6,6 +6,7 @@ import { sortedIds, createNTestNotes, setupDatabaseAndSynchronizer, switchClient
import Folder from './Folder';
import Note from './Note';
import Tag from './Tag';
import ItemChange from './ItemChange';
const ArrayUtils = require('../ArrayUtils.js');
async function allItems() {
@ -344,4 +345,44 @@ describe('models_Note', function() {
expect(sortedNotes3[4].id).toBe(note2.id);
}));
it('should create a conflict note', async () => {
const folder = await Folder.save({ title: 'Source Folder' });
const origNote = await Note.save({ title: 'note', parent_id: folder.id });
const conflictedNote = await Note.createConflictNote(origNote, ItemChange.SOURCE_SYNC);
expect(conflictedNote.is_conflict).toBe(1);
expect(conflictedNote.conflict_original_id).toBe(origNote.id);
expect(conflictedNote.parent_id).toBe(folder.id);
});
it('should copy conflicted note to target folder and cancel conflict', (async () => {
const srcfolder = await Folder.save({ title: 'Source Folder' });
const targetfolder = await Folder.save({ title: 'Target Folder' });
const note1 = await Note.save({ title: 'note', parent_id: srcfolder.id });
const conflictedNote = await Note.createConflictNote(note1, ItemChange.SOURCE_SYNC);
const note2 = await Note.copyToFolder(conflictedNote.id, targetfolder.id);
expect(note2.id === conflictedNote.id).toBe(false);
expect(note2.title).toBe(conflictedNote.title);
expect(note2.is_conflict).toBe(0);
expect(note2.conflict_original_id).toBe('');
expect(note2.parent_id).toBe(targetfolder.id);
}));
it('should move conflicted note to target folder and cancel conflict', (async () => {
const srcFolder = await Folder.save({ title: 'Source Folder' });
const targetFolder = await Folder.save({ title: 'Target Folder' });
const note1 = await Note.save({ title: 'note', parent_id: srcFolder.id });
const conflictedNote = await Note.createConflictNote(note1, ItemChange.SOURCE_SYNC);
const movedNote = await Note.moveToFolder(conflictedNote.id, targetFolder.id);
expect(movedNote.parent_id).toBe(targetFolder.id);
expect(movedNote.is_conflict).toBe(0);
expect(movedNote.conflict_original_id).toBe('');
}));
});

View File

@ -523,6 +523,7 @@ export default class Note extends BaseItem {
changes: {
parent_id: folderId,
is_conflict: 0, // Also reset the conflict flag in case we're moving the note out of the conflict folder
conflict_original_id: '', // Reset parent id as well.
},
});
}
@ -537,6 +538,7 @@ export default class Note extends BaseItem {
id: noteId,
parent_id: folderId,
is_conflict: 0,
conflict_original_id: '',
updated_time: time.unixMs(),
};
@ -911,4 +913,12 @@ export default class Note extends BaseItem {
return new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' });
}
static async createConflictNote(sourceNote: NoteEntity, changeSource: number): Promise<NoteEntity> {
const conflictNote = Object.assign({}, sourceNote);
delete conflictNote.id;
conflictNote.is_conflict = 1;
conflictNote.conflict_original_id = sourceNote.id;
return await Note.save(conflictNote, { autoTimestamp: false, changeSource: changeSource });
}
}

View File

@ -98,6 +98,7 @@ export interface NoteEntity {
"created_time"?: number
"updated_time"?: number
"is_conflict"?: number
"conflict_original_id"?: string
"latitude"?: number
"longitude"?: number
"altitude"?: number

View File

@ -44,9 +44,10 @@ describe('Synchronizer.conflicts', function() {
// the conflicted and original note must be the same in every way, to make sure no data has been lost.
const conflictedNote = conflictedNotes[0];
expect(conflictedNote.id == note2conf.id).toBe(false);
expect(conflictedNote.conflict_original_id).toBe(note2conf.id);
for (const n in conflictedNote) {
if (!conflictedNote.hasOwnProperty(n)) continue;
if (n == 'id' || n == 'is_conflict') continue;
if (n == 'id' || n == 'is_conflict' || n == 'conflict_original_id') continue;
expect(conflictedNote[n]).toBe(note2conf[n]);
}

View File

@ -477,6 +477,7 @@ encryption_applied: 0
markup_language: 1
is_shared: 1
share_id: ${note.share_id || ''}
conflict_original_id:
type_: 1`;
}