Commit 8188eada authored by Robert Knight's avatar Robert Knight

Add fallback for `PDFViewerApplication.appConfig` for older PDF.js releases

Specify the type of `window.PDFViewerApplication` in src/types/pdfjs.js
add various missing properties required by `PDFIntegration` as well as
adding checks for potentially null/undefined values that were missing
previously.

 - Add a fallback for older versions of PDF.js where `PDFViewerApplication`
   did not have an `appConfig` property [1]
 - Add a missing check for `getPageView` returning `null`

Fixes https://github.com/hypothesis/product-backlog/issues/1205

[1] The property was introduced in https://github.com/mozilla/pdf.js/commit/b6c74f20561b04573cd00dd924484be7f80a09ce
parent 3b967dc6
......@@ -23,6 +23,7 @@ import { PDFMetadata } from './pdf-metadata';
* @typedef {import('../../types/annotator').Integration} Integration
* @typedef {import('../../types/annotator').SidebarLayout} SidebarLayout
* @typedef {import('../../types/api').Selector} Selector
* @typedef {import('../../types/pdfjs').PDFViewerApplication} PDFViewerApplication
*/
// The viewport and controls for PDF.js start breaking down below about 670px
......@@ -61,14 +62,18 @@ export class PDFIntegration {
this.annotator = annotator;
const window_ = /** @type {HypothesisWindow} */ (window);
this.pdfViewer = window_.PDFViewerApplication.pdfViewer;
// Assume this class is only used if we're in the PDF.js viewer.
const pdfViewerApp = /** @type {PDFViewerApplication} */ (window_.PDFViewerApplication);
this.pdfViewer = pdfViewerApp.pdfViewer;
this.pdfViewer.viewer.classList.add('has-transparent-text-layer');
// Get the element that contains all of the PDF.js UI. This is typically
// `document.body`.
this.pdfContainer = window_.PDFViewerApplication?.appConfig?.appContainer;
this.pdfContainer = pdfViewerApp.appConfig?.appContainer ?? document.body;
this.pdfMetadata = new PDFMetadata(window_.PDFViewerApplication);
this.pdfMetadata = new PDFMetadata(pdfViewerApp);
this.observer = new MutationObserver(debounce(() => this._update(), 100));
this.observer.observe(this.pdfViewer.viewer, {
......@@ -241,7 +246,7 @@ export class PDFIntegration {
const pageCount = this.pdfViewer.pagesCount;
for (let pageIndex = 0; pageIndex < pageCount; pageIndex++) {
const page = this.pdfViewer.getPageView(pageIndex);
if (!page.textLayer?.renderingDone) {
if (!page?.textLayer?.renderingDone) {
continue;
}
......
......@@ -138,7 +138,7 @@
* when loaded in a frame that influence how it behaves.
*
* @typedef Globals
* @prop {Object} [PDFViewerApplication] -
* @prop {import('./pdfjs').PDFViewerApplication} [PDFViewerApplication] -
* PDF.js entry point. If set, triggers loading of PDF rather than HTML integration.
* @prop {boolean} [__hypothesis_frame] -
* Flag used to indicate that the "annotator" part of Hypothesis is loaded in
......
......@@ -88,10 +88,14 @@
*
* Defined in `web/pdf_viewer.js` in the PDF.js source.
*
* @prop {string} currentScaleValue - Zoom level/mode. This can be a string representation
* of a float or a special constant ("auto", "page-fit", "page-width" and more)
* @prop {number} pagesCount
* @prop {EventBus} eventBus -
* Reference to the global event bus. Added in PDF.js v1.6.210.
* @prop {(page: number) => PDFPageView|null} getPageView
* @prop {HTMLElement} viewer - DOM element containing the main content of the document
* @prop {() => void} update - Re-render the current view
*/
/**
......@@ -102,12 +106,21 @@
* @prop {(event: string, listener: Function) => void} off
*/
/**
* Object containing references to various DOM elements that make up the PDF.js viewer UI,
* as well as a few other global objects used by the viewer.
*
* @typedef AppConfig
* @prop {HTMLElement} appContainer
*/
/**
* The `PDFViewerApplication` global which is the entry-point for accessing PDF.js.
*
* Defined in `web/app.js` in the PDF.js source.
*
* @typedef PDFViewerApplication
* @prop {AppConfig} [appConfig] - Viewer DOM elements. Since v1.5.188.
* @prop {EventBus} [eventBus] -
* Global event bus. Since v1.6.210. This is not available until the PDF viewer
* has been initialized. See `initialized` and `initializedPromise` properties.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment