/)) {
+ note = Zotero.Utilities.htmlSpecialChars(note);
+ note = Zotero.Notes.notePrefix + '
');
+ notesToUpdate.push([item.id, note]);
+ }
+
+ // Don't include
wrapper when returning value
+ let startLen = note.substr(0, 36).match(/^
/)[0].length;
+ let endLen = 6; // "
".length
+ note = note.substr(startLen, note.length - startLen - endLen);
+ }
+
+ item._noteText = note ? note : '';
+ item._loaded.note = true;
+ item._clearChanged('note');
+ }.bind(this)
+ }
+ );
+
+ if (notesToUpdate.length) {
+ yield Zotero.DB.executeTransaction(function* () {
+ for (let i = 0; i < notesToUpdate.length; i++) {
+ let row = notesToUpdate[i];
+ let sql = "UPDATE itemNotes SET note=? WHERE itemID=?";
+ yield Zotero.DB.queryAsync(sql, [row[1], row[0]]);
+ }
+ }.bind(this));
+ }
+
+ // Mark notes and attachments without notes as loaded
+ sql = "SELECT itemID FROM items WHERE libraryID=?" + idSQL
+ + " AND itemTypeID IN (?, ?) AND itemID NOT IN (SELECT itemID FROM itemNotes)";
+ params = [libraryID, Zotero.ItemTypes.getID('note'), Zotero.ItemTypes.getID('attachment')];
+ yield Zotero.DB.queryAsync(
+ sql,
+ params,
+ {
+ noCache: ids.length != 1,
+ onRow: function (row) {
+ let itemID = row.getResultByIndex(0);
+ let item = this._objectCache[itemID];
+ if (!item) {
+ throw new Error("Item " + itemID + " not loaded");
+ }
+
+ item._noteText = '';
+ item._loaded.note = true;
+ item._clearChanged('note');
+ }.bind(this)
+ }
+ );
+ });
+
+
+ this._loadChildItems = Zotero.Promise.coroutine(function* (libraryID, ids, idSQL) {
+ var params = [libraryID];
+ var rows = [];
+ var onRow = function (row, setFunc) {
+ var itemID = row.getResultByIndex(0);
+
+ if (lastItemID && itemID !== lastItemID) {
+ setFunc(lastItemID, rows);
+ rows = [];
+ }
+
+ lastItemID = itemID;
+ rows.push({
+ itemID: row.getResultByIndex(1),
+ title: row.getResultByIndex(2),
+ trashed: row.getResultByIndex(3)
+ });
+ };
+
+ var sql = "SELECT parentItemID, A.itemID, value AS title, "
+ + "CASE WHEN DI.itemID IS NULL THEN 0 ELSE 1 END AS trashed "
+ + "FROM itemAttachments A "
+ + "JOIN items I ON (A.parentItemID=I.itemID) "
+ + "LEFT JOIN itemData ID ON (fieldID=110 AND A.itemID=ID.itemID) "
+ + "LEFT JOIN itemDataValues IDV USING (valueID) "
+ + "LEFT JOIN deletedItems DI USING (itemID) "
+ + "WHERE libraryID=?"
+ + (ids.length ? " AND parentItemID IN (" + ids.map(id => parseInt(id)).join(", ") + ")" : "");
+ // Since we do the sort here and cache these results, a restart will be required
+ // if this pref (off by default) is turned on, but that's OK
+ if (Zotero.Prefs.get('sortAttachmentsChronologically')) {
+ sql += " ORDER BY parentItemID, dateAdded";
+ }
+ var setAttachmentItem = function (itemID, rows) {
+ var item = this._objectCache[itemID];
+ if (!item) {
+ throw new Error("Item " + itemID + " not loaded");
+ }
+
+ item._attachments = {
+ rows,
+ chronologicalWithTrashed: null,
+ chronologicalWithoutTrashed: null,
+ alphabeticalWithTrashed: null,
+ alphabeticalWithoutTrashed: null
+ };
+ }.bind(this);
+ var lastItemID = null;
+ yield Zotero.DB.queryAsync(
+ sql,
+ params,
+ {
+ noCache: ids.length != 1,
+ onRow: function (row) {
+ onRow(row, setAttachmentItem);
+ }
+ }
+ );
+ if (lastItemID) {
+ setAttachmentItem(lastItemID, rows);
+ }
+
+ //
+ // Notes
+ //
+ sql = "SELECT parentItemID, N.itemID, title, "
+ + "CASE WHEN DI.itemID IS NULL THEN 0 ELSE 1 END AS trashed "
+ + "FROM itemNotes N "
+ + "JOIN items I ON (N.parentItemID=I.itemID) "
+ + "LEFT JOIN deletedItems DI USING (itemID) "
+ + "WHERE libraryID=?"
+ + (ids.length ? " AND parentItemID IN (" + ids.map(id => parseInt(id)).join(", ") + ")" : "");
+ if (Zotero.Prefs.get('sortNotesChronologically')) {
+ sql += " ORDER BY parentItemID, dateAdded";
+ }
+ var setNoteItem = function (itemID, rows) {
+ var item = this._objectCache[itemID];
+ if (!item) {
+ throw new Error("Item " + itemID + " not loaded");
+ }
+
+ item._notes = {
+ rows,
+ rowsEmbedded: null,
+ chronologicalWithTrashed: null,
+ chronologicalWithoutTrashed: null,
+ alphabeticalWithTrashed: null,
+ alphabeticalWithoutTrashed: null,
+ numWithTrashed: null,
+ numWithoutTrashed: null,
+ numWithTrashedWithEmbedded: null,
+ numWithoutTrashedWithoutEmbedded: null
+ };
+ }.bind(this);
+ lastItemID = null;
+ rows = [];
+ yield Zotero.DB.queryAsync(
+ sql,
+ params,
+ {
+ noCache: ids.length != 1,
+ onRow: function (row) {
+ onRow(row, setNoteItem);
+ }
+ }
+ );
+ if (lastItemID) {
+ setNoteItem(lastItemID, rows);
+ }
+
+ // Mark all top-level items as having child items loaded
+ sql = "SELECT itemID FROM items I WHERE libraryID=?" + idSQL + " AND itemID NOT IN "
+ + "(SELECT itemID FROM itemAttachments UNION SELECT itemID FROM itemNotes)";
+ yield Zotero.DB.queryAsync(
+ sql,
+ params,
+ {
+ noCache: ids.length != 1,
+ onRow: function (row) {
+ var itemID = row.getResultByIndex(0);
+ var item = this._objectCache[itemID];
+ if (!item) {
+ throw new Error("Item " + itemID + " not loaded");
+ }
+ item._loaded.childItems = true;
+ item._clearChanged('childItems');
+ }.bind(this)
+ }
+ );
+ });
+
+
+ this._loadTags = Zotero.Promise.coroutine(function* (libraryID, ids, idSQL) {
+ var sql = "SELECT itemID, name, type FROM items "
+ + "LEFT JOIN itemTags USING (itemID) "
+ + "LEFT JOIN tags USING (tagID) WHERE libraryID=?" + idSQL;
+ var params = [libraryID];
+
+ var lastItemID;
+ var rows = [];
+ var setRows = function (itemID, rows) {
+ var item = this._objectCache[itemID];
+ if (!item) {
+ throw new Error("Item " + itemID + " not found");
+ }
+
+ item._tags = [];
+ for (let i = 0; i < rows.length; i++) {
+ let row = rows[i];
+ item._tags.push(Zotero.Tags.cleanData(row));
+ }
+
+ item._loaded.tags = true;
+ item._clearChanged('tags');
+ }.bind(this);
+
+ yield Zotero.DB.queryAsync(
+ sql,
+ params,
+ {
+ noCache: ids.length != 1,
+ onRow: function (row) {
+ let itemID = row.getResultByIndex(0);
+
+ if (lastItemID && itemID !== lastItemID) {
+ setRows(lastItemID, rows);
+ rows = [];
+ }
+
+ lastItemID = itemID;
+
+ // Item has no tags
+ let tag = row.getResultByIndex(1);
+ if (tag === null) {
+ return;
+ }
+
+ rows.push({
+ tag: tag,
+ type: row.getResultByIndex(2)
+ });
+ }.bind(this)
+ }
+ );
+ if (lastItemID) {
+ setRows(lastItemID, rows);
+ }
+ });
+
+
+ this._loadCollections = Zotero.Promise.coroutine(function* (libraryID, ids, idSQL) {
+ var sql = "SELECT itemID, collectionID FROM items "
+ + "LEFT JOIN collectionItems USING (itemID) "
+ + "WHERE libraryID=?" + idSQL;
+ var params = [libraryID];
+
+ var lastItemID;
+ var rows = [];
+ var setRows = function (itemID, rows) {
+ var item = this._objectCache[itemID];
+ if (!item) {
+ throw new Error("Item " + itemID + " not found");
+ }
+
+ item._collections = rows;
+ item._loaded.collections = true;
+ item._clearChanged('collections');
+ }.bind(this);
+
+ yield Zotero.DB.queryAsync(
+ sql,
+ params,
+ {
+ noCache: ids.length != 1,
+ onRow: function (row) {
+ let itemID = row.getResultByIndex(0);
+
+ if (lastItemID && itemID !== lastItemID) {
+ setRows(lastItemID, rows);
+ rows = [];
+ }
+
+ lastItemID = itemID;
+ let collectionID = row.getResultByIndex(1);
+ // No collections
+ if (collectionID === null) {
+ return;
+ }
+ rows.push(collectionID);
+ }.bind(this)
+ }
+ );
+ if (lastItemID) {
+ setRows(lastItemID, rows);
+ }
});
@@ -409,17 +725,11 @@ Zotero.Items = function() {
var otherItemIDs = [];
var itemURI = Zotero.URI.getItemURI(item);
- yield item.loadTags();
- yield item.loadRelations();
var replPred = Zotero.Relations.replacedItemPredicate;
var toSave = {};
toSave[this.id];
for each(var otherItem in otherItems) {
- yield otherItem.loadChildItems();
- yield otherItem.loadCollections();
- yield otherItem.loadTags();
- yield otherItem.loadRelations();
let otherItemURI = Zotero.URI.getItemURI(otherItem);
// Move child items to master
@@ -632,16 +942,6 @@ Zotero.Items = function() {
});
- this._postLoad = function (libraryID, ids) {
- if (!ids) {
- if (!this._cachedFields[libraryID]) {
- this._cachedFields[libraryID] = [];
- }
- this._cachedFields[libraryID] = this.primaryFields.concat();
- }
- }
-
-
/*
* Generate SQL to retrieve firstCreator field
*
diff --git a/chrome/content/zotero/xpcom/db.js b/chrome/content/zotero/xpcom/db.js
index 5b0ab097c..4eff4f016 100644
--- a/chrome/content/zotero/xpcom/db.js
+++ b/chrome/content/zotero/xpcom/db.js
@@ -630,7 +630,13 @@ Zotero.DBConnection.prototype.queryAsync = Zotero.Promise.coroutine(function* (s
}
}
}
- let rows = yield conn.executeCached(sql, params, onRow);
+ let rows;
+ if (options && options.noCache) {
+ rows = yield conn.execute(sql, params, onRow);
+ }
+ else {
+ rows = yield conn.executeCached(sql, params, onRow);
+ }
// Parse out the SQL command being used
let op = sql.match(/^[^a-z]*[^ ]+/i);
if (op) {
diff --git a/chrome/content/zotero/xpcom/itemTreeView.js b/chrome/content/zotero/xpcom/itemTreeView.js
index 920776eb1..ace81c4fe 100644
--- a/chrome/content/zotero/xpcom/itemTreeView.js
+++ b/chrome/content/zotero/xpcom/itemTreeView.js
@@ -82,7 +82,7 @@ Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (tree
if (this._treebox) {
if (this._needsSort) {
- yield this.sort();
+ this.sort();
}
return;
}
@@ -133,11 +133,11 @@ Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (tree
if (self._treebox.view.selection.count > 1) {
switch (event.keyCode) {
case 39:
- self.expandSelectedRows().done();
+ self.expandSelectedRows();
break;
case 37:
- self.collapseSelectedRows().done();
+ self.collapseSelectedRows();
break;
}
@@ -148,7 +148,7 @@ Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (tree
var key = String.fromCharCode(event.which);
if (key == '+' && !(event.ctrlKey || event.altKey || event.metaKey)) {
- self.expandAllRows().done();
+ self.expandAllRows();
event.preventDefault();
return;
}
@@ -230,8 +230,8 @@ Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (tree
// handleKeyPress() in zoteroPane.js.
tree._handleEnter = function () {};
- yield this.sort();
- yield this.expandMatchParents();
+ this.sort();
+ this.expandMatchParents();
if (this._ownerDocument.defaultView.ZoteroPane_Local) {
this._ownerDocument.defaultView.ZoteroPane_Local.clearItemsPaneMessage();
@@ -266,13 +266,10 @@ Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (tree
*/
Zotero.ItemTreeView.prototype.refresh = Zotero.serial(Zotero.Promise.coroutine(function* () {
Zotero.debug('Refreshing items list for ' + this.id);
- //if(!Zotero.ItemTreeView._haveCachedFields) yield Zotero.Promise.resolve();
- var cacheFields = ['title', 'date'];
-
- // Cache the visible fields so they don't load individually
+ // DEBUG: necessary?
try {
- var visibleFields = this.getVisibleFields();
+ this._treebox.columns.count
}
// If treebox isn't ready, skip refresh
catch (e) {
@@ -286,33 +283,6 @@ Zotero.ItemTreeView.prototype.refresh = Zotero.serial(Zotero.Promise.coroutine(f
});
try {
- for (let i=0; i
=0; i--) {
- yield this.toggleOpenState(rowsToOpen[i], true);
+ this.toggleOpenState(rowsToOpen[i], true);
}
this._refreshItemRowMap();
if (unsuppress) {
//this._treebox.endUpdateBatch();
this.selection.selectEventsSuppressed = false;
}
-});
+}
-Zotero.ItemTreeView.prototype.expandMatchParents = Zotero.Promise.coroutine(function* () {
+Zotero.ItemTreeView.prototype.expandMatchParents = function () {
// Expand parents of child matches
if (!this._searchMode) {
return;
@@ -2001,7 +1952,7 @@ Zotero.ItemTreeView.prototype.expandMatchParents = Zotero.Promise.coroutine(func
for (var i=0; i} - File hash, null if never synced, if false if
- * file doesn't exist
- */
- getSyncedHash: Zotero.Promise.coroutine(function* (itemID) {
- var sql = "SELECT storageHash FROM itemAttachments WHERE itemID=?";
- var hash = yield Zotero.DB.valueQueryAsync(sql, itemID);
- if (hash === false) {
- throw new Error("Item " + itemID + " not found");
- }
- return hash;
- }),
-
-
- /**
- * @param {Integer} itemID
- * @param {String} hash File hash
- * @param {Boolean} [updateItem=FALSE] - Mark attachment item as unsynced
- */
- setSyncedHash: Zotero.Promise.coroutine(function* (itemID, hash, updateItem) {
- if (hash !== null && hash.length != 32) {
- throw new Error("Invalid file hash '" + hash + "'");
- }
-
- Zotero.DB.requireTransaction();
-
- var sql = "UPDATE itemAttachments SET storageHash=? WHERE itemID=?";
- yield Zotero.DB.queryAsync(sql, [hash, itemID]);
-
- if (updateItem) {
- let item = yield Zotero.Items.getAsync(itemID);
- yield item.updateSynced(false);
- }
+ sql = "UPDATE itemAttachments SET syncState=? WHERE itemID IN (" + sql + ")";
+ yield Zotero.DB.queryAsync(sql, [this.SYNC_STATE_TO_UPLOAD].concat(params));
}),
@@ -678,11 +577,10 @@ Zotero.Sync.Storage.Local = {
// Set the file mtime to the time from the server
yield OS.File.setDates(path, null, new Date(parseInt(mtime)));
- yield Zotero.DB.executeTransaction(function* () {
- yield this.setSyncedHash(item.id, md5);
- yield this.setSyncState(item.id, this.SYNC_STATE_IN_SYNC);
- yield this.setSyncedModificationTime(item.id, mtime);
- }.bind(this));
+ item.attachmentSyncState = this.SYNC_STATE_IN_SYNC;
+ item.attachmentSyncedModificationTime = mtime;
+ item.attachmentSyncedHash = md5;
+ yield item.saveTx();
return new Zotero.Sync.Storage.Result({
localChanges: true
@@ -1040,7 +938,7 @@ Zotero.Sync.Storage.Local = {
for (let localItem of localItems) {
// Use the mtime for the dateModified field, since that's all that's shown in the
// CR window at the moment
- let localItemJSON = yield localItem.toJSON();
+ let localItemJSON = localItem.toJSON();
localItemJSON.dateModified = Zotero.Date.dateToISO(
new Date(yield localItem.attachmentModificationTime)
);
@@ -1101,8 +999,9 @@ Zotero.Sync.Storage.Local = {
else {
syncState = this.SYNC_STATE_FORCE_DOWNLOAD;
}
- let itemID = Zotero.Items.getIDFromLibraryAndKey(libraryID, conflict.left.key);
- yield Zotero.Sync.Storage.Local.setSyncState(itemID, syncState);
+ let item = Zotero.Items.getByLibraryAndKey(libraryID, conflict.left.key);
+ item.attachmentSyncState = syncState;
+ yield item.save({ skipAll: true });
}
}.bind(this));
return true;
diff --git a/chrome/content/zotero/xpcom/storage/webdav.js b/chrome/content/zotero/xpcom/storage/webdav.js
index 13f64bc86..49c133c6b 100644
--- a/chrome/content/zotero/xpcom/storage/webdav.js
+++ b/chrome/content/zotero/xpcom/storage/webdav.js
@@ -288,15 +288,14 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = {
Zotero.debug("File mod time matches remote file -- skipping download of "
+ item.libraryKey);
- yield Zotero.DB.executeTransaction(function* () {
- var syncState = Zotero.Sync.Storage.Local.getSyncState(item.id);
- // DEBUG: Necessary to update item?
- var updateItem = syncState != 1;
- yield Zotero.Sync.Storage.Local.setSyncedModificationTime(
- item.id, metadata.mtime, updateItem
- );
- yield Zotero.Sync.Storage.Local.setSyncState(item.id, "in_sync");
- });
+ var updateItem = item.attachmentSyncState != 1
+ item.attachmentSyncedModificationTime = metadata.mtime;
+ item.attachmentSyncState = "in_sync";
+ yield item.saveTx({ skipAll: true });
+ // DEBUG: Necessary?
+ if (updateItem) {
+ yield item.updateSynced(false);
+ }
return new Zotero.Sync.Storage.Result({
localChanges: true, // ?
@@ -416,7 +415,7 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = {
}
// Check if file already exists on WebDAV server
- if ((yield Zotero.Sync.Storage.Local.getSyncState(item.id))
+ if (item.attachmentSyncState
!= Zotero.Sync.Storage.Local.SYNC_STATE_FORCE_UPLOAD) {
if (metadata.mtime) {
// Local file time
@@ -438,15 +437,14 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = {
// If WebDAV server already has file, update synced properties
if (!changed) {
- yield Zotero.DB.executeTransaction(function* () {
- yield Zotero.Sync.Storage.Local.setSyncedModificationTime(
- item.id, fmtime, true
- );
- if (hash) {
- yield Zotero.Sync.Storage.Local.setSyncedHash(item.id, hash);
- }
- yield Zotero.Sync.Storage.Local.setSyncState(item.id, "in_sync");
- });
+ item.attachmentSyncedModificationTime = fmtime;
+ if (hash) {
+ item.attachmentSyncedHash = hash;
+ }
+ item.attachmentSyncState = "in_sync";
+ yield item.saveTx({ skipAll: true });
+ // skipAll doesn't mark as unsynced, so do that separately
+ yield item.updateSynced(false);
return new Zotero.Sync.Storage.Result;
}
}
@@ -460,9 +458,9 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = {
// API would ever be updated with the correct values, so we can't just wait for
// the API to change.) If a conflict is found, we flag the item as in conflict
// and require another file sync, which will trigger conflict resolution.
- let smtime = yield Zotero.Sync.Storage.Local.getSyncedModificationTime(item.id);
+ let smtime = item.attachmentSyncedModificationTime;
if (smtime != mtime) {
- let shash = yield Zotero.Sync.Storage.Local.getSyncedHash(item.id);
+ let shash = item.attachmentSyncedHash;
if (shash && metadata.md5 && shash == metadata.md5) {
Zotero.debug("Last synced mod time for item " + item.libraryKey
+ " doesn't match time on storage server but hash does -- ignoring");
@@ -472,12 +470,13 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = {
Zotero.logError("Conflict -- last synced file mod time for item "
+ item.libraryKey + " does not match time on storage server"
+ " (" + smtime + " != " + mtime + ")");
- yield Zotero.DB.executeTransaction(function* () {
- // Conflict resolution uses the synced mtime as the remote value, so set
- // that to the WebDAV value, since that's the one in conflict.
- yield Zotero.Sync.Storage.Local.setSyncedModificationTime(item.id, mtime);
- yield Zotero.Sync.Storage.Local.setSyncState(item.id, "in_conflict");
- });
+
+ // Conflict resolution uses the synced mtime as the remote value, so set
+ // that to the WebDAV value, since that's the one in conflict.
+ item.attachmentSyncedModificationTime = mtime;
+ item.attachmentSyncState = "in_conflict";
+ yield item.saveTx({ skipAll: true });
+
return new Zotero.Sync.Storage.Result({
fileSyncRequired: true
});
@@ -1191,7 +1190,10 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = {
throw new Error(Zotero.Sync.Storage.Mode.WebDAV.defaultError);
}
- return { mtime, md5 };
+ return {
+ mtime: parseInt(mtime),
+ md5
+ };
}),
@@ -1243,11 +1245,12 @@ Zotero.Sync.Storage.Mode.WebDAV.prototype = {
// Update .prop file on WebDAV server
yield this._setStorageFileMetadata(item);
- yield Zotero.DB.executeTransaction(function* () {
- yield Zotero.Sync.Storage.Local.setSyncState(item.id, "in_sync");
- yield Zotero.Sync.Storage.Local.setSyncedModificationTime(item.id, params.mtime, true);
- yield Zotero.Sync.Storage.Local.setSyncedHash(item.id, params.md5);
- });
+ item.attachmentSyncedModificationTime = params.mtime;
+ item.attachmentSyncedHash = params.md5;
+ item.attachmentSyncState = "in_sync";
+ yield item.saveTx({ skipAll: true });
+ // skipAll doesn't mark as unsynced, so do that separately
+ yield item.updateSynced(false);
try {
yield OS.File.remove(
diff --git a/chrome/content/zotero/xpcom/storage/zfs.js b/chrome/content/zotero/xpcom/storage/zfs.js
index 43ee3744b..e8f2b4bfa 100644
--- a/chrome/content/zotero/xpcom/storage/zfs.js
+++ b/chrome/content/zotero/xpcom/storage/zfs.js
@@ -131,15 +131,13 @@ Zotero.Sync.Storage.Mode.ZFS.prototype = {
}
// Update local metadata and stop request, skipping file download
- yield Zotero.DB.executeTransaction(function* () {
- if (updateHash) {
- yield Zotero.Sync.Storage.Local.setSyncedHash(item.id, requestData.md5);
- }
- yield Zotero.Sync.Storage.Local.setSyncedModificationTime(
- item.id, requestData.mtime
- );
- yield Zotero.Sync.Storage.Local.setSyncState(item.id, "in_sync");
- });
+ item.attachmentSyncedModificationTime = requestData.mtime;
+ if (updateHash) {
+ item.attachmentSyncedHash = requestData.md5;
+ }
+ item.attachmentSyncState = "in_sync";
+ yield item.saveTx({ skipAll: true });
+
return false;
}),
onProgress: function (a, b, c) {
@@ -261,7 +259,7 @@ Zotero.Sync.Storage.Mode.ZFS.prototype = {
var sql = "SELECT value FROM settings WHERE setting=? AND key=?";
var values = yield Zotero.DB.columnQueryAsync(sql, ['storage', 'zfsPurge']);
- if (!values) {
+ if (!values.length) {
return false;
}
@@ -353,7 +351,7 @@ Zotero.Sync.Storage.Mode.ZFS.prototype = {
var headers = {
"Content-Type": "application/x-www-form-urlencoded"
};
- var storedHash = yield Zotero.Sync.Storage.Local.getSyncedHash(item.id);
+ var storedHash = item.attachmentSyncedHash;
//var storedModTime = yield Zotero.Sync.Storage.getSyncedModificationTime(item.id);
if (storedHash) {
headers["If-Match"] = storedHash;
@@ -538,17 +536,17 @@ Zotero.Sync.Storage.Mode.ZFS.prototype = {
Zotero.debug(fileHash);
if (json.data.md5 == fileHash) {
- yield Zotero.DB.executeTransaction(function* () {
- yield Zotero.Sync.Storage.Local.setSyncedModificationTime(
- item.id, fileModTime
- );
- yield Zotero.Sync.Storage.Local.setSyncedHash(item.id, fileHash);
- yield Zotero.Sync.Storage.Local.setSyncState(item.id, "in_sync");
- });
+ item.attachmentSyncedModificationTime = fileModTime;
+ item.attachmentSyncedHash = fileHash;
+ item.attachmentSyncState = "in_sync";
+ yield item.saveTx({ skipAll: true });
+
return new Zotero.Sync.Storage.Result;
}
- yield Zotero.Sync.Storage.Local.setSyncState(item.id, "in_conflict");
+ item.attachmentSyncState = "in_conflict";
+ yield item.saveTx({ skipAll: true });
+
return new Zotero.Sync.Storage.Result({
fileSyncRequired: true
});
@@ -767,11 +765,12 @@ Zotero.Sync.Storage.Mode.ZFS.prototype = {
_updateItemFileInfo: Zotero.Promise.coroutine(function* (item, params) {
// Mark as in-sync
yield Zotero.DB.executeTransaction(function* () {
- yield Zotero.Sync.Storage.Local.setSyncState(item.id, "in_sync");
+ // Store file mod time and hash
+ item.attachmentSyncedModificationTime = params.mtime;
+ item.attachmentSyncedHash = params.md5;
+ item.attachmentSyncState = "in_sync";
+ yield item.save({ skipAll: true });
- // Store file mod time and hash
- yield Zotero.Sync.Storage.Local.setSyncedModificationTime(item.id, params.mtime);
- yield Zotero.Sync.Storage.Local.setSyncedHash(item.id, params.md5);
// Update sync cache with new file metadata and version from server
var json = yield Zotero.Sync.Data.Local.getCacheObject(
'item', item.libraryID, item.key, item.version
@@ -933,7 +932,7 @@ Zotero.Sync.Storage.Mode.ZFS.prototype = {
}
// Check for conflict
- if ((yield Zotero.Sync.Storage.Local.getSyncState(item.id))
+ if (item.attachmentSyncState
!= Zotero.Sync.Storage.Local.SYNC_STATE_FORCE_UPLOAD) {
if (info) {
// Local file time
diff --git a/chrome/content/zotero/xpcom/sync/syncEngine.js b/chrome/content/zotero/xpcom/sync/syncEngine.js
index 23b1242ae..10d65e5e6 100644
--- a/chrome/content/zotero/xpcom/sync/syncEngine.js
+++ b/chrome/content/zotero/xpcom/sync/syncEngine.js
@@ -316,7 +316,7 @@ Zotero.Sync.Data.Engine.prototype._startDownload = Zotero.Promise.coroutine(func
// Conflict resolution
else if (objectType == 'item') {
conflicts.push({
- left: yield obj.toJSON(),
+ left: obj.toJSON(),
right: {
deleted: true
}
diff --git a/chrome/content/zotero/xpcom/sync/syncLocal.js b/chrome/content/zotero/xpcom/sync/syncLocal.js
index 997f026c7..a2df6ce3c 100644
--- a/chrome/content/zotero/xpcom/sync/syncLocal.js
+++ b/chrome/content/zotero/xpcom/sync/syncLocal.js
@@ -512,7 +512,7 @@ Zotero.Sync.Data.Local = {
objectType, obj.libraryID, obj.key, obj.version
);
- let jsonDataLocal = yield obj.toJSON();
+ let jsonDataLocal = obj.toJSON();
// For items, check if mtime or file hash changed in metadata,
// which would indicate that a remote storage sync took place and
@@ -780,7 +780,8 @@ Zotero.Sync.Data.Local = {
markToDownload = true;
}
if (markToDownload) {
- yield Zotero.Sync.Storage.Local.setSyncState(item.id, "to_download");
+ item.attachmentSyncState = "to_download";
+ yield item.save({ skipAll: true });
}
}),
@@ -870,7 +871,6 @@ Zotero.Sync.Data.Local = {
_saveObjectFromJSON: Zotero.Promise.coroutine(function* (obj, json, options) {
try {
- yield obj.loadAllData();
obj.fromJSON(json);
if (!options.saveAsChanged) {
obj.version = json.version;
diff --git a/chrome/content/zotero/xpcom/timeline.js b/chrome/content/zotero/xpcom/timeline.js
index ed473c9a0..fdf27afb3 100644
--- a/chrome/content/zotero/xpcom/timeline.js
+++ b/chrome/content/zotero/xpcom/timeline.js
@@ -31,7 +31,6 @@ Zotero.Timeline = {
yield '\n';
for (let i=0; i items.add(item));
}
@@ -720,7 +718,7 @@ Zotero.Translate.ItemGetter.prototype = {
* Converts an attachment to array format and copies it to the export folder if desired
*/
"_attachmentToArray":Zotero.Promise.coroutine(function* (attachment) {
- var attachmentArray = yield Zotero.Utilities.Internal.itemToExportFormat(attachment, this.legacy);
+ var attachmentArray = Zotero.Utilities.Internal.itemToExportFormat(attachment, this.legacy);
var linkMode = attachment.attachmentLinkMode;
if(linkMode != Zotero.Attachments.LINK_MODE_LINKED_URL) {
var attachFile = attachment.getFile();
@@ -864,13 +862,13 @@ Zotero.Translate.ItemGetter.prototype = {
var returnItemArray = yield this._attachmentToArray(returnItem);
if(returnItemArray) return returnItemArray;
} else {
- var returnItemArray = yield Zotero.Utilities.Internal.itemToExportFormat(returnItem, this.legacy);
+ var returnItemArray = Zotero.Utilities.Internal.itemToExportFormat(returnItem, this.legacy);
// get attachments, although only urls will be passed if exportFileData is off
returnItemArray.attachments = [];
var attachments = returnItem.getAttachments();
for each(var attachmentID in attachments) {
- var attachment = yield Zotero.Items.getAsync(attachmentID);
+ var attachment = Zotero.Items.get(attachmentID);
var attachmentInfo = yield this._attachmentToArray(attachment);
if(attachmentInfo) {
diff --git a/chrome/content/zotero/xpcom/utilities.js b/chrome/content/zotero/xpcom/utilities.js
index 001099194..d623696f2 100644
--- a/chrome/content/zotero/xpcom/utilities.js
+++ b/chrome/content/zotero/xpcom/utilities.js
@@ -1591,8 +1591,9 @@ Zotero.Utilities = {
*/
"itemToCSLJSON":function(zoteroItem) {
if (zoteroItem instanceof Zotero.Item) {
- return Zotero.Utilities.Internal.itemToExportFormat(zoteroItem).
- then(Zotero.Utilities.itemToCSLJSON);
+ return this.itemToCSLJSON(
+ Zotero.Utilities.Internal.itemToExportFormat(zoteroItem)
+ );
}
var cslType = CSL_TYPE_MAPPINGS[zoteroItem.itemType];
diff --git a/chrome/content/zotero/xpcom/utilities_internal.js b/chrome/content/zotero/xpcom/utilities_internal.js
index 5aca23268..e5d6e21dc 100644
--- a/chrome/content/zotero/xpcom/utilities_internal.js
+++ b/chrome/content/zotero/xpcom/utilities_internal.js
@@ -610,44 +610,7 @@ Zotero.Utilities.Internal = {
* @param {Boolean} legacy Add mappings for legacy (pre-4.0.27) translators
* @return {Promise