From 3c785e2a916e2e68cf7b6fccc8ead3f379c83b2d Mon Sep 17 00:00:00 2001 From: Tom Najdek Date: Wed, 13 Mar 2024 11:20:41 +0100 Subject: [PATCH] Show icon in Attachments column immediately. Resolve #3760 This introduces a small performance penalty for the initial load of the items as we run DB queries to check for the best attachment. Disk access is delayed until after the list is displayed and the row is scrolled into view. --- chrome/content/zotero/itemTree.jsx | 10 +++++++++- chrome/content/zotero/xpcom/data/item.js | 15 +++++++++------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/chrome/content/zotero/itemTree.jsx b/chrome/content/zotero/itemTree.jsx index 5028afb2ac..d034299141 100644 --- a/chrome/content/zotero/itemTree.jsx +++ b/chrome/content/zotero/itemTree.jsx @@ -229,6 +229,14 @@ var ItemTree = class ItemTree extends LibraryTree { : newSearchItems.filter(item => !!item.parentItemID).map(item => item.parentItemID) ); this._searchParentIDs = newSearchParentIDs; + + let t1 = Date.now(); + await Promise.all(newSearchItems + .filter(i => this._canGetBestAttachmentState(i)) + .map(i => i.getBestAttachmentState(false)) + ); + Zotero.debug(`Got best attachment states in ${Date.now() - t1} ms`); + newSearchItems = new Set(newSearchItems); var newCellTextCache = {}; @@ -2672,7 +2680,7 @@ var ItemTree = class ItemTree extends LibraryTree { ariaLabel = Zotero.getString('pane.item.attachments.has'); } - if (!exists) { + if (exists === false) { icon.classList.add('icon-missing-file'); } } diff --git a/chrome/content/zotero/xpcom/data/item.js b/chrome/content/zotero/xpcom/data/item.js index 90d4992d42..88a23477d2 100644 --- a/chrome/content/zotero/xpcom/data/item.js +++ b/chrome/content/zotero/xpcom/data/item.js @@ -3774,15 +3774,17 @@ Zotero.Item.prototype.getBestAttachments = Zotero.Promise.coroutine(function* () }); - /** * Return state of best attachment (or this item if it's a standalone attachment) * - * @return {Promise} - Promise for object with string 'type' ('none'|'pdf'|'snapshot'|'epub'|'image'|'video'|'other') - * and boolean 'exists' + * @param {Boolean} [checkIfExists=true] - Whether to check if the attachment file exists + * @return {Promise} - Promise for object with the following properties: + * - 'type': string, indicating the type of the best attachment ('none', 'pdf', 'snapshot', 'epub', 'image', 'video', 'other') + * - 'key': string, the key of the best attachment + * - 'exists': boolean, indicating whether the attachment file exists. `exists` is null if `checkIfExists` is false and no cached value is available */ -Zotero.Item.prototype.getBestAttachmentState = async function () { - if (this._bestAttachmentState !== null && this._bestAttachmentState.type) { +Zotero.Item.prototype.getBestAttachmentState = async function (checkIfExists = true) { + if (this._bestAttachmentState !== null && this._bestAttachmentState.type && (!checkIfExists || ('exists' in this._bestAttachmentState && this._bestAttachmentState.exists !== null))) { return this._bestAttachmentState; } var item = this.isAttachment() && this.isTopLevelItem() @@ -3812,7 +3814,8 @@ Zotero.Item.prototype.getBestAttachmentState = async function () { else { type = 'other'; } - var exists = await item.fileExists(); + + var exists = checkIfExists ? await item.fileExists() : null; let key = item.key; return this._bestAttachmentState = { type, exists, key }; };