diff --git a/chrome/content/zotero/xpcom/data/item.js b/chrome/content/zotero/xpcom/data/item.js index 5a3876c42..65994dbdc 100644 --- a/chrome/content/zotero/xpcom/data/item.js +++ b/chrome/content/zotero/xpcom/data/item.js @@ -4017,6 +4017,10 @@ Zotero.Item.prototype._eraseData = Zotero.Promise.coroutine(function* (env) { ? (yield this.ObjectsClass.getByLibraryAndKeyAsync(this.libraryID, parentItem)) : null; + if (parentItem) { + Zotero.Notifier.queue('refresh', 'item', parentItem.id); + } + // // Delete associated attachment files if (this.isAttachment()) { let linkMode = this.getAttachmentLinkMode(); diff --git a/chrome/content/zotero/xpcom/itemTreeView.js b/chrome/content/zotero/xpcom/itemTreeView.js index 1aae2a203..72813e68c 100644 --- a/chrome/content/zotero/xpcom/itemTreeView.js +++ b/chrome/content/zotero/xpcom/itemTreeView.js @@ -593,6 +593,20 @@ Zotero.ItemTreeView.prototype.notify = Zotero.Promise.coroutine(function* (actio this._cellTextCache = {}; } + // For a refresh on an item in the trash, check if the item still belongs + if (type == 'item' && collectionTreeRow.isTrash()) { + let rows = []; + for (let id of ids) { + let row = this.getRowIndexByID(id); + if (row === false) continue; + let item = Zotero.Items.get(id); + if (!item.deleted && !item.numChildren()) { + rows.push(row); + } + } + this._removeRows(rows); + } + return; } @@ -664,14 +678,7 @@ 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 (let i = rows.length - 1; i >= 0; i--) { - this._removeRow(rows[i]); - } - + this._removeRows(rows); madeChanges = true; } } diff --git a/chrome/content/zotero/xpcom/libraryTreeView.js b/chrome/content/zotero/xpcom/libraryTreeView.js index 31d757e5f..a50719328 100644 --- a/chrome/content/zotero/xpcom/libraryTreeView.js +++ b/chrome/content/zotero/xpcom/libraryTreeView.js @@ -279,6 +279,15 @@ Zotero.LibraryTreeView.prototype = { }, + _removeRows: function (rows) { + rows = Zotero.Utilities.arrayUnique(rows); + rows.sort((a, b) => a - b); + for (let i = rows.length - 1; i >= 0; i--) { + this._removeRow(rows[i]); + } + }, + + getLevel: function (row) { return this._rows[row].level; }, diff --git a/test/tests/itemTreeViewTest.js b/test/tests/itemTreeViewTest.js index 00e9b1f9a..cd80a78ea 100644 --- a/test/tests/itemTreeViewTest.js +++ b/test/tests/itemTreeViewTest.js @@ -530,6 +530,23 @@ describe("Zotero.ItemTreeView", function() { assert.isFalse(zp.itemsView.getRowIndexByID(item.id)); }); + describe("Trash", function () { + it("should remove untrashed parent item when last trashed child is deleted", function* () { + var userLibraryID = Zotero.Libraries.userLibraryID; + var item = yield createDataObject('item'); + var note = yield createDataObject( + 'item', { itemType: 'note', parentID: item.id, deleted: true } + ); + yield cv.selectByID("T" + userLibraryID); + yield waitForItemsLoad(win); + assert.isNumber(zp.itemsView.getRowIndexByID(item.id)); + var promise = waitForDialog(); + yield zp.emptyTrash(); + yield promise; + assert.isFalse(zp.itemsView.getRowIndexByID(item.id)); + }); + }); + describe("My Publications", function () { before(function* () { var libraryID = Zotero.Libraries.userLibraryID;