From 3fa27c054a2e66b038557801debfb39700194fd6 Mon Sep 17 00:00:00 2001
From: pacien
Date: Wed, 24 Oct 2018 05:03:45 +0200
Subject: Rename project
---
beamer/viewer/init.js | 67 +++++++++++++++++++++++
beamer/viewer/presentation.js | 57 +++++++++++++++++++
beamer/viewer/screen/screen.js | 110 +++++++++++++++++++++++++++++++++++++
beamer/viewer/screen/timer.js | 48 ++++++++++++++++
beamer/viewer/stage/actions.js | 121 +++++++++++++++++++++++++++++++++++++++++
beamer/viewer/stage/stage.js | 76 ++++++++++++++++++++++++++
beamer/viewer/viewer.css | 116 +++++++++++++++++++++++++++++++++++++++
beamer/viewer/viewer.js | 65 ++++++++++++++++++++++
8 files changed, 660 insertions(+)
create mode 100644 beamer/viewer/init.js
create mode 100644 beamer/viewer/presentation.js
create mode 100644 beamer/viewer/screen/screen.js
create mode 100644 beamer/viewer/screen/timer.js
create mode 100644 beamer/viewer/stage/actions.js
create mode 100644 beamer/viewer/stage/stage.js
create mode 100644 beamer/viewer/viewer.css
create mode 100644 beamer/viewer/viewer.js
(limited to 'beamer/viewer')
diff --git a/beamer/viewer/init.js b/beamer/viewer/init.js
new file mode 100644
index 0000000..9192834
--- /dev/null
+++ b/beamer/viewer/init.js
@@ -0,0 +1,67 @@
+/*
+ * Beamer Viewer, a web-based PDF presentation viewer
+ * Copyright (C) 2018 Pacien TRAN-GIRARD
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+"use strict";
+
+const params = function() {
+ const queryDict = {};
+ location.hash.substr(1).split("&").forEach(item => {
+ const pair = item.split("=");
+ queryDict[pair[0]] = pair[1];
+ });
+ return queryDict;
+}();
+
+function isController() {
+ return window.opener == null || window.opener.location.href != window.location.href;
+}
+
+function initCache() {
+ if (!navigator.serviceWorker) return;
+ navigator.serviceWorker.register("appcache.js");
+
+ const offlineCapableIndicator = document.getElementById("offlineCapable");
+ offlineCapableIndicator.style.visibility = "visible";
+}
+
+function checkPopupPermission() {
+ const popup = window.open("popup.html");
+
+ if (popup == null) {
+ const warningMessage = document.getElementById("warning");
+ warningMessage.textContent = "A pop-up blocker is active. Make sure to allow pop-ups on this website.";
+ }
+}
+
+function init() {
+ initCache();
+ checkPopupPermission();
+
+ const viewer = new Viewer();
+
+ if ("file" in params)
+ viewer.load(params["file"]);
+}
+
+function load(file) {
+ location.hash = "file=" + file;
+ location.reload();
+}
+
+if (isController())
+ init();
diff --git a/beamer/viewer/presentation.js b/beamer/viewer/presentation.js
new file mode 100644
index 0000000..222a6d4
--- /dev/null
+++ b/beamer/viewer/presentation.js
@@ -0,0 +1,57 @@
+/*
+ * Beamer Viewer, a web-based PDF presentation viewer
+ * Copyright (C) 2018 Pacien TRAN-GIRARD
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+"use strict";
+
+class Presentation {
+ constructor(pdf) {
+ this.pdf = pdf;
+ this.currentPageIndex = 1;
+ this.stage = this._setupStage();
+ }
+
+ _setupStage() {
+ const self = this;
+ const onStageReadyCallback = function() { self._onStageReady(); };
+ const onNextCallback = function() { self._onNext(); };
+ const onPreviousCallback = function() { self._onPrevious(); };
+ return new Stage(onStageReadyCallback, onNextCallback, onPreviousCallback);
+ }
+
+ _onStageReady() {
+ this._setPage(this.currentPageIndex);
+ }
+
+ _onNext() {
+ if (this.currentPageIndex === this.pdf.numPages) return;
+ this._setPage(this.currentPageIndex + 1);
+ }
+
+ _onPrevious() {
+ if (this.currentPageIndex === 1) return;
+ this._setPage(this.currentPageIndex - 1);
+ }
+
+ _setPage(pageIndex) {
+ const self = this;
+ this.currentPageIndex = pageIndex;
+ this.pdf.getPage(this.currentPageIndex).then(function(page) {
+ self.stage.setPage(page);
+ })
+ }
+}
diff --git a/beamer/viewer/screen/screen.js b/beamer/viewer/screen/screen.js
new file mode 100644
index 0000000..c65ebc3
--- /dev/null
+++ b/beamer/viewer/screen/screen.js
@@ -0,0 +1,110 @@
+/*
+ * Beamer Viewer, a web-based PDF presentation viewer
+ * Copyright (C) 2018 Pacien TRAN-GIRARD
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+"use strict";
+
+class Screen {
+ constructor(window, secondary=false, withTimer=false) {
+ this.window = window;
+ this.secondary = secondary;
+
+ this.canvasId = "screen";
+ this.page = null;
+
+ this.timer = withTimer ? new Timer(window) : null;
+ this.pageTurnCount = 0;
+
+ this._registerListeners();
+ this._hideWelcomeScreen();
+ }
+
+ setPage(page) {
+ if (this.pageTurnCount++ === 1 && this.timer != null)
+ this.timer.start();
+
+ this.page = page;
+ this._repaint();
+ }
+
+ _registerListeners() {
+ const self = this;
+ this.window.addEventListener("resize", function() {
+ self._repaint();
+ });
+ }
+
+ _hideWelcomeScreen() {
+ const welcomeScreen = this.window.document.getElementById("welcomeScreen");
+ welcomeScreen.style.display = "none";
+ }
+
+ _getScreenSize(ratio) {
+ const windowRatio = this.window.innerWidth / this.window.innerHeight;
+ const horizontalScaleFactor = ratio / windowRatio;
+ return {
+ width: this.window.innerWidth * Math.min(horizontalScaleFactor, 1),
+ height: this.window.innerHeight / Math.max(horizontalScaleFactor, 1)
+ };
+ }
+
+ _getSlideSizeRatio() {
+ const viewport = this.page.getViewport(1);
+ return (viewport.width / 2) / viewport.height;
+ }
+
+ _newCanvas(width, height, xOffset, yOffset) {
+ const canvas = document.createElement("canvas");
+ canvas.width = width;
+ canvas.height = height;
+
+ const context = canvas.getContext("2d");
+ context.transform(1, 0, 0, 1, xOffset, yOffset);
+
+ return { canvas: canvas, context: context };
+ }
+
+ _showCanvas(canvas) {
+ const oldCanvas = this.window.document.getElementById(this.canvasId);
+ canvas.id = oldCanvas.id;
+ canvas.classList = oldCanvas.classList;
+ oldCanvas.replaceWith(canvas);
+ }
+
+ _render(canvas, context, scaleFactor) {
+ const renderContext = {
+ canvasContext: context,
+ viewport: this.page.getViewport(scaleFactor)
+ };
+
+ const self = this;
+ this.page.render(renderContext).then(function() {
+ self._showCanvas(canvas);
+ });
+ }
+
+ _repaint() {
+ if (this.page == null) return;
+
+ const screenRatio = this._getSlideSizeRatio();
+ const { width, height } = this._getScreenSize(screenRatio);
+ const scaleFactor = height / this.page.getViewport(1).height;
+ const xOffset = this.secondary ? -width : 0;
+ const { canvas, context } = this._newCanvas(width, height, xOffset, 0);
+ this._render(canvas, context, scaleFactor);
+ }
+}
diff --git a/beamer/viewer/screen/timer.js b/beamer/viewer/screen/timer.js
new file mode 100644
index 0000000..a04ea63
--- /dev/null
+++ b/beamer/viewer/screen/timer.js
@@ -0,0 +1,48 @@
+/*
+ * Beamer Viewer, a web-based PDF presentation viewer
+ * Copyright (C) 2018 Pacien TRAN-GIRARD
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+"use strict";
+
+class Timer {
+ constructor(window) {
+ this.display = window.document.getElementById("timer");
+ this.startTime = null;
+ this._setDisplay(0);
+ }
+
+ start() {
+ if (this.startTime != null) return;
+ this.startTime = Date.now();
+
+ const self = this;
+ setInterval(function() {
+ self._runTimer();
+ }, 1000);
+ }
+
+ _runTimer() {
+ const timeDelta = Math.floor((Date.now() - this.startTime) / 1000);
+ this._setDisplay(timeDelta);
+ }
+
+ _setDisplay(seconds) {
+ const dateObj = new Date(null);
+ dateObj.setSeconds(seconds);
+ this.display.textContent = dateObj.toISOString().substr(11, 8);
+ }
+}
diff --git a/beamer/viewer/stage/actions.js b/beamer/viewer/stage/actions.js
new file mode 100644
index 0000000..601a441
--- /dev/null
+++ b/beamer/viewer/stage/actions.js
@@ -0,0 +1,121 @@
+/*
+ * Beamer Viewer, a web-based PDF presentation viewer
+ * Copyright (C) 2018 Pacien TRAN-GIRARD
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+"use strict";
+
+class ActionEventHandler {
+ constructor(onNext, onPrevious) {
+ this.onNext = onNext;
+ this.onPrevious = onPrevious;
+ }
+}
+
+class KeyboardEventHandler extends ActionEventHandler {
+ register(window) {
+ const self = this;
+ window.addEventListener("keydown", function(event) {
+ self._onCommand(event);
+ })
+ }
+
+ _onCommand(keyboardEvent) {
+ switch (keyboardEvent.key) {
+ case "Enter":
+ case " ":
+ case "ArrowRight":
+ case "n":
+ return this.onNext();
+
+ case "ArrowLeft":
+ case "p":
+ return this.onPrevious();
+ }
+ }
+}
+
+class MouseClickEventHandler extends ActionEventHandler {
+ register(window) {
+ const self = this;
+ window.addEventListener("click", function(event) {
+ self._onCommand(event);
+ })
+ }
+
+ _onCommand(mouseEvent) {
+ this.onNext();
+ }
+}
+
+class TouchSwipeEventHandler extends ActionEventHandler {
+ constructor(onNext, onPrevious) {
+ super(onNext, onPrevious);
+ this.touchStartEvent = null;
+ this.touchMoveEvent = null;
+ }
+
+ register(window) {
+ const self = this;
+
+ window.addEventListener("touchstart", function(event) {
+ event.preventDefault();
+ self._onTouchStart(event);
+ });
+
+ window.addEventListener("touchmove", function(event) {
+ event.preventDefault();
+ self._onTouchMove(event);
+ });
+
+ window.addEventListener("touchend", function(event) {
+ event.preventDefault();
+ self._onTouchEnd();
+ });
+
+ window.addEventListener("touchcancel", function(event) {
+ event.preventDefault();
+ });
+ }
+
+ _onTouchStart(touchEvent) {
+ this.touchStartEvent = touchEvent;
+ }
+
+ _onTouchMove(touchEvent) {
+ this.touchMoveEvent = touchEvent;
+ }
+
+ _onTouchEnd() {
+ if (this.touchStartEvent == null || this.touchMoveEvent == null) return;
+
+ const touchDown = this._xCoordinate(this.touchStartEvent);
+ const touchUp = this._xCoordinate(this.touchMoveEvent);
+ const xDelta = touchDown - touchUp;
+
+ if (xDelta > 0)
+ this.onNext();
+ else if (xDelta < 0)
+ this.onPrevious();
+
+ this.touchStartEvent = null;
+ this.touchMoveEvent = null;
+ }
+
+ _xCoordinate(touchEvent) {
+ return touchEvent.touches[0].clientX; // first finger
+ }
+}
diff --git a/beamer/viewer/stage/stage.js b/beamer/viewer/stage/stage.js
new file mode 100644
index 0000000..201f7b4
--- /dev/null
+++ b/beamer/viewer/stage/stage.js
@@ -0,0 +1,76 @@
+/*
+ * Beamer Viewer, a web-based PDF presentation viewer
+ * Copyright (C) 2018 Pacien TRAN-GIRARD
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+"use strict";
+
+class Stage {
+ constructor(onReady, onNext, onPrevious) {
+ this.audienceScreen = null;
+ this.presenterScreen = null;
+
+ this.projector = window.open(window.location.href, "_blank", "toolbar=0,location=0,menubar=0");
+ if (this.projector == null)
+ alert("Please allow pop-ups, then refresh this page.");
+
+ const self = this;
+ this.projector.addEventListener("load", function() {
+ self.audienceScreen = new Screen(self.projector, false, false);
+ self.presenterScreen = new Screen(window, true, true);
+ self._watchDetach();
+ onReady();
+ });
+
+ this.eventHandlers = [
+ new KeyboardEventHandler(onNext, onPrevious),
+ new MouseClickEventHandler(onNext, onPrevious),
+ new TouchSwipeEventHandler(onNext, onPrevious)
+ ];
+
+ this._registerEventHandler(window);
+ this._registerEventHandler(this.projector);
+ }
+
+ setPage(page) {
+ this.audienceScreen.setPage(page);
+ this.presenterScreen.setPage(page);
+ }
+
+ _registerEventHandler(window) {
+ if (window == null) return;
+
+ this.eventHandlers.forEach(function(eventHandler) {
+ eventHandler.register(window);
+ });
+ }
+
+ _watchDetach() {
+ const self = this;
+ window.addEventListener("beforeunload", function() {
+ self._setMessage(self.projector, "Controller detached");
+ });
+
+ this.projector.addEventListener("beforeunload", function() {
+ self._setMessage(window, "Viewer detached");
+ });
+ }
+
+ _setMessage(window, message) {
+ const messageBar = window.document.getElementById("message");
+ messageBar.textContent = message;
+ }
+}
diff --git a/beamer/viewer/viewer.css b/beamer/viewer/viewer.css
new file mode 100644
index 0000000..a69ddb2
--- /dev/null
+++ b/beamer/viewer/viewer.css
@@ -0,0 +1,116 @@
+/*
+ * Beamer Viewer, a web-based PDF presentation viewer
+ * Copyright (C) 2018 Pacien TRAN-GIRARD
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+html, body {
+ background-color: black;
+ color: white;
+ font-family: sans-serif;
+ overflow: hidden;
+ touch-action: none;
+ height: 100%;
+}
+
+a {
+ color: white;
+}
+
+header > h1 {
+ display: inline-block;
+ margin: 0 0.5rem 0 0;
+}
+
+header span {
+ font-size: 1.25rem;
+}
+
+#offlineCapable {
+ visibility: hidden;
+}
+
+#welcomeScreen {
+ max-height: 100%;
+ min-width: 20rem;
+ overflow: auto;
+ padding: 1rem;
+ box-sizing: border-box;
+}
+
+#welcomeScreen > div {
+ margin-bottom: 4rem;
+}
+
+#welcomeScreen > div:last-child {
+ margin-bottom: 1rem;
+}
+
+#welcomeScreen table {
+ width: 100%;
+ border-collapse: collapse;
+}
+
+#welcomeScreen table td {
+ text-align: center;
+ border: 1px solid white;
+ width: 50%;
+ height: 8rem;
+}
+
+#welcomeScreen ul {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+
+#welcomeScreen li {
+ display: inline;
+}
+
+#welcomeScreen li + li::before {
+ content: " • ";
+}
+
+#fileInput {
+ width: 100%;
+}
+
+.centered {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translateX(-50%) translateY(-50%);
+}
+
+.notification {
+ position: absolute;
+ bottom: 0;
+ left: 50%;
+ transform: translateX(-50%);
+ padding: 0.5rem 1rem;
+ border-radius: 1rem 1rem 0 0;
+ background-color: black;
+ font-size: 1.6rem;
+}
+
+.notification:empty {
+ display: none;
+}
+
+.warning {
+ font-weight: bold;
+ color: orangered;
+}
diff --git a/beamer/viewer/viewer.js b/beamer/viewer/viewer.js
new file mode 100644
index 0000000..414ff1c
--- /dev/null
+++ b/beamer/viewer/viewer.js
@@ -0,0 +1,65 @@
+/*
+ * Beamer Viewer, a web-based PDF presentation viewer
+ * Copyright (C) 2018 Pacien TRAN-GIRARD
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+"use strict";
+
+class Viewer {
+ constructor() {
+ this.fileInput = document.getElementById("fileInput");
+ this._listenForInput();
+ }
+
+ load(source) {
+ pdfjsLib.getDocument(source).then(function(pdf) {
+ const presentation = new Presentation(pdf);
+ }).catch(function(error) {
+ console.error(error);
+ window.alert("Error while loading presentation:\n\n" + error.message);
+ window.location.href = window.location.pathname; // reload without "?file=..."
+ });
+ }
+
+ _readFile(file) {
+ const fileReader = new FileReader();
+ const self = this;
+ fileReader.onload = function() {
+ const byteArray = new Uint8Array(this.result);
+ self.load(byteArray);
+ }
+
+ fileReader.readAsArrayBuffer(file);
+ }
+
+ _listenForInput() {
+ const self = this;
+ fileInput.addEventListener("change", function(event) {
+ self._readFile(event.target.files[0]);
+ });
+
+ document.body.addEventListener("drop", function(event) {
+ event.preventDefault();
+ event.stopPropagation();
+ self._readFile(event.dataTransfer.files[0]);
+ });
+
+ document.body.addEventListener("dragover", function(event) {
+ event.preventDefault();
+ event.stopPropagation();
+ });
+ }
+}
--
cgit v1.2.3