diff --git a/chrome/content/zotero/itemTree.jsx b/chrome/content/zotero/itemTree.jsx index 1fa3d861b8..9864245778 100644 --- a/chrome/content/zotero/itemTree.jsx +++ b/chrome/content/zotero/itemTree.jsx @@ -1726,7 +1726,12 @@ var ItemTree = class ItemTree extends LibraryTree { if (collectionTreeRow.isTrash()) { await Zotero.Items.erase(ids); } - else if (collectionTreeRow.isLibrary(true) || force) { + else if (collectionTreeRow.isLibrary(true) + || collectionTreeRow.isSearch() + || collectionTreeRow.isUnfiled() + || collectionTreeRow.isRetracted() + || collectionTreeRow.isDuplicates() + || force) { await Zotero.Items.trashTx(ids); } else if (collectionTreeRow.isCollection()) { diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js index 1e8241cfc4..2094bb0309 100644 --- a/chrome/content/zotero/zoteroPane.js +++ b/chrome/content/zotero/zoteroPane.js @@ -1750,7 +1750,11 @@ var ZoteroPane = new function() }; var prompt = force ? toTrash : toRemoveFromPublications; } - else if (collectionTreeRow.isLibrary(true)) { + else if (collectionTreeRow.isLibrary(true) + || collectionTreeRow.isSearch() + || collectionTreeRow.isUnfiled() + || collectionTreeRow.isRetracted() + || collectionTreeRow.isDuplicates()) { // In library, don't prompt if meta key was pressed var prompt = (force && !fromMenu) ? false : toTrash; } @@ -1763,15 +1767,6 @@ var ZoteroPane = new function() var prompt = force ? toTrash : toRemove; } - else if (collectionTreeRow.isSearch() - || collectionTreeRow.isUnfiled() - || collectionTreeRow.isRetracted() - || collectionTreeRow.isDuplicates()) { - if (!force) { - return; - } - var prompt = toTrash; - } // Do nothing in trash view if any non-deleted items are selected else if (collectionTreeRow.isTrash()) { for (const index of this.itemsView.selection.selected) { diff --git a/test/tests/zoteroPaneTest.js b/test/tests/zoteroPaneTest.js index 4e45631591..d66974ffbf 100644 --- a/test/tests/zoteroPaneTest.js +++ b/test/tests/zoteroPaneTest.js @@ -443,6 +443,8 @@ describe("ZoteroPane", function() { describe("#deleteSelectedItems()", function () { + const DELETE_KEY_CODE = 46; + it("should remove an item from My Publications", function* () { var item = createUnsavedDataObject('item'); item.inPublications = true; @@ -464,7 +466,18 @@ describe("ZoteroPane", function() { var modifyPromise = waitForItemEvent('modify'); var event = doc.createEvent("KeyboardEvent"); - event.initKeyEvent("keypress", true, true, window, false, false, false, false, 46, 0); + event.initKeyEvent( + "keypress", + true, + true, + window, + false, + false, + false, + false, + DELETE_KEY_CODE, + 0 + ); tree.dispatchEvent(event); yield promise; yield modifyPromise; @@ -473,7 +486,7 @@ describe("ZoteroPane", function() { assert.isFalse(item.deleted); }); - it("should move an item to trash from My Publications", function* () { + it("should move My Publications item to trash with prompt for modified Delete", function* () { var item = createUnsavedDataObject('item'); item.inPublications = true; yield item.saveTx(); @@ -503,7 +516,7 @@ describe("ZoteroPane", function() { false, !Zotero.isMac, // shift Zotero.isMac, // meta - 46, + DELETE_KEY_CODE, 0 ); tree.dispatchEvent(event); @@ -513,6 +526,80 @@ describe("ZoteroPane", function() { assert.isTrue(item.inPublications); assert.isTrue(item.deleted); }); + + it("should move saved search item to trash with prompt for unmodified Delete", async function () { + var search = await createDataObject('search'); + var title = [...Object.values(search.conditions)] + .filter(x => x.condition == 'title' && x.operator == 'contains')[0].value; + var item = await createDataObject('item', { title }); + + await waitForItemsLoad(win); + var iv = zp.itemsView; + + var selected = iv.selectItem(item.id); + assert.ok(selected); + + var tree = doc.getElementById(iv.id); + tree.focus(); + + await Zotero.Promise.delay(1); + + var promise = waitForDialog(); + var modifyPromise = waitForItemEvent('modify'); + + var event = new KeyboardEvent( + "keypress", + { + key: 'Delete', + code: 'Delete', + keyCode: DELETE_KEY_CODE, + bubbles: true, + cancelable: true + } + ); + tree.dispatchEvent(event); + await promise; + await modifyPromise; + + assert.isTrue(item.deleted); + }); + + it("should move saved search trash without prompt for modified Delete", async function () { + var search = await createDataObject('search'); + var title = [...Object.values(search.conditions)] + .filter(x => x.condition == 'title' && x.operator == 'contains')[0].value; + var item = await createDataObject('item', { title }); + + await waitForItemsLoad(win); + var iv = zp.itemsView; + + var selected = iv.selectItem(item.id); + assert.ok(selected); + + var tree = doc.getElementById(iv.id); + tree.focus(); + + await Zotero.Promise.delay(1); + + var modifyPromise = waitForItemEvent('modify'); + + var event = new KeyboardEvent( + "keypress", + { + key: 'Delete', + code: 'Delete', + metaKey: Zotero.isMac, + shiftKey: !Zotero.isMac, + keyCode: DELETE_KEY_CODE, + bubbles: true, + cancelable: true + } + ); + tree.dispatchEvent(event); + await modifyPromise; + + assert.isTrue(item.deleted); + }); }); describe("#deleteSelectedCollection()", function () {