diff --git a/web/pdf_presentation_mode.js b/web/pdf_presentation_mode.js index f94bea021..912d3a202 100644 --- a/web/pdf_presentation_mode.js +++ b/web/pdf_presentation_mode.js @@ -20,7 +20,6 @@ import { SpreadMode, } from "./ui_utils.js"; -const DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS = 1500; // in ms const DELAY_BEFORE_HIDING_CONTROLS = 3000; // in ms const ACTIVE_SELECTOR = "pdfPresentationMode"; const CONTROLS_SELECTOR = "pdfPresentationModeControls"; @@ -42,6 +41,10 @@ const SWIPE_ANGLE_THRESHOLD = Math.PI / 6; */ class PDFPresentationMode { + #state = PresentationModeState.UNKNOWN; + + #args = null; + /** * @param {PDFPresentationModeOptions} options */ @@ -50,8 +53,6 @@ class PDFPresentationMode { this.pdfViewer = pdfViewer; this.eventBus = eventBus; - this.active = false; - this.args = null; this.contextMenuOpen = false; this.mouseScrollTimeStamp = 0; this.mouseScrollDelta = 0; @@ -60,37 +61,47 @@ class PDFPresentationMode { /** * Request the browser to enter fullscreen mode. - * @returns {boolean} Indicating if the request was successful. + * @returns {Promise} Indicating if the request was successful. */ - request() { - if ( - this.switchInProgress || - this.active || - !this.pdfViewer.pagesCount || - !this.container.requestFullscreen - ) { + async request() { + const { container, pdfViewer } = this; + + if (this.active || !pdfViewer.pagesCount || !container.requestFullscreen) { return false; } this.#addFullscreenChangeListeners(); - this.#setSwitchInProgress(); - this.#notifyStateChange(); + this.#notifyStateChange(PresentationModeState.CHANGING); - this.container.requestFullscreen(); + const promise = container.requestFullscreen(); - this.args = { - pageNumber: this.pdfViewer.currentPageNumber, - scaleValue: this.pdfViewer.currentScaleValue, - scrollMode: this.pdfViewer.scrollMode, - spreadMode: this.pdfViewer.spreadMode, + this.#args = { + pageNumber: pdfViewer.currentPageNumber, + scaleValue: pdfViewer.currentScaleValue, + scrollMode: pdfViewer.scrollMode, + spreadMode: pdfViewer.spreadMode, }; - return true; + + try { + await promise; + return true; + } catch (reason) { + this.#removeFullscreenChangeListeners(); + this.#notifyStateChange(PresentationModeState.NORMAL); + } + return false; + } + + get active() { + return ( + this.#state === PresentationModeState.CHANGING || + this.#state === PresentationModeState.FULLSCREEN + ); } #mouseWheel(evt) { if (!this.active) { return; } - evt.preventDefault(); const delta = normalizeWheelEventDelta(evt); @@ -126,48 +137,14 @@ class PDFPresentationMode { } } - #notifyStateChange() { - let state = PresentationModeState.NORMAL; - if (this.switchInProgress) { - state = PresentationModeState.CHANGING; - } else if (this.active) { - state = PresentationModeState.FULLSCREEN; - } - this.eventBus.dispatch("presentationmodechanged", { - source: this, - state, - }); - } + #notifyStateChange(state) { + this.#state = state; - /** - * Used to initialize a timeout when requesting Presentation Mode, - * i.e. when the browser is requested to enter fullscreen mode. - * This timeout is used to prevent the current page from being scrolled - * partially, or completely, out of view when entering Presentation Mode. - * NOTE: This issue seems limited to certain zoom levels (e.g. page-width). - */ - #setSwitchInProgress() { - if (this.switchInProgress) { - clearTimeout(this.switchInProgress); - } - this.switchInProgress = setTimeout(() => { - this.#removeFullscreenChangeListeners(); - delete this.switchInProgress; - this.#notifyStateChange(); - }, DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS); - } - - #resetSwitchInProgress() { - if (this.switchInProgress) { - clearTimeout(this.switchInProgress); - delete this.switchInProgress; - } + this.eventBus.dispatch("presentationmodechanged", { source: this, state }); } #enter() { - this.active = true; - this.#resetSwitchInProgress(); - this.#notifyStateChange(); + this.#notifyStateChange(PresentationModeState.FULLSCREEN); this.container.classList.add(ACTIVE_SELECTOR); // Ensure that the correct page is scrolled into view when entering @@ -175,7 +152,7 @@ class PDFPresentationMode { setTimeout(() => { this.pdfViewer.scrollMode = ScrollMode.PAGE; this.pdfViewer.spreadMode = SpreadMode.NONE; - this.pdfViewer.currentPageNumber = this.args.pageNumber; + this.pdfViewer.currentPageNumber = this.#args.pageNumber; this.pdfViewer.currentScaleValue = "page-fit"; }, 0); @@ -196,15 +173,14 @@ class PDFPresentationMode { // Ensure that the correct page is scrolled into view when exiting // Presentation Mode, by waiting until fullscreen mode is disabled. setTimeout(() => { - this.active = false; this.#removeFullscreenChangeListeners(); - this.#notifyStateChange(); + this.#notifyStateChange(PresentationModeState.NORMAL); - this.pdfViewer.scrollMode = this.args.scrollMode; - this.pdfViewer.spreadMode = this.args.spreadMode; - this.pdfViewer.currentScaleValue = this.args.scaleValue; + this.pdfViewer.scrollMode = this.#args.scrollMode; + this.pdfViewer.spreadMode = this.#args.spreadMode; + this.pdfViewer.currentScaleValue = this.#args.scaleValue; this.pdfViewer.currentPageNumber = pageNumber; - this.args = null; + this.#args = null; }, 0); this.#removeWindowListeners();