commit 43762248a4f55fc65791fca6e3034352c44d8d13
parent 87fa51849f7387cef4d1a9caf1f64d1acf2e9328
Author: Dan Stillman <dstillman@zotero.org>
Date: Sun, 24 May 2015 22:57:46 -0400
Fix trash emptying, and do it in batches of 50
Diffstat:
5 files changed, 71 insertions(+), 36 deletions(-)
diff --git a/chrome/content/zotero/xpcom/data/items.js b/chrome/content/zotero/xpcom/data/items.js
@@ -102,9 +102,8 @@ Zotero.Items = function() {
/**
* Return items marked as deleted
*
- * @param {Integer} libraryID
- * @param {Boolean} asIDs Return itemIDs instead of
- * Zotero.Item objects
+ * @param {Integer} libraryID - Library to search
+ * @param {Boolean} [asIDs] - Return itemIDs instead of Zotero.Item objects
* @return {Zotero.Item[]|Integer[]}
*/
this.getDeleted = Zotero.Promise.coroutine(function* (libraryID, asIDs, days) {
@@ -113,7 +112,6 @@ Zotero.Items = function() {
if (days) {
sql += " AND dateDeleted<=DATE('NOW', '-" + parseInt(days) + " DAYS')";
}
-
var ids = yield Zotero.DB.columnQueryAsync(sql, [libraryID]);
if (!ids.length) {
return [];
@@ -500,24 +498,27 @@ Zotero.Items = function() {
/**
- * @param {Integer} days Only delete items deleted more than this many days ago
+ * @param {Integer} libraryID - Library to delete from
+ * @param {Integer} [days] - Only delete items deleted more than this many days ago
+ * @param {Integer} [limit]
*/
this.emptyTrash = Zotero.Promise.coroutine(function* (libraryID, days, limit) {
+ if (!libraryID) {
+ throw new Error("Library ID not provided");
+ }
+
var t = new Date();
var deletedIDs = [];
- yield Zotero.DB.executeTransaction(function* () {
- deletedIDs = yield this.getDeleted(libraryID, true, days);
- if (deletedIDs.length) {
- if (limit) {
- deletedIDs = deletedIDs.slice(0, limit - 1)
- }
- yield this.erase(deletedIDs);
+ deletedIDs = yield this.getDeleted(libraryID, true, days);
+ if (deletedIDs.length) {
+ yield Zotero.Utilities.Internal.forEachChunkAsync(deletedIDs, 50, function* (chunk) {
+ yield this.erase(chunk);
Zotero.Notifier.trigger('refresh', 'trash', libraryID);
- }
- }.bind(this));
-
+ }.bind(this));
+ }
+
if (deletedIDs.length) {
Zotero.debug("Emptied " + deletedIDs.length + " item(s) from trash in " + (new Date() - t) + " ms");
}
@@ -547,7 +548,7 @@ Zotero.Items = function() {
// TODO: increase number after dealing with slow
// tag.getLinkedItems() call during deletes
var num = 10;
- this.emptyTrash(null, days, num)
+ this.emptyTrash(Zotero.Libraries.userLibraryID, days, num)
.then(deleted => {
if (!deleted) {
this._emptyTrashTimer = null;
diff --git a/chrome/content/zotero/xpcom/itemTreeView.js b/chrome/content/zotero/xpcom/itemTreeView.js
@@ -603,15 +603,12 @@ Zotero.ItemTreeView.prototype.notify = Zotero.Promise.coroutine(function* (actio
}
if (rows.length > 0) {
+ // Child items might have been added more than once
+ rows = Zotero.Utilities.arrayUnique(rows);
rows.sort(function(a,b) { return a-b });
- for(var i=0, len=rows.length; i<len; i++)
- {
- var row = rows[i];
- if(row != null)
- {
- this._removeRow(row-i);
- }
+ for (let i = rows.length - 1; i >= 0; i--) {
+ this._removeRow(rows[i]);
}
madeChanges = true;
diff --git a/test/content/support.js b/test/content/support.js
@@ -76,6 +76,11 @@ function waitForWindow(uri) {
return deferred.promise;
}
+var selectLibrary = Zotero.Promise.coroutine(function* (win) {
+ yield win.ZoteroPane.collectionsView.selectLibrary(Zotero.Libraries.userLibraryID);
+ yield waitForItemsLoad(win);
+});
+
var waitForItemsLoad = function (win, collectionRowToSelect) {
var resolve;
var promise = new Zotero.Promise(() => resolve = arguments[0]);
@@ -151,7 +156,7 @@ function waitForCallback(cb, interval, timeout) {
function createUnsavedDataObject(objectType, params) {
params = params || {};
if (objectType == 'item') {
- var param = 'book';
+ var param = params.itemType || 'book';
}
var obj = new Zotero[Zotero.Utilities.capitalize(objectType)](param);
switch (objectType) {
diff --git a/test/tests/collectionTreeViewTest.js b/test/tests/collectionTreeViewTest.js
@@ -3,21 +3,14 @@
describe("Zotero.CollectionTreeView", function() {
var win, collectionsView;
- // Select library
- // TODO: Add a selectCollection() function and select a collection instead
- var resetSelection = Zotero.Promise.coroutine(function* () {
- yield collectionsView.selectLibrary(Zotero.Libraries.userLibraryID);
- yield waitForItemsLoad(win);
- assert.equal(collectionsView.getSelectedLibraryID(), Zotero.Libraries.userLibraryID);
- });
-
// Load Zotero pane and select library
before(function* () {
win = yield loadZoteroPane();
collectionsView = win.ZoteroPane.collectionsView;
});
beforeEach(function () {
- return resetSelection();
+ // TODO: Add a selectCollection() function and select a collection instead?
+ return selectLibrary(win);
})
after(function () {
win.close();
@@ -108,7 +101,7 @@ describe("Zotero.CollectionTreeView", function() {
collection.name = "No select on modify";
var id = yield collection.saveTx();
- yield resetSelection();
+ yield selectLibrary(win);
collection.name = "No select on modify 2";
yield collection.saveTx();
diff --git a/test/tests/itemsTest.js b/test/tests/itemsTest.js
@@ -1,3 +1,42 @@
-describe("Zotero.Items", function() {
-
+describe("Zotero.Items", function () {
+ var win, collectionsView;
+
+ before(function* () {
+ win = yield loadZoteroPane();
+ collectionsView = win.ZoteroPane.collectionsView;
+ })
+ beforeEach(function () {
+ return selectLibrary(win);
+ })
+ after(function () {
+ win.close();
+ })
+
+ describe("#emptyTrash()", function () {
+ it("should delete items in the trash", function* () {
+ var item1 = createUnsavedDataObject('item');
+ item1.setField('title', 'a');
+ item1.deleted = true;
+ var id1 = yield item1.saveTx();
+
+ var item2 = createUnsavedDataObject('item');
+ item2.setField('title', 'b');
+ item2.deleted = true;
+ var id2 = yield item2.saveTx();
+
+ var item3 = createUnsavedDataObject('item', { itemType: 'attachment', parentID: id2 });
+ item3.attachmentLinkMode = Zotero.Attachments.LINK_MODE_IMPORTED_URL;
+ item3.deleted = true;
+ var id3 = yield item3.saveTx();
+
+ yield collectionsView.selectTrash(Zotero.Libraries.userLibraryID);
+
+ yield Zotero.Items.emptyTrash(Zotero.Libraries.userLibraryID);
+
+ assert.isFalse(yield Zotero.Items.getAsync(id1));
+ assert.isFalse(yield Zotero.Items.getAsync(id2));
+ assert.isFalse(yield Zotero.Items.getAsync(id3));
+ assert.equal(win.ZoteroPane.itemsView.rowCount, 0);
+ })
+ })
});