Skip to content

Simplify handling of requestFullscreen errors in PDFPresentationMode #14765

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 10, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 42 additions & 66 deletions web/pdf_presentation_mode.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -42,6 +41,10 @@ const SWIPE_ANGLE_THRESHOLD = Math.PI / 6;
*/

class PDFPresentationMode {
#state = PresentationModeState.UNKNOWN;

#args = null;

/**
* @param {PDFPresentationModeOptions} options
*/
Expand All @@ -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;
Expand All @@ -60,37 +61,47 @@ class PDFPresentationMode {

/**
* Request the browser to enter fullscreen mode.
* @returns {boolean} Indicating if the request was successful.
* @returns {Promise<boolean>} 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);
Expand Down Expand Up @@ -126,56 +137,22 @@ 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,
});
}

/**
* 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);
}
#notifyStateChange(state) {
this.#state = state;

#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
// Presentation Mode, by waiting until fullscreen mode in enabled.
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);

Expand All @@ -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();
Expand Down