diff --git a/web/base_viewer.js b/web/base_viewer.js index 7a5c599074442..2c343200ea09f 100644 --- a/web/base_viewer.js +++ b/web/base_viewer.js @@ -115,6 +115,10 @@ function PDFPageViewBuffer(size) { data.shift().destroy(); } }; + + this.has = function (view) { + return data.includes(view); + }; } function isSameScale(oldScale, newScale) { @@ -1096,9 +1100,15 @@ class BaseViewer { if (!this.pdfDocument) { return false; } - if (pageNumber < 1 || pageNumber > this.pagesCount) { + if ( + !( + Number.isInteger(pageNumber) && + pageNumber > 0 && + pageNumber <= this.pagesCount + ) + ) { console.error( - `${this._name}.isPageVisible: "${pageNumber}" is out of bounds.` + `${this._name}.isPageVisible: "${pageNumber}" is not a valid page.` ); return false; } @@ -1107,6 +1117,32 @@ class BaseViewer { }); } + /** + * @param {number} pageNumber + */ + isPageCached(pageNumber) { + if (!this.pdfDocument || !this._buffer) { + return false; + } + if ( + !( + Number.isInteger(pageNumber) && + pageNumber > 0 && + pageNumber <= this.pagesCount + ) + ) { + console.error( + `${this._name}.isPageCached: "${pageNumber}" is not a valid page.` + ); + return false; + } + const pageView = this._pages[pageNumber - 1]; + if (!pageView) { + return false; + } + return this._buffer.has(pageView); + } + cleanup() { for (let i = 0, ii = this._pages.length; i < ii; i++) { if ( diff --git a/web/interfaces.js b/web/interfaces.js index bd29db6f3ef79..0925417a2d152 100644 --- a/web/interfaces.js +++ b/web/interfaces.js @@ -95,6 +95,11 @@ class IPDFLinkService { * @param {number} pageNumber */ isPageVisible(pageNumber) {} + + /** + * @param {number} pageNumber + */ + isPageCached(pageNumber) {} } /** diff --git a/web/pdf_link_service.js b/web/pdf_link_service.js index c484d9f5dee91..fc7016fd49f31 100644 --- a/web/pdf_link_service.js +++ b/web/pdf_link_service.js @@ -458,6 +458,13 @@ class PDFLinkService { isPageVisible(pageNumber) { return this.pdfViewer.isPageVisible(pageNumber); } + + /** + * @param {number} pageNumber + */ + isPageCached(pageNumber) { + return this.pdfViewer.isPageCached(pageNumber); + } } function isValidExplicitDestination(dest) { @@ -609,6 +616,13 @@ class SimpleLinkService { isPageVisible(pageNumber) { return true; } + + /** + * @param {number} pageNumber + */ + isPageCached(pageNumber) { + return true; + } } export { PDFLinkService, SimpleLinkService }; diff --git a/web/pdf_thumbnail_view.js b/web/pdf_thumbnail_view.js index bf325ec6da68d..633f8ab655414 100644 --- a/web/pdf_thumbnail_view.js +++ b/web/pdf_thumbnail_view.js @@ -363,6 +363,16 @@ class PDFThumbnailView { finishRenderTask(error); } ); + // Only trigger cleanup, once rendering has finished, when the current + // pageView is *not* cached on the `BaseViewer`-instance. + resultPromise.finally(() => { + const pageCached = this.linkService.isPageCached(this.id); + if (pageCached) { + return; + } + this.pdfPage?.cleanup(); + }); + return resultPromise; }