From 9f70bca12c9e3ad245dabe4df307795d44bc3c3e Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 21 Mar 2020 14:37:03 +0100 Subject: [PATCH] Re-factor `PDFViewerApplication.load` such that `{PDFViewer, PDFThumbnailViewer}.setDocument` happens slightly earlier The `BaseViewer.setDocument` method in particular is necessary for rendering to start when the viewer loads, hence you obviously want that to happen as soon as possible and without any unnecessary delays. Unfortunately *some* API calls need to be done before that, note existing comments, however the `ViewHistory` initialization (and subsequent fetching of data) in particular can be moved slightly without any adverse effects. As part of testing I've used logging with `performance.now()` inserted in various parts of this code, and there's *obviously* no discernible changes between `master` and this patch for e.g. rendering starting in the viewer. *Note:* The vast majority of this patch is simple indentation changes, which were forced by Prettier (and done automatically with `gulp lint --fix`). --- web/app.js | 192 +++++++++++++++++++++++++---------------------------- 1 file changed, 91 insertions(+), 101 deletions(-) diff --git a/web/app.js b/web/app.js index 7cc34a192..030ed6733 100644 --- a/web/app.js +++ b/web/app.js @@ -1040,8 +1040,6 @@ const PDFViewerApplication = { this.toolbar.setPagesCount(pdfDocument.numPages, false); this.secondaryToolbar.setPagesCount(pdfDocument.numPages); - const store = (this.store = new ViewHistory(pdfDocument.fingerprint)); - let baseDocumentUrl; if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) { baseDocumentUrl = null; @@ -1060,123 +1058,115 @@ const PDFViewerApplication = { const pdfThumbnailViewer = this.pdfThumbnailViewer; pdfThumbnailViewer.setDocument(pdfDocument); + const storedPromise = (this.store = new ViewHistory( + pdfDocument.fingerprint + )) + .getMultiple({ + page: null, + zoom: DEFAULT_SCALE_VALUE, + scrollLeft: "0", + scrollTop: "0", + rotation: null, + sidebarView: SidebarView.UNKNOWN, + scrollMode: ScrollMode.UNKNOWN, + spreadMode: SpreadMode.UNKNOWN, + }) + .catch(() => { + /* Unable to read from storage; ignoring errors. */ + return Object.create(null); + }); + firstPagePromise.then(pdfPage => { this.loadingBar.setWidth(this.appConfig.viewerContainer); - const storePromise = store - .getMultiple({ - page: null, - zoom: DEFAULT_SCALE_VALUE, - scrollLeft: "0", - scrollTop: "0", - rotation: null, - sidebarView: SidebarView.UNKNOWN, - scrollMode: ScrollMode.UNKNOWN, - spreadMode: SpreadMode.UNKNOWN, - }) - .catch(() => { - /* Unable to read from storage; ignoring errors. */ - }); - Promise.all([ animationStarted, - storePromise, + storedPromise, pageLayoutPromise, pageModePromise, openActionPromise, ]) - .then( - async ([ - timeStamp, - values = {}, - pageLayout, - pageMode, - openAction, - ]) => { - const viewOnLoad = AppOptions.get("viewOnLoad"); + .then(async ([timeStamp, stored, pageLayout, pageMode, openAction]) => { + const viewOnLoad = AppOptions.get("viewOnLoad"); - this._initializePdfHistory({ - fingerprint: pdfDocument.fingerprint, - viewOnLoad, - initialDest: openAction && openAction.dest, - }); - const initialBookmark = this.initialBookmark; + this._initializePdfHistory({ + fingerprint: pdfDocument.fingerprint, + viewOnLoad, + initialDest: openAction && openAction.dest, + }); + const initialBookmark = this.initialBookmark; - // Initialize the default values, from user preferences. - const zoom = AppOptions.get("defaultZoomValue"); - let hash = zoom ? `zoom=${zoom}` : null; + // Initialize the default values, from user preferences. + const zoom = AppOptions.get("defaultZoomValue"); + let hash = zoom ? `zoom=${zoom}` : null; - let rotation = null; - let sidebarView = AppOptions.get("sidebarViewOnLoad"); - let scrollMode = AppOptions.get("scrollModeOnLoad"); - let spreadMode = AppOptions.get("spreadModeOnLoad"); + let rotation = null; + let sidebarView = AppOptions.get("sidebarViewOnLoad"); + let scrollMode = AppOptions.get("scrollModeOnLoad"); + let spreadMode = AppOptions.get("spreadModeOnLoad"); - if (values.page && viewOnLoad !== ViewOnLoad.INITIAL) { - hash = - `page=${values.page}&zoom=${zoom || values.zoom},` + - `${values.scrollLeft},${values.scrollTop}`; + if (stored.page && viewOnLoad !== ViewOnLoad.INITIAL) { + hash = + `page=${stored.page}&zoom=${zoom || stored.zoom},` + + `${stored.scrollLeft},${stored.scrollTop}`; - rotation = parseInt(values.rotation, 10); - // Always let user preferences take precedence over the view - // history. - if (sidebarView === SidebarView.UNKNOWN) { - sidebarView = values.sidebarView | 0; - } - if (scrollMode === ScrollMode.UNKNOWN) { - scrollMode = values.scrollMode | 0; - } - if (spreadMode === SpreadMode.UNKNOWN) { - spreadMode = values.spreadMode | 0; - } + rotation = parseInt(stored.rotation, 10); + // Always let user preference take precedence over the view history. + if (sidebarView === SidebarView.UNKNOWN) { + sidebarView = stored.sidebarView | 0; } - // Always let the user preference/view history take precedence. - if (pageMode && sidebarView === SidebarView.UNKNOWN) { - sidebarView = apiPageModeToSidebarView(pageMode); + if (scrollMode === ScrollMode.UNKNOWN) { + scrollMode = stored.scrollMode | 0; } - if (pageLayout && spreadMode === SpreadMode.UNKNOWN) { - spreadMode = apiPageLayoutToSpreadMode(pageLayout); + if (spreadMode === SpreadMode.UNKNOWN) { + spreadMode = stored.spreadMode | 0; } - - this.setInitialView(hash, { - rotation, - sidebarView, - scrollMode, - spreadMode, - }); - this.eventBus.dispatch("documentinit", { source: this }); - // Make all navigation keys work on document load, - // unless the viewer is embedded in a web page. - if (!this.isViewerEmbedded) { - pdfViewer.focus(); - } - - // For documents with different page sizes, once all pages are - // resolved, ensure that the correct location becomes visible on - // load. - // (To reduce the risk, in very large and/or slow loading documents, - // that the location changes *after* the user has started - // interacting with the viewer, wait for either `pagesPromise` or - // a timeout.) - await Promise.race([ - pagesPromise, - new Promise(resolve => { - setTimeout(resolve, FORCE_PAGES_LOADED_TIMEOUT); - }), - ]); - if (!initialBookmark && !hash) { - return; - } - if (pdfViewer.hasEqualPageSizes) { - return; - } - this.initialBookmark = initialBookmark; - - // eslint-disable-next-line no-self-assign - pdfViewer.currentScaleValue = pdfViewer.currentScaleValue; - // Re-apply the initial document location. - this.setInitialView(hash); } - ) + // Always let the user preference/view history take precedence. + if (pageMode && sidebarView === SidebarView.UNKNOWN) { + sidebarView = apiPageModeToSidebarView(pageMode); + } + if (pageLayout && spreadMode === SpreadMode.UNKNOWN) { + spreadMode = apiPageLayoutToSpreadMode(pageLayout); + } + + this.setInitialView(hash, { + rotation, + sidebarView, + scrollMode, + spreadMode, + }); + this.eventBus.dispatch("documentinit", { source: this }); + // Make all navigation keys work on document load, + // unless the viewer is embedded in a web page. + if (!this.isViewerEmbedded) { + pdfViewer.focus(); + } + + // For documents with different page sizes, once all pages are + // resolved, ensure that the correct location becomes visible on load. + // (To reduce the risk, in very large and/or slow loading documents, + // that the location changes *after* the user has started interacting + // with the viewer, wait for either `pagesPromise` or a timeout.) + await Promise.race([ + pagesPromise, + new Promise(resolve => { + setTimeout(resolve, FORCE_PAGES_LOADED_TIMEOUT); + }), + ]); + if (!initialBookmark && !hash) { + return; + } + if (pdfViewer.hasEqualPageSizes) { + return; + } + this.initialBookmark = initialBookmark; + + // eslint-disable-next-line no-self-assign + pdfViewer.currentScaleValue = pdfViewer.currentScaleValue; + // Re-apply the initial document location. + this.setInitialView(hash); + }) .catch(() => { // Ensure that the document is always completely initialized, // even if there are any errors thrown above.