1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | "use strict";
|
23 |
|
24 | Object.defineProperty(exports, "__esModule", {
|
25 | value: true
|
26 | });
|
27 | exports.PDFPresentationMode = void 0;
|
28 |
|
29 | var _ui_utils = require("./ui_utils.js");
|
30 |
|
31 | var _pdf = require("../pdf");
|
32 |
|
33 | const DELAY_BEFORE_HIDING_CONTROLS = 3000;
|
34 | const ACTIVE_SELECTOR = "pdfPresentationMode";
|
35 | const CONTROLS_SELECTOR = "pdfPresentationModeControls";
|
36 | const MOUSE_SCROLL_COOLDOWN_TIME = 50;
|
37 | const PAGE_SWITCH_THRESHOLD = 0.1;
|
38 | const SWIPE_MIN_DISTANCE_THRESHOLD = 50;
|
39 | const SWIPE_ANGLE_THRESHOLD = Math.PI / 6;
|
40 |
|
41 | class PDFPresentationMode {
|
42 | #state = _ui_utils.PresentationModeState.UNKNOWN;
|
43 | #args = null;
|
44 |
|
45 | constructor({
|
46 | container,
|
47 | pdfViewer,
|
48 | eventBus
|
49 | }) {
|
50 | this.container = container;
|
51 | this.pdfViewer = pdfViewer;
|
52 | this.eventBus = eventBus;
|
53 | this.contextMenuOpen = false;
|
54 | this.mouseScrollTimeStamp = 0;
|
55 | this.mouseScrollDelta = 0;
|
56 | this.touchSwipeState = null;
|
57 | }
|
58 |
|
59 | async request() {
|
60 | const {
|
61 | container,
|
62 | pdfViewer
|
63 | } = this;
|
64 |
|
65 | if (this.active || !pdfViewer.pagesCount || !container.requestFullscreen) {
|
66 | return false;
|
67 | }
|
68 |
|
69 | this.#addFullscreenChangeListeners();
|
70 | this.#notifyStateChange(_ui_utils.PresentationModeState.CHANGING);
|
71 | const promise = container.requestFullscreen();
|
72 | this.#args = {
|
73 | pageNumber: pdfViewer.currentPageNumber,
|
74 | scaleValue: pdfViewer.currentScaleValue,
|
75 | scrollMode: pdfViewer.scrollMode,
|
76 | spreadMode: null,
|
77 | annotationEditorMode: null
|
78 | };
|
79 |
|
80 | if (pdfViewer.spreadMode !== _ui_utils.SpreadMode.NONE && !(pdfViewer.pageViewsReady && pdfViewer.hasEqualPageSizes)) {
|
81 | console.warn("Ignoring Spread modes when entering PresentationMode, " + "since the document may contain varying page sizes.");
|
82 | this.#args.spreadMode = pdfViewer.spreadMode;
|
83 | }
|
84 |
|
85 | if (pdfViewer.annotationEditorMode !== _pdf.AnnotationEditorType.DISABLE) {
|
86 | this.#args.annotationEditorMode = pdfViewer.annotationEditorMode;
|
87 | }
|
88 |
|
89 | try {
|
90 | await promise;
|
91 | return true;
|
92 | } catch (reason) {
|
93 | this.#removeFullscreenChangeListeners();
|
94 | this.#notifyStateChange(_ui_utils.PresentationModeState.NORMAL);
|
95 | }
|
96 |
|
97 | return false;
|
98 | }
|
99 |
|
100 | get active() {
|
101 | return this.#state === _ui_utils.PresentationModeState.CHANGING || this.#state === _ui_utils.PresentationModeState.FULLSCREEN;
|
102 | }
|
103 |
|
104 | #mouseWheel(evt) {
|
105 | if (!this.active) {
|
106 | return;
|
107 | }
|
108 |
|
109 | evt.preventDefault();
|
110 | const delta = (0, _ui_utils.normalizeWheelEventDelta)(evt);
|
111 | const currentTime = Date.now();
|
112 | const storedTime = this.mouseScrollTimeStamp;
|
113 |
|
114 | if (currentTime > storedTime && currentTime - storedTime < MOUSE_SCROLL_COOLDOWN_TIME) {
|
115 | return;
|
116 | }
|
117 |
|
118 | if (this.mouseScrollDelta > 0 && delta < 0 || this.mouseScrollDelta < 0 && delta > 0) {
|
119 | this.#resetMouseScrollState();
|
120 | }
|
121 |
|
122 | this.mouseScrollDelta += delta;
|
123 |
|
124 | if (Math.abs(this.mouseScrollDelta) >= PAGE_SWITCH_THRESHOLD) {
|
125 | const totalDelta = this.mouseScrollDelta;
|
126 | this.#resetMouseScrollState();
|
127 | const success = totalDelta > 0 ? this.pdfViewer.previousPage() : this.pdfViewer.nextPage();
|
128 |
|
129 | if (success) {
|
130 | this.mouseScrollTimeStamp = currentTime;
|
131 | }
|
132 | }
|
133 | }
|
134 |
|
135 | #notifyStateChange(state) {
|
136 | this.#state = state;
|
137 | this.eventBus.dispatch("presentationmodechanged", {
|
138 | source: this,
|
139 | state
|
140 | });
|
141 | }
|
142 |
|
143 | #enter() {
|
144 | this.#notifyStateChange(_ui_utils.PresentationModeState.FULLSCREEN);
|
145 | this.container.classList.add(ACTIVE_SELECTOR);
|
146 | setTimeout(() => {
|
147 | this.pdfViewer.scrollMode = _ui_utils.ScrollMode.PAGE;
|
148 |
|
149 | if (this.#args.spreadMode !== null) {
|
150 | this.pdfViewer.spreadMode = _ui_utils.SpreadMode.NONE;
|
151 | }
|
152 |
|
153 | this.pdfViewer.currentPageNumber = this.#args.pageNumber;
|
154 | this.pdfViewer.currentScaleValue = "page-fit";
|
155 |
|
156 | if (this.#args.annotationEditorMode !== null) {
|
157 | this.pdfViewer.annotationEditorMode = _pdf.AnnotationEditorType.NONE;
|
158 | }
|
159 | }, 0);
|
160 | this.#addWindowListeners();
|
161 | this.#showControls();
|
162 | this.contextMenuOpen = false;
|
163 | window.getSelection().removeAllRanges();
|
164 | }
|
165 |
|
166 | #exit() {
|
167 | const pageNumber = this.pdfViewer.currentPageNumber;
|
168 | this.container.classList.remove(ACTIVE_SELECTOR);
|
169 | setTimeout(() => {
|
170 | this.#removeFullscreenChangeListeners();
|
171 | this.#notifyStateChange(_ui_utils.PresentationModeState.NORMAL);
|
172 | this.pdfViewer.scrollMode = this.#args.scrollMode;
|
173 |
|
174 | if (this.#args.spreadMode !== null) {
|
175 | this.pdfViewer.spreadMode = this.#args.spreadMode;
|
176 | }
|
177 |
|
178 | this.pdfViewer.currentScaleValue = this.#args.scaleValue;
|
179 | this.pdfViewer.currentPageNumber = pageNumber;
|
180 |
|
181 | if (this.#args.annotationEditorMode !== null) {
|
182 | this.pdfViewer.annotationEditorMode = this.#args.annotationEditorMode;
|
183 | }
|
184 |
|
185 | this.#args = null;
|
186 | }, 0);
|
187 | this.#removeWindowListeners();
|
188 | this.#hideControls();
|
189 | this.#resetMouseScrollState();
|
190 | this.contextMenuOpen = false;
|
191 | }
|
192 |
|
193 | #mouseDown(evt) {
|
194 | if (this.contextMenuOpen) {
|
195 | this.contextMenuOpen = false;
|
196 | evt.preventDefault();
|
197 | return;
|
198 | }
|
199 |
|
200 | if (evt.button === 0) {
|
201 | const isInternalLink = evt.target.href && evt.target.classList.contains("internalLink");
|
202 |
|
203 | if (!isInternalLink) {
|
204 | evt.preventDefault();
|
205 |
|
206 | if (evt.shiftKey) {
|
207 | this.pdfViewer.previousPage();
|
208 | } else {
|
209 | this.pdfViewer.nextPage();
|
210 | }
|
211 | }
|
212 | }
|
213 | }
|
214 |
|
215 | #contextMenu() {
|
216 | this.contextMenuOpen = true;
|
217 | }
|
218 |
|
219 | #showControls() {
|
220 | if (this.controlsTimeout) {
|
221 | clearTimeout(this.controlsTimeout);
|
222 | } else {
|
223 | this.container.classList.add(CONTROLS_SELECTOR);
|
224 | }
|
225 |
|
226 | this.controlsTimeout = setTimeout(() => {
|
227 | this.container.classList.remove(CONTROLS_SELECTOR);
|
228 | delete this.controlsTimeout;
|
229 | }, DELAY_BEFORE_HIDING_CONTROLS);
|
230 | }
|
231 |
|
232 | #hideControls() {
|
233 | if (!this.controlsTimeout) {
|
234 | return;
|
235 | }
|
236 |
|
237 | clearTimeout(this.controlsTimeout);
|
238 | this.container.classList.remove(CONTROLS_SELECTOR);
|
239 | delete this.controlsTimeout;
|
240 | }
|
241 |
|
242 | #resetMouseScrollState() {
|
243 | this.mouseScrollTimeStamp = 0;
|
244 | this.mouseScrollDelta = 0;
|
245 | }
|
246 |
|
247 | #touchSwipe(evt) {
|
248 | if (!this.active) {
|
249 | return;
|
250 | }
|
251 |
|
252 | if (evt.touches.length > 1) {
|
253 | this.touchSwipeState = null;
|
254 | return;
|
255 | }
|
256 |
|
257 | switch (evt.type) {
|
258 | case "touchstart":
|
259 | this.touchSwipeState = {
|
260 | startX: evt.touches[0].pageX,
|
261 | startY: evt.touches[0].pageY,
|
262 | endX: evt.touches[0].pageX,
|
263 | endY: evt.touches[0].pageY
|
264 | };
|
265 | break;
|
266 |
|
267 | case "touchmove":
|
268 | if (this.touchSwipeState === null) {
|
269 | return;
|
270 | }
|
271 |
|
272 | this.touchSwipeState.endX = evt.touches[0].pageX;
|
273 | this.touchSwipeState.endY = evt.touches[0].pageY;
|
274 | evt.preventDefault();
|
275 | break;
|
276 |
|
277 | case "touchend":
|
278 | if (this.touchSwipeState === null) {
|
279 | return;
|
280 | }
|
281 |
|
282 | let delta = 0;
|
283 | const dx = this.touchSwipeState.endX - this.touchSwipeState.startX;
|
284 | const dy = this.touchSwipeState.endY - this.touchSwipeState.startY;
|
285 | const absAngle = Math.abs(Math.atan2(dy, dx));
|
286 |
|
287 | if (Math.abs(dx) > SWIPE_MIN_DISTANCE_THRESHOLD && (absAngle <= SWIPE_ANGLE_THRESHOLD || absAngle >= Math.PI - SWIPE_ANGLE_THRESHOLD)) {
|
288 | delta = dx;
|
289 | } else if (Math.abs(dy) > SWIPE_MIN_DISTANCE_THRESHOLD && Math.abs(absAngle - Math.PI / 2) <= SWIPE_ANGLE_THRESHOLD) {
|
290 | delta = dy;
|
291 | }
|
292 |
|
293 | if (delta > 0) {
|
294 | this.pdfViewer.previousPage();
|
295 | } else if (delta < 0) {
|
296 | this.pdfViewer.nextPage();
|
297 | }
|
298 |
|
299 | break;
|
300 | }
|
301 | }
|
302 |
|
303 | #addWindowListeners() {
|
304 | this.showControlsBind = this.#showControls.bind(this);
|
305 | this.mouseDownBind = this.#mouseDown.bind(this);
|
306 | this.mouseWheelBind = this.#mouseWheel.bind(this);
|
307 | this.resetMouseScrollStateBind = this.#resetMouseScrollState.bind(this);
|
308 | this.contextMenuBind = this.#contextMenu.bind(this);
|
309 | this.touchSwipeBind = this.#touchSwipe.bind(this);
|
310 | window.addEventListener("mousemove", this.showControlsBind);
|
311 | window.addEventListener("mousedown", this.mouseDownBind);
|
312 | window.addEventListener("wheel", this.mouseWheelBind, {
|
313 | passive: false
|
314 | });
|
315 | window.addEventListener("keydown", this.resetMouseScrollStateBind);
|
316 | window.addEventListener("contextmenu", this.contextMenuBind);
|
317 | window.addEventListener("touchstart", this.touchSwipeBind);
|
318 | window.addEventListener("touchmove", this.touchSwipeBind);
|
319 | window.addEventListener("touchend", this.touchSwipeBind);
|
320 | }
|
321 |
|
322 | #removeWindowListeners() {
|
323 | window.removeEventListener("mousemove", this.showControlsBind);
|
324 | window.removeEventListener("mousedown", this.mouseDownBind);
|
325 | window.removeEventListener("wheel", this.mouseWheelBind, {
|
326 | passive: false
|
327 | });
|
328 | window.removeEventListener("keydown", this.resetMouseScrollStateBind);
|
329 | window.removeEventListener("contextmenu", this.contextMenuBind);
|
330 | window.removeEventListener("touchstart", this.touchSwipeBind);
|
331 | window.removeEventListener("touchmove", this.touchSwipeBind);
|
332 | window.removeEventListener("touchend", this.touchSwipeBind);
|
333 | delete this.showControlsBind;
|
334 | delete this.mouseDownBind;
|
335 | delete this.mouseWheelBind;
|
336 | delete this.resetMouseScrollStateBind;
|
337 | delete this.contextMenuBind;
|
338 | delete this.touchSwipeBind;
|
339 | }
|
340 |
|
341 | #fullscreenChange() {
|
342 | if (document.fullscreenElement) {
|
343 | this.#enter();
|
344 | } else {
|
345 | this.#exit();
|
346 | }
|
347 | }
|
348 |
|
349 | #addFullscreenChangeListeners() {
|
350 | this.fullscreenChangeBind = this.#fullscreenChange.bind(this);
|
351 | window.addEventListener("fullscreenchange", this.fullscreenChangeBind);
|
352 | }
|
353 |
|
354 | #removeFullscreenChangeListeners() {
|
355 | window.removeEventListener("fullscreenchange", this.fullscreenChangeBind);
|
356 | delete this.fullscreenChangeBind;
|
357 | }
|
358 |
|
359 | }
|
360 |
|
361 | exports.PDFPresentationMode = PDFPresentationMode; |
\ | No newline at end of file |