diff --git a/chrome/content/zotero/elements/itemDetails.js b/chrome/content/zotero/elements/itemDetails.js index 7a9ecb795e..5f178e3a61 100644 --- a/chrome/content/zotero/elements/itemDetails.js +++ b/chrome/content/zotero/elements/itemDetails.js @@ -178,6 +178,18 @@ this.forceUpdateSideNav(); } + get skipRender() { + return this._skipRender; + } + + set skipRender(val) { + this._skipRender = val; + let panes = this.getPanes(); + for (let pane of [this._header, ...panes]) { + pane.skipRender = val; + } + } + static get observedAttributes() { return ['pinnedPane']; } @@ -198,12 +210,18 @@ }); this._initIntersectionObserver(); - this._unregisterID = Zotero.Notifier.registerObserver(this, ['item', 'itempane'], 'ItemDetails'); + this._unregisterID = Zotero.Notifier.registerObserver( + this, ['item', 'itempane', 'tab'], 'ItemDetails'); this._disableScrollHandler = false; this._pinnedPaneMinScrollHeight = 0; this._lastUpdateCustomSection = 0; + + // If true, will render on tab select + this._pendingRender = false; + // If true, will skip render + this._skipRender = false; } destroy() { @@ -220,6 +238,13 @@ if (!this.initialized || !this.item) { return; } + + if (this.skipRender) { + this._pendingRender = true; + return; + } + this._pendingRender = false; + let item = this.item; Zotero.debug('Viewing item'); this._isRendering = true; @@ -317,6 +342,9 @@ elem.registerSectionButton(buttonOptions); } } + if (this._pendingRender) { + elem.pendingRender = true; + } this._paneParent.append(elem); elem.setL10nID(header.l10nID); elem.setL10nArgs(header.l10nArgs); @@ -333,13 +361,17 @@ this._header.renderCustomHead(callback); } - notify = async (action, type, _ids, _extraData) => { + notify = async (action, type, ids, _extraData) => { if (action == 'refresh' && this.item) { if (type == 'itempane') { this.renderCustomSections(); } await this.render(); } + + if (action == 'select' && type == 'tab') { + this._handleTabSelect(ids); + } }; getPane(id) { @@ -596,6 +628,17 @@ }); } }; + + _handleTabSelect(tabIDs) { + if (!this.tabID || typeof Zotero_Tabs === 'undefined') { + return; + } + let isTabSelected = tabIDs.includes(this.tabID); + this.skipRender = !isTabSelected; + if (isTabSelected && this._pendingRender) { + this.render(); + } + } } customElements.define("item-details", ItemDetails); diff --git a/chrome/content/zotero/elements/itemPaneSection.js b/chrome/content/zotero/elements/itemPaneSection.js index 11b8d01762..40c6c905c7 100644 --- a/chrome/content/zotero/elements/itemPaneSection.js +++ b/chrome/content/zotero/elements/itemPaneSection.js @@ -59,6 +59,13 @@ class ItemPaneSectionElementBase extends XULElementBase { this._tabType = tabType; this.setAttribute('tabType', tabType); } + + _syncRenderPending = false; + + _asyncRenderPending = false; + + /** Controlled by parent element */ + skipRender = false; get open() { return this._section?.open || false; @@ -105,11 +112,25 @@ class ItemPaneSectionElementBase extends XULElementBase { */ _isAlreadyRendered(type = "sync") { let key = `_${type}RenderItemID`; - let cachedFlag = this[key]; - if (cachedFlag && this.item?.id == cachedFlag) { + let pendingKey = `_${type}RenderPending`; + + let renderFlag = this[key]; + let pendingFlag = this[pendingKey]; + + let isRendered = renderFlag && this.item?.id == renderFlag; + if (this.skipRender) { + if (!isRendered) { + this[pendingKey] = true; + } + // Skip render + return true; + } + + if (!pendingFlag && renderFlag && this.item?.id == renderFlag) { return true; } this[key] = this.item.id; + this[pendingKey] = false; return false; } @@ -120,7 +141,11 @@ class ItemPaneSectionElementBase extends XULElementBase { } async _forceRenderAll() { - if (this.hidden) return; + if (this.hidden || this.skipRender) { + this._syncRenderPending = true; + this._asyncRenderPending = true; + return; + } this._resetRenderedFlags(); if (this.render) this.render(); if (this.asyncRender) await this.asyncRender();