commit
523201bb18
11 changed files with 392 additions and 58 deletions
|
@ -62,6 +62,7 @@
|
|||
"core-js": "^3.6.5",
|
||||
"date-fns": "^2.16.1",
|
||||
"epubjs": "^0.3.85",
|
||||
"pdfjs-dist": "2.4.456",
|
||||
"fast-text-encoding": "^1.0.3",
|
||||
"flv.js": "^1.5.0",
|
||||
"headroom.js": "^0.12.0",
|
||||
|
@ -325,6 +326,7 @@
|
|||
"src/libraries/scroller.js",
|
||||
"src/plugins/backdropScreensaver/plugin.js",
|
||||
"src/plugins/bookPlayer/plugin.js",
|
||||
"src/plugins/pdfPlayer/plugin.js",
|
||||
"src/plugins/bookPlayer/tableOfContents.js",
|
||||
"src/plugins/chromecastPlayer/chromecastHelper.js",
|
||||
"src/plugins/photoPlayer/plugin.js",
|
||||
|
|
|
@ -95,6 +95,11 @@ _define('epubjs', function () {
|
|||
return epubjs;
|
||||
});
|
||||
|
||||
const pdfjs = require('pdfjs-dist/build/pdf');
|
||||
_define('pdfjs', function () {
|
||||
return pdfjs;
|
||||
});
|
||||
|
||||
// page.js
|
||||
const page = require('page');
|
||||
_define('page', function() {
|
||||
|
|
|
@ -172,7 +172,6 @@ function supportsCue() {
|
|||
function onAppVisible() {
|
||||
if (isHidden) {
|
||||
isHidden = false;
|
||||
console.debug('triggering app resume event');
|
||||
events.trigger(appHost, 'resume');
|
||||
}
|
||||
}
|
||||
|
@ -180,7 +179,6 @@ function onAppVisible() {
|
|||
function onAppHidden() {
|
||||
if (!isHidden) {
|
||||
isHidden = true;
|
||||
console.debug('app is hidden');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
"plugins/bookPlayer/plugin",
|
||||
"plugins/youtubePlayer/plugin",
|
||||
"plugins/backdropScreensaver/plugin",
|
||||
"plugins/pdfPlayer/plugin",
|
||||
"plugins/logoScreensaver/plugin",
|
||||
"plugins/sessionPlayer/plugin",
|
||||
"plugins/chromecastPlayer/plugin"
|
||||
|
|
|
@ -25,8 +25,9 @@ export class BookPlayer {
|
|||
}
|
||||
|
||||
play(options) {
|
||||
this._progress = 0;
|
||||
this._loaded = false;
|
||||
this.progress = 0;
|
||||
this.cancellationToken = false;
|
||||
this.loaded = false;
|
||||
|
||||
loading.show();
|
||||
const elem = this.createMediaElement();
|
||||
|
@ -36,35 +37,35 @@ export class BookPlayer {
|
|||
stop() {
|
||||
this.unbindEvents();
|
||||
|
||||
const elem = this._mediaElement;
|
||||
const tocElement = this._tocElement;
|
||||
const rendition = this._rendition;
|
||||
const elem = this.mediaElement;
|
||||
const tocElement = this.tocElement;
|
||||
const rendition = this.rendition;
|
||||
|
||||
if (elem) {
|
||||
dialogHelper.close(elem);
|
||||
this._mediaElement = null;
|
||||
this.mediaElement = null;
|
||||
}
|
||||
|
||||
if (tocElement) {
|
||||
tocElement.destroy();
|
||||
this._tocElement = null;
|
||||
this.tocElement = null;
|
||||
}
|
||||
|
||||
if (rendition) {
|
||||
rendition.destroy();
|
||||
}
|
||||
|
||||
// Hide loader in case player was not fully loaded yet
|
||||
// hide loader in case player was not fully loaded yet
|
||||
loading.hide();
|
||||
this._cancellationToken.shouldCancel = true;
|
||||
this.cancellationToken = true;
|
||||
}
|
||||
|
||||
currentItem() {
|
||||
return this._currentItem;
|
||||
return this.item;
|
||||
}
|
||||
|
||||
currentTime() {
|
||||
return this._progress * 1000;
|
||||
return this.progress * 1000;
|
||||
}
|
||||
|
||||
duration() {
|
||||
|
@ -96,12 +97,10 @@ export class BookPlayer {
|
|||
|
||||
onWindowKeyUp(e) {
|
||||
const key = keyboardnavigation.getKeyName(e);
|
||||
|
||||
// TODO: depending on the event this can be the document or the rendition itself
|
||||
const rendition = this._rendition || this;
|
||||
const rendition = this.rendition;
|
||||
const book = rendition.book;
|
||||
|
||||
if (this._loaded === false) return;
|
||||
if (!this.loaded) return;
|
||||
switch (key) {
|
||||
case 'l':
|
||||
case 'ArrowRight':
|
||||
|
@ -114,9 +113,9 @@ export class BookPlayer {
|
|||
book.package.metadata.direction === 'rtl' ? rendition.next() : rendition.prev();
|
||||
break;
|
||||
case 'Escape':
|
||||
if (this._tocElement) {
|
||||
if (this.tocElement) {
|
||||
// Close table of contents on ESC if it is open
|
||||
this._tocElement.destroy();
|
||||
this.tocElement.destroy();
|
||||
} else {
|
||||
// Otherwise stop the entire book player
|
||||
this.stop();
|
||||
|
@ -130,7 +129,7 @@ export class BookPlayer {
|
|||
}
|
||||
|
||||
bindMediaElementEvents() {
|
||||
const elem = this._mediaElement;
|
||||
const elem = this.mediaElement;
|
||||
|
||||
elem.addEventListener('close', this.onDialogClosed, {once: true});
|
||||
elem.querySelector('#btnBookplayerExit').addEventListener('click', this.onDialogClosed, {once: true});
|
||||
|
@ -147,11 +146,11 @@ export class BookPlayer {
|
|||
document.addEventListener('keyup', this.onWindowKeyUp);
|
||||
|
||||
// FIXME: I don't really get why document keyup event is not triggered when epub is in focus
|
||||
this._rendition.on('keyup', this.onWindowKeyUp);
|
||||
this.rendition.on('keyup', this.onWindowKeyUp);
|
||||
}
|
||||
|
||||
unbindMediaElementEvents() {
|
||||
const elem = this._mediaElement;
|
||||
const elem = this.mediaElement;
|
||||
|
||||
elem.removeEventListener('close', this.onDialogClosed);
|
||||
elem.querySelector('#btnBookplayerExit').removeEventListener('click', this.onDialogClosed);
|
||||
|
@ -163,20 +162,20 @@ export class BookPlayer {
|
|||
}
|
||||
|
||||
unbindEvents() {
|
||||
if (this._mediaElement) {
|
||||
if (this.mediaElement) {
|
||||
this.unbindMediaElementEvents();
|
||||
}
|
||||
|
||||
document.removeEventListener('keyup', this.onWindowKeyUp);
|
||||
|
||||
if (this._rendition) {
|
||||
this._rendition.off('keyup', this.onWindowKeyUp);
|
||||
if (this.rendition) {
|
||||
this.rendition.off('keyup', this.onWindowKeyUp);
|
||||
}
|
||||
}
|
||||
|
||||
openTableOfContents() {
|
||||
if (this._loaded) {
|
||||
this._tocElement = new TableOfContents(this);
|
||||
if (this.loaded) {
|
||||
this.tocElement = new TableOfContents(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,7 +190,7 @@ export class BookPlayer {
|
|||
}
|
||||
|
||||
createMediaElement() {
|
||||
let elem = this._mediaElement;
|
||||
let elem = this.mediaElement;
|
||||
if (elem) {
|
||||
return elem;
|
||||
}
|
||||
|
@ -207,8 +206,6 @@ export class BookPlayer {
|
|||
removeOnClose: true
|
||||
});
|
||||
|
||||
elem.id = 'bookPlayer';
|
||||
|
||||
let html = '';
|
||||
|
||||
if (browser.mobile) {
|
||||
|
@ -226,13 +223,13 @@ export class BookPlayer {
|
|||
html += '<div class="button-wrapper bottom-button"><button id="btnBookplayerNext" is="paper-icon-button-light" class="autoSize bookplayerButton hide-mouse-idle-tv">Next <i class="material-icons bookplayerButtonIcon navigate_next"></i></button></div>';
|
||||
}
|
||||
|
||||
elem.id = 'bookPlayer';
|
||||
elem.innerHTML = html;
|
||||
|
||||
dialogHelper.open(elem);
|
||||
}
|
||||
|
||||
this._mediaElement = elem;
|
||||
|
||||
this.mediaElement = elem;
|
||||
return elem;
|
||||
}
|
||||
|
||||
|
@ -253,7 +250,7 @@ export class BookPlayer {
|
|||
|
||||
setCurrentSrc(elem, options) {
|
||||
const item = options.items[0];
|
||||
this._currentItem = item;
|
||||
this.item = item;
|
||||
this.streamInfo = {
|
||||
started: true,
|
||||
ended: false,
|
||||
|
@ -271,13 +268,8 @@ export class BookPlayer {
|
|||
const book = epubjs(downloadHref, {openAs: 'epub'});
|
||||
const rendition = this.render('viewer', book);
|
||||
|
||||
this._currentSrc = downloadHref;
|
||||
this._rendition = rendition;
|
||||
const cancellationToken = {
|
||||
shouldCancel: false
|
||||
};
|
||||
|
||||
this._cancellationToken = cancellationToken;
|
||||
this.currentSrc = downloadHref;
|
||||
this.rendition = rendition;
|
||||
|
||||
return rendition.display().then(() => {
|
||||
const epubElem = document.querySelector('.epub-container');
|
||||
|
@ -285,10 +277,8 @@ export class BookPlayer {
|
|||
|
||||
this.bindEvents();
|
||||
|
||||
return this._rendition.book.locations.generate(1024).then(async () => {
|
||||
if (cancellationToken.shouldCancel) {
|
||||
return reject();
|
||||
}
|
||||
return this.rendition.book.locations.generate(1024).then(async () => {
|
||||
if (this.cancellationToken) reject();
|
||||
|
||||
const percentageTicks = options.startPositionTicks / 10000000;
|
||||
if (percentageTicks !== 0.0) {
|
||||
|
@ -296,15 +286,14 @@ export class BookPlayer {
|
|||
await rendition.display(resumeLocation);
|
||||
}
|
||||
|
||||
this._loaded = true;
|
||||
this.loaded = true;
|
||||
epubElem.style.display = 'block';
|
||||
rendition.on('relocated', (locations) => {
|
||||
this._progress = book.locations.percentageFromCfi(locations.start.cfi);
|
||||
this.progress = book.locations.percentageFromCfi(locations.start.cfi);
|
||||
events.trigger(this, 'timeupdate');
|
||||
});
|
||||
|
||||
loading.hide();
|
||||
|
||||
return resolve();
|
||||
});
|
||||
}, () => {
|
||||
|
@ -320,7 +309,7 @@ export class BookPlayer {
|
|||
}
|
||||
|
||||
canPlayItem(item) {
|
||||
if (item.Path && (item.Path.endsWith('epub'))) {
|
||||
if (item.Path && item.Path.endsWith('epub')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@ import dialogHelper from 'dialogHelper';
|
|||
|
||||
export default class TableOfContents {
|
||||
constructor(bookPlayer) {
|
||||
this._bookPlayer = bookPlayer;
|
||||
this._rendition = bookPlayer._rendition;
|
||||
this.bookPlayer = bookPlayer;
|
||||
this.rendition = bookPlayer.rendition;
|
||||
|
||||
this.onDialogClosed = this.onDialogClosed.bind(this);
|
||||
|
||||
|
@ -11,24 +11,24 @@ export default class TableOfContents {
|
|||
}
|
||||
|
||||
destroy() {
|
||||
const elem = this._elem;
|
||||
const elem = this.elem;
|
||||
if (elem) {
|
||||
this.unbindEvents();
|
||||
dialogHelper.close(elem);
|
||||
}
|
||||
|
||||
this._bookPlayer._tocElement = null;
|
||||
this.bookPlayer.tocElement = null;
|
||||
}
|
||||
|
||||
bindEvents() {
|
||||
const elem = this._elem;
|
||||
const elem = this.elem;
|
||||
|
||||
elem.addEventListener('close', this.onDialogClosed, {once: true});
|
||||
elem.querySelector('.btnBookplayerTocClose').addEventListener('click', this.onDialogClosed, {once: true});
|
||||
}
|
||||
|
||||
unbindEvents() {
|
||||
const elem = this._elem;
|
||||
const elem = this.elem;
|
||||
|
||||
elem.removeEventListener('close', this.onDialogClosed);
|
||||
elem.querySelector('.btnBookplayerTocClose').removeEventListener('click', this.onDialogClosed);
|
||||
|
@ -52,7 +52,7 @@ export default class TableOfContents {
|
|||
}
|
||||
|
||||
createMediaElement() {
|
||||
const rendition = this._rendition;
|
||||
const rendition = this.rendition;
|
||||
|
||||
const elem = dialogHelper.createDialog({
|
||||
size: 'small',
|
||||
|
@ -68,7 +68,8 @@ export default class TableOfContents {
|
|||
tocHtml += '<ul class="toc">';
|
||||
rendition.book.navigation.forEach((chapter) => {
|
||||
tocHtml += '<li>';
|
||||
// Remove '../' from href
|
||||
|
||||
// remove parent directory reference from href to fix certain books
|
||||
const link = chapter.href.startsWith('../') ? chapter.href.substr(3) : chapter.href;
|
||||
tocHtml += `<a href="${rendition.book.path.directory + link}">${chapter.label}</a>`;
|
||||
tocHtml += '</li>';
|
||||
|
@ -83,7 +84,7 @@ export default class TableOfContents {
|
|||
this.destroy();
|
||||
});
|
||||
|
||||
this._elem = elem;
|
||||
this.elem = elem;
|
||||
|
||||
this.bindEvents();
|
||||
dialogHelper.open(elem);
|
||||
|
|
306
src/plugins/pdfPlayer/plugin.js
Normal file
306
src/plugins/pdfPlayer/plugin.js
Normal file
|
@ -0,0 +1,306 @@
|
|||
import loading from 'loading';
|
||||
import keyboardnavigation from 'keyboardnavigation';
|
||||
import dialogHelper from 'dialogHelper';
|
||||
import dom from 'dom';
|
||||
import appRouter from 'appRouter';
|
||||
import events from 'events';
|
||||
import 'css!./style';
|
||||
import 'material-icons';
|
||||
import 'paper-icon-button-light';
|
||||
|
||||
export class PdfPlayer {
|
||||
constructor() {
|
||||
this.name = 'PDF Player';
|
||||
this.type = 'mediaplayer';
|
||||
this.id = 'pdfplayer';
|
||||
this.priority = 1;
|
||||
|
||||
this.onDialogClosed = this.onDialogClosed.bind(this);
|
||||
this.onWindowKeyUp = this.onWindowKeyUp.bind(this);
|
||||
this.onTouchStart = this.onTouchStart.bind(this);
|
||||
}
|
||||
|
||||
play(options) {
|
||||
this.progress = 0;
|
||||
this.loaded = false;
|
||||
this.cancellationToken = false;
|
||||
this.pages = {};
|
||||
|
||||
loading.show();
|
||||
|
||||
const elem = this.createMediaElement();
|
||||
return this.setCurrentSrc(elem, options);
|
||||
}
|
||||
|
||||
stop() {
|
||||
this.unbindEvents();
|
||||
|
||||
const elem = this.mediaElement;
|
||||
if (elem) {
|
||||
dialogHelper.close(elem);
|
||||
this.mediaElement = null;
|
||||
}
|
||||
|
||||
// hide loading animation
|
||||
loading.hide();
|
||||
|
||||
// cancel page render
|
||||
this.cancellationToken = true;
|
||||
}
|
||||
|
||||
currentItem() {
|
||||
return this.item;
|
||||
}
|
||||
|
||||
currentTime() {
|
||||
return this.progress;
|
||||
}
|
||||
|
||||
duration() {
|
||||
return this.book ? this.book.numPages : 0;
|
||||
}
|
||||
|
||||
volume() {
|
||||
return 100;
|
||||
}
|
||||
|
||||
isMuted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
paused() {
|
||||
return false;
|
||||
}
|
||||
|
||||
seekable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
onWindowKeyUp(e) {
|
||||
const key = keyboardnavigation.getKeyName(e);
|
||||
|
||||
if (!this.loaded) return;
|
||||
switch (key) {
|
||||
case 'l':
|
||||
case 'ArrowRight':
|
||||
case 'Right':
|
||||
this.next();
|
||||
break;
|
||||
case 'j':
|
||||
case 'ArrowLeft':
|
||||
case 'Left':
|
||||
this.previous();
|
||||
break;
|
||||
case 'Escape':
|
||||
this.stop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
onTouchStart(e) {
|
||||
if (!this.loaded || !e.touches || e.touches.length === 0) return;
|
||||
if (e.touches[0].clientX < dom.getWindowSize().innerWidth / 2) {
|
||||
this.previous();
|
||||
} else {
|
||||
this.next();
|
||||
}
|
||||
}
|
||||
|
||||
onDialogClosed() {
|
||||
this.stop();
|
||||
}
|
||||
|
||||
bindMediaElementEvents() {
|
||||
const elem = this.mediaElement;
|
||||
|
||||
elem.addEventListener('close', this.onDialogClosed, {once: true});
|
||||
elem.querySelector('.btnExit').addEventListener('click', this.onDialogClosed, {once: true});
|
||||
}
|
||||
|
||||
bindEvents() {
|
||||
this.bindMediaElementEvents();
|
||||
|
||||
document.addEventListener('keyup', this.onWindowKeyUp);
|
||||
document.addEventListener('touchstart', this.onTouchStart);
|
||||
}
|
||||
|
||||
unbindMediaElementEvents() {
|
||||
const elem = this.mediaElement;
|
||||
|
||||
elem.removeEventListener('close', this.onDialogClosed);
|
||||
elem.querySelector('.btnExit').removeEventListener('click', this.onDialogClosed);
|
||||
}
|
||||
|
||||
unbindEvents() {
|
||||
if (this.mediaElement) {
|
||||
this.unbindMediaElementEvents();
|
||||
}
|
||||
|
||||
document.removeEventListener('keyup', this.onWindowKeyUp);
|
||||
document.removeEventListener('touchstart', this.onTouchStart);
|
||||
}
|
||||
|
||||
createMediaElement() {
|
||||
let elem = this.mediaElement;
|
||||
if (elem) {
|
||||
return elem;
|
||||
}
|
||||
|
||||
elem = document.getElementById('pdfPlayer');
|
||||
if (!elem) {
|
||||
elem = dialogHelper.createDialog({
|
||||
exitAnimationDuration: 400,
|
||||
size: 'fullscreen',
|
||||
autoFocus: false,
|
||||
scrollY: false,
|
||||
exitAnimation: 'fadeout',
|
||||
removeOnClose: true
|
||||
});
|
||||
|
||||
let html = '';
|
||||
html += '<canvas id="canvas"></canvas>';
|
||||
html += '<div class="actionButtons">';
|
||||
html += '<button is="paper-icon-button-light" class="autoSize btnExit" tabindex="-1"><i class="material-icons actionButtonIcon close"></i></button>';
|
||||
html += '</div>';
|
||||
|
||||
elem.id = 'pdfPlayer';
|
||||
elem.innerHTML = html;
|
||||
|
||||
dialogHelper.open(elem);
|
||||
}
|
||||
|
||||
this.mediaElement = elem;
|
||||
return elem;
|
||||
}
|
||||
|
||||
setCurrentSrc(elem, options) {
|
||||
const item = options.items[0];
|
||||
|
||||
this.item = item;
|
||||
this.streamInfo = {
|
||||
started: true,
|
||||
ended: false,
|
||||
mediaSource: {
|
||||
Id: item.Id
|
||||
}
|
||||
};
|
||||
|
||||
const serverId = item.ServerId;
|
||||
const apiClient = window.connectionManager.getApiClient(serverId);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
import('pdfjs').then(({default: pdfjs}) => {
|
||||
const downloadHref = apiClient.getItemDownloadUrl(item.Id);
|
||||
|
||||
this.bindEvents();
|
||||
pdfjs.GlobalWorkerOptions.workerSrc = appRouter.baseUrl() + '/libraries/pdf.worker.js';
|
||||
|
||||
const downloadTask = pdfjs.getDocument(downloadHref);
|
||||
downloadTask.promise.then(book => {
|
||||
if (this.cancellationToken) return;
|
||||
this.book = book;
|
||||
this.loaded = true;
|
||||
|
||||
const percentageTicks = options.startPositionTicks / 10000;
|
||||
if (percentageTicks !== 0) {
|
||||
this.loadPage(percentageTicks);
|
||||
this.progress = percentageTicks;
|
||||
} else {
|
||||
this.loadPage(1);
|
||||
}
|
||||
|
||||
return resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
next() {
|
||||
if (this.progress === this.duration() - 1) return;
|
||||
this.loadPage(this.progress + 2);
|
||||
this.progress = this.progress + 1;
|
||||
}
|
||||
|
||||
previous() {
|
||||
if (this.progress === 0) return;
|
||||
this.loadPage(this.progress);
|
||||
this.progress = this.progress - 1;
|
||||
}
|
||||
|
||||
replaceCanvas(canvas) {
|
||||
const old = document.getElementById('canvas');
|
||||
|
||||
canvas.id = 'canvas';
|
||||
old.parentNode.replaceChild(canvas, old);
|
||||
}
|
||||
|
||||
loadPage(number) {
|
||||
const prefix = 'page';
|
||||
const pad = 2;
|
||||
|
||||
// generate list of cached pages by padding the requested page on both sides
|
||||
const pages = [prefix + number];
|
||||
for (let i = 1; i <= pad; i++) {
|
||||
if (number - i > 0) pages.push(prefix + (number - i));
|
||||
if (number + i < this.duration()) pages.push(prefix + (number + i));
|
||||
}
|
||||
|
||||
// load any missing pages in the cache
|
||||
for (const page of pages) {
|
||||
if (!this.pages[page]) {
|
||||
this.pages[page] = document.createElement('canvas');
|
||||
this.renderPage(this.pages[page], parseInt(page.substr(4)));
|
||||
}
|
||||
}
|
||||
|
||||
// show the requested page
|
||||
this.replaceCanvas(this.pages[prefix + number], number);
|
||||
|
||||
// delete all pages outside the cache area
|
||||
for (const page in this.pages) {
|
||||
if (!pages.includes(page)) {
|
||||
delete this.pages[page];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
renderPage(canvas, number) {
|
||||
this.book.getPage(number).then(page => {
|
||||
events.trigger(this, 'timeupdate');
|
||||
|
||||
const original = page.getViewport({ scale: 1 });
|
||||
const context = canvas.getContext('2d');
|
||||
|
||||
const widthRatio = dom.getWindowSize().innerWidth / original.width;
|
||||
const heightRatio = dom.getWindowSize().innerHeight / original.height;
|
||||
const scale = Math.min(heightRatio, widthRatio);
|
||||
const viewport = page.getViewport({ scale: scale });
|
||||
|
||||
canvas.width = viewport.width;
|
||||
canvas.height = viewport.height;
|
||||
const renderContext = {
|
||||
canvasContext: context,
|
||||
viewport: viewport
|
||||
};
|
||||
|
||||
const renderTask = page.render(renderContext);
|
||||
renderTask.promise.then(() => {
|
||||
loading.hide();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
canPlayMediaType(mediaType) {
|
||||
return (mediaType || '').toLowerCase() === 'book';
|
||||
}
|
||||
|
||||
canPlayItem(item) {
|
||||
if (item.Path && item.Path.endsWith('pdf')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export default PdfPlayer;
|
25
src/plugins/pdfPlayer/style.css
Normal file
25
src/plugins/pdfPlayer/style.css
Normal file
|
@ -0,0 +1,25 @@
|
|||
#pdfPlayer {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: none;
|
||||
z-index: 100;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
#canvas {
|
||||
display: block;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.actionButtons {
|
||||
right: 0.5vh;
|
||||
top: 0.5vh;
|
||||
z-index: 1002;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.actionButtonIcon {
|
||||
color: black;
|
||||
opacity: 0.7;
|
||||
}
|
|
@ -495,6 +495,7 @@ function initClient() {
|
|||
'flvjs',
|
||||
'jstree',
|
||||
'epubjs',
|
||||
'pdfjs',
|
||||
'jQuery',
|
||||
'hlsjs',
|
||||
'howler',
|
||||
|
|
|
@ -12,7 +12,8 @@ const Assets = [
|
|||
'libass-wasm/dist/js/subtitles-octopus-worker.wasm',
|
||||
'libass-wasm/dist/js/subtitles-octopus-worker-legacy.js',
|
||||
'libass-wasm/dist/js/subtitles-octopus-worker-legacy.data',
|
||||
'libass-wasm/dist/js/subtitles-octopus-worker-legacy.js.mem'
|
||||
'libass-wasm/dist/js/subtitles-octopus-worker-legacy.js.mem',
|
||||
'pdfjs-dist/build/pdf.worker.js'
|
||||
];
|
||||
|
||||
const LibarchiveWasm = [
|
||||
|
|
|
@ -8315,6 +8315,11 @@ pbkdf2@^3.0.3:
|
|||
safe-buffer "^5.0.1"
|
||||
sha.js "^2.4.8"
|
||||
|
||||
pdfjs-dist@2.4.456:
|
||||
version "2.4.456"
|
||||
resolved "https://registry.yarnpkg.com/pdfjs-dist/-/pdfjs-dist-2.4.456.tgz#0eaad2906cda866bbb393e79a0e5b4e68bd75520"
|
||||
integrity sha512-yckJEHq3F48hcp6wStEpbN9McOj328Ib09UrBlGAKxvN2k+qYPN5iq6TH6jD1C0pso7zTep+g/CKsYgdrQd5QA==
|
||||
|
||||
pend@~1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue