From 4d8a9ed753e2a985d0fe252d08c91696e7c9261a Mon Sep 17 00:00:00 2001 From: Martynas Bagdonas Date: Wed, 26 Aug 2020 18:08:53 +0300 Subject: [PATCH] Replace all note local URIs at the first sync time --- chrome/content/zotero/xpcom/data/notes.js | 107 ++++++++++-------- chrome/content/zotero/xpcom/editorInstance.js | 26 +++-- chrome/content/zotero/xpcom/sync/syncLocal.js | 1 + 3 files changed, 77 insertions(+), 57 deletions(-) diff --git a/chrome/content/zotero/xpcom/data/notes.js b/chrome/content/zotero/xpcom/data/notes.js index 993ad60a3e..2b67959054 100644 --- a/chrome/content/zotero/xpcom/data/notes.js +++ b/chrome/content/zotero/xpcom/data/notes.js @@ -25,10 +25,7 @@ Zotero.Notes = new function() { - this.noteToTitle = noteToTitle; - // Currently active editor instances - this.editorInstances = []; - + this._editorInstances = []; this.__defineGetter__("MAX_TITLE_LENGTH", function() { return 120; }); this.__defineGetter__("defaultNote", function () { return '
'; }); @@ -43,7 +40,7 @@ Zotero.Notes = new function() { /** * Return first line (or first MAX_LENGTH characters) of note content **/ - function noteToTitle(text) { + this.noteToTitle = function(text) { var origText = text; text = text.trim(); text = Zotero.Utilities.unescapeHTML(text); @@ -67,49 +64,69 @@ Zotero.Notes = new function() { t = t.substring(0, ln); } return t; - } + }; - /** - * Replaces local URIs for citation and highlight nodes - * - * Must be called just before the initial sync, - * if called later the item version will be increased, - * which might be incovenient for the future (better) notes sync - * - * @param item Note item - * @returns {Promise} - */ - this.updateURIs = async (item) => { - let html = item.note; - let num = 0; - // "uri":"http://zotero.org/users/local/(.+?)/items/(.+?)" - let regex = new RegExp(/%22uri%22%3A%22http%3A%2F%2Fzotero.org%2Fusers%2Flocal%2F(.+?)%2Fitems%2F(.+?)%22/g); - html = html.replace(regex, function (m, g1, g2) { - num++; - let libraryID = Zotero.URI.getURILibrary('http://zotero.org/users/local/' + g1); - let libraryURI = Zotero.URI.getLibraryURI(libraryID); - return encodeURIComponent('"uri":"' + libraryURI + '/items/' + g2 + '"'); + this.registerEditorInstance = function(instance) { + this._editorInstances.push(instance); + }; + + this.unregisterEditorInstance = async function(instance) { + // Make sure the editor instance is not unregistered while + // Zotero.Notes.updateUser is in progress, otherwise the + // instance might not get the`disableSaving` flag set + await Zotero.DB.executeTransaction(async () => { + let index = this._editorInstances.indexOf(instance); + if (index >= 0) { + this._editorInstances.splice(index, 1); + } }); - if (num) { - item.setNote(html); - // Cut off saving for each editor instance for this item, - // to make sure none of the editor instances will concurrently - // overwrite our changes - this.editorInstances.forEach(editorInstance => { - if (editorInstance.item.id === item.id) { - editorInstance.disableSaving = true; - } - }); - // Although, theoretically, a new editor instance with the old data can still - // be created while asynchronous `item.saveTx` is in progress, but really unlikely + }; - // Observer notification will automatically recreate the affected editor instances - await item.saveTx(); - Zotero.debug(`Updated URIs for item ${item.id}: ${num}`); + /** + * Replace local URIs for citations and highlights + * in all notes. Cut-off note saving for the opened + * notes and then trigger notification to refresh + * + * @param {Number} fromUserID + * @param {Number} toUserID + * @returns {Promise} + */ + this.updateUser = async function (fromUserID, toUserID) { + if (!fromUserID) { + fromUserID = 'local%2F' + Zotero.Users.getLocalUserKey(); } - } -} + if (!toUserID) { + throw new Error('Invalid target userID ' + toUserID); + } + Zotero.DB.requireTransaction(); -if (typeof process === 'object' && process + '' === '[object process]'){ - module.exports = Zotero.Notes; + // `"uri":"http://zotero.org/users/${fromUserID}/items/"` + let from = `%22uri%22%3A%22http%3A%2F%2Fzotero.org%2Fusers%2F${fromUserID}%2Fitems%2F`; + // `"uri":"http://zotero.org/users/${toUserId}/items/"` + let to = `%22uri%22%3A%22http%3A%2F%2Fzotero.org%2Fusers%2F${toUserID}%2Fitems%2F`; + let sql = `UPDATE itemNotes SET note=REPLACE(note, '${from}', '${to}')`; + await Zotero.DB.queryAsync(sql); + + // Disable saving for each editor instance to make sure none + // of the instances can overwrite our changes + this._editorInstances.forEach(x => x.disableSaving = true); + + let idsToRefresh = []; + let objectsClass = Zotero.DataObjectUtilities.getObjectsClassForObjectType('item'); + let loadedObjects = objectsClass.getLoaded(); + for (let object of loadedObjects) { + if (object.isNote()) { + idsToRefresh.push(object.id); + await object.reload(['note'], true); + } + } + + Zotero.DB.addCurrentCallback('commit', async () => { + await Zotero.Notifier.trigger('refresh', 'item', idsToRefresh); + }); + }; +}; + +if (typeof process === 'object' && process + '' === '[object process]') { + module.exports = Zotero.Notes; } diff --git a/chrome/content/zotero/xpcom/editorInstance.js b/chrome/content/zotero/xpcom/editorInstance.js index 3f0d965fac..01950e12b6 100644 --- a/chrome/content/zotero/xpcom/editorInstance.js +++ b/chrome/content/zotero/xpcom/editorInstance.js @@ -347,19 +347,21 @@ class EditorInstance { } // Update note if (this._item) { - let changed = this._item.setNote(html, schemaVersion); - if (changed && this._saveOnEdit) { - // Make sure saving is not disabled - if (this._disableSaving) { - return; - } - await this._item.saveTx({ - notifierData: { - noteEditorID: this.instanceID, - state + await Zotero.DB.executeTransaction(async () => { + let changed = this._item.setNote(html, schemaVersion); + if (changed && this._saveOnEdit) { + // Make sure saving is not disabled + if (this._disableSaving) { + return; } - }); - } + await this._item.save({ + notifierData: { + noteEditorID: this.instanceID, + state + } + }); + } + }); } // Create a new note else { diff --git a/chrome/content/zotero/xpcom/sync/syncLocal.js b/chrome/content/zotero/xpcom/sync/syncLocal.js index ccc3aa419a..3d6283c7fb 100644 --- a/chrome/content/zotero/xpcom/sync/syncLocal.js +++ b/chrome/content/zotero/xpcom/sync/syncLocal.js @@ -175,6 +175,7 @@ Zotero.Sync.Data.Local = { // Replace local user key with libraryID, in case duplicates were merged before the // first sync yield Zotero.Relations.updateUser(null, userID); + yield Zotero.Notes.updateUser(null, userID); } });