diff --git a/chrome/content/zotero/elements/contextPane.js b/chrome/content/zotero/elements/contextPane.js index 75df9412d3..6b8ee474d8 100644 --- a/chrome/content/zotero/elements/contextPane.js +++ b/chrome/content/zotero/elements/contextPane.js @@ -171,7 +171,7 @@ ZoteroContextPane.showLoadingMessage(false); this._sidenav.hidden = true; } - else if (Zotero_Tabs.selectedType == 'reader') { + else if (Zotero_Tabs.selectedType.includes('reader')) { let reader = Zotero.Reader.getByTabID(Zotero_Tabs.selectedID); this._handleReaderReady(reader); @@ -195,9 +195,6 @@ if (!reader) { return; } - ZoteroContextPane.showLoadingMessage(true); - await reader._initPromise; - ZoteroContextPane.showLoadingMessage(false); // Focus reader pages view if context pane note editor is not selected if (Zotero_Tabs.selectedID == reader.tabID && !Zotero_Tabs.isTabsMenuVisible() @@ -305,9 +302,8 @@ itemDetails.sidenav = this._sidenav; if (previousPinnedPane) itemDetails.pinnedPane = previousPinnedPane; - // `unloaded` tabs are never selected and shouldn't be rendered on creation. - // Use `includes` here for forward compatibility. - if (!tabType.includes("unloaded")) { + // Make sure that the context pane of the selected tab is rendered + if (tabID == Zotero_Tabs.selectedID) { this._selectItemContext(tabID); } } diff --git a/chrome/content/zotero/tabs.js b/chrome/content/zotero/tabs.js index c15465ee75..8d6b2b1a73 100644 --- a/chrome/content/zotero/tabs.js +++ b/chrome/content/zotero/tabs.js @@ -108,7 +108,9 @@ var Zotero_Tabs = new function () { icon = ; } catch (e) { - // item might not yet be loaded, we will get the icon on the next update + // item might not yet be loaded, we will get the right icon on the next update + // but until then use a default placeholder + icon = ; } } @@ -199,25 +201,13 @@ var Zotero_Tabs = new function () { } else if (tab.type === 'reader') { if (Zotero.Items.exists(tab.data.itemID)) { - if (tab.selected) { - Zotero.Reader.open(tab.data.itemID, - null, - { - title: tab.title, - tabIndex: i, - openInBackground: !tab.selected, - secondViewState: tab.data.secondViewState - } - ); - } - else { - this.add({ - type: 'reader-unloaded', - title: tab.title, - index: i, - data: tab.data - }); - } + this.add({ + type: 'reader-unloaded', + title: tab.title, + index: i, + data: tab.data, + select: tab.selected + }); } } } @@ -462,16 +452,22 @@ var Zotero_Tabs = new function () { selectedTab.lastFocusedElement = document.activeElement; } if (tab.type === 'reader-unloaded') { - this.close(tab.id); - Zotero.Reader.open(tab.data.itemID, options && options.location, { - tabID: tab.id, - title: tab.title, - tabIndex, - allowDuplicate: true, - secondViewState: tab.data.secondViewState, - preventJumpback: true - }); - return; + // Make sure the loading message is displayed first. + // Then, open reader and hide the loading message once it has loaded. + ZoteroContextPane.showLoadingMessage(true); + let hideMessageWhenReaderLoaded = async () => { + let reader = await Zotero.Reader.open(tab.data.itemID, options && options.location, { + tabID: tab.id, + title: tab.title, + tabIndex, + allowDuplicate: true, + secondViewState: tab.data.secondViewState, + preventJumpback: true + }); + await reader._initPromise; + ZoteroContextPane.showLoadingMessage(false); + }; + hideMessageWhenReaderLoaded(); } this._prevSelectedID = reopening ? this._selectedID : null; this._selectedID = id; @@ -532,6 +528,13 @@ var Zotero_Tabs = new function () { data: tab.data }); }; + + // Mark a tab as loaded + this.markAsLoaded = function (id) { + let { tab } = this._getTab(id); + if (!tab) return; + tab.type = "reader"; + }; this.unloadUnusedTabs = function () { for (let tab of this._tabs) { diff --git a/chrome/content/zotero/xpcom/reader.js b/chrome/content/zotero/xpcom/reader.js index 9156502bd7..2581396ffb 100644 --- a/chrome/content/zotero/xpcom/reader.js +++ b/chrome/content/zotero/xpcom/reader.js @@ -520,7 +520,6 @@ class ReaderInstance { }, this._iframeWindow, { cloneFunctions: true })); this._resolveInitPromise(); - // Set title once again, because `ReaderWindow` isn't loaded the first time this.updateTitle(); @@ -1017,19 +1016,28 @@ class ReaderTab extends ReaderInstance { this._onToggleSidebarCallback = options.onToggleSidebar; this._onChangeSidebarWidthCallback = options.onChangeSidebarWidth; this._window = Services.wm.getMostRecentWindow('navigator:browser'); - let { id, container } = this._window.Zotero_Tabs.add({ - id: options.tabID, - type: 'reader', - title: options.title || '', - index: options.index, - data: { - itemID: this._item.id - }, - select: !options.background, - preventJumpback: options.preventJumpback - }); - this.tabID = id; - this._tabContainer = container; + let existingTabID = this._window.Zotero_Tabs.getTabIDByItemID(this._item.id); + // If an unloaded tab for this item already exists, load the reader in it. + // Otherwise, create a new tab + if (existingTabID) { + this.tabID = existingTabID; + this._tabContainer = this._window.document.getElementById(existingTabID); + } + else { + let { id, container } = this._window.Zotero_Tabs.add({ + id: options.tabID, + type: 'reader', + title: options.title || '', + index: options.index, + data: { + itemID: this._item.id + }, + select: !options.background, + preventJumpback: options.preventJumpback + }); + this.tabID = id; + this._tabContainer = container; + } this._iframe = this._window.document.createXULElement('browser'); this._iframe.setAttribute('class', 'reader'); @@ -1737,6 +1745,9 @@ class Reader { async open(itemID, location, { title, tabIndex, tabID, openInBackground, openInWindow, allowDuplicate, secondViewState, preventJumpback } = {}) { let { libraryID } = Zotero.Items.getLibraryAndKeyFromID(itemID); let library = Zotero.Libraries.get(libraryID); + let win = Zotero.getMainWindow(); + // Change tab's type from "unloaded-reader" to "reader" + win.Zotero_Tabs.markAsLoaded(tabID); await library.waitForDataLoad('item'); let item = Zotero.Items.get(itemID); @@ -1747,7 +1758,6 @@ class Reader { this._loadSidebarState(); this.triggerAnnotationsImportCheck(itemID); let reader; - let win = Zotero.getMainWindow(); // If duplicating is not allowed, and no reader instance is loaded for itemID, // try to find an unloaded tab and select it. Zotero.Reader.open will then be called again if (!allowDuplicate && !this._readers.find(r => r.itemID === itemID)) {