tabs startup loading optimization (#4174)
- if an unloaded tab is being opened, do not close the tab and have reader re-open a fresh tab. Instead, keep the tab as is, have reader use the tab as a container and just change the tab's type. It should fix a glitch on windows when if you click on a tab during initial loading, it will disappear until reader re-adds it. A few tweaks to allow unloaded tabs be generally "selectable". Fixes: #4149 - during startup loading, select the yet-unloaded tab right away. That way, a tab is almost immediately selected, instead of being stuck on the library tab until the reader is ready. - if the items are not loaded yet, use a placeholder icon for tabs. Fixes: #4150 - special handling for reader loading message during initial load. When an unloaded tab is selected, the loading message needs to be displayed but, since there is no reader yet, we add it in Zotero_Tabs.select and try to remove by the reader when it's loaded.
This commit is contained in:
parent
d188857e06
commit
3f45def928
3 changed files with 61 additions and 52 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,7 +108,9 @@ var Zotero_Tabs = new function () {
|
|||
icon = <CSSItemTypeIcon itemType={item.getItemTypeIconName(true)} className="tab-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 = <CSSItemTypeIcon className="tab-icon" />;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,28 +201,16 @@ 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
|
||||
data: tab.data,
|
||||
select: tab.selected
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Unset the previously selected tab id, because it was set when restoring tabs
|
||||
this._prevSelectedID = null;
|
||||
};
|
||||
|
@ -462,8 +452,11 @@ 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, {
|
||||
// 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,
|
||||
|
@ -471,7 +464,10 @@ var Zotero_Tabs = new function () {
|
|||
secondViewState: tab.data.secondViewState,
|
||||
preventJumpback: true
|
||||
});
|
||||
return;
|
||||
await reader._initPromise;
|
||||
ZoteroContextPane.showLoadingMessage(false);
|
||||
};
|
||||
hideMessageWhenReaderLoaded();
|
||||
}
|
||||
this._prevSelectedID = reopening ? this._selectedID : null;
|
||||
this._selectedID = id;
|
||||
|
@ -533,6 +529,13 @@ var Zotero_Tabs = new function () {
|
|||
});
|
||||
};
|
||||
|
||||
// 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) {
|
||||
if (Zotero.Date.getUnixTimestamp() - tab.timeUnselected > UNLOAD_UNUSED_AFTER) {
|
||||
|
|
|
@ -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,6 +1016,14 @@ class ReaderTab extends ReaderInstance {
|
|||
this._onToggleSidebarCallback = options.onToggleSidebar;
|
||||
this._onChangeSidebarWidthCallback = options.onChangeSidebarWidth;
|
||||
this._window = Services.wm.getMostRecentWindow('navigator:browser');
|
||||
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',
|
||||
|
@ -1030,6 +1037,7 @@ class ReaderTab extends ReaderInstance {
|
|||
});
|
||||
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)) {
|
||||
|
|
Loading…
Reference in a new issue