[FIX] website_slides: outdated pdfjs API use

Apparently a PDF Document used to *be* a promise (a "thenable") but
that's not the case anymore. The loading promise has to be deref'd
explicitely. This is also the case for `page.render`, which is not a
thenable anymore.

Furthermore, the API seems to have changed to favor parameter
objects (getViewport) and setting callbacks (onPassword) rather than
having lots of positional parameters.

Finally, remove apparently long dead `disableWorker` feature in
`PDFSlidesViewer`, although really the entire thing should be
rewritten in modern javascript.

Part-of: odoo/odoo#100067
This commit is contained in:
Xavier Morel
2022-10-26 09:07:34 +02:00
parent 55d9f318fb
commit 542cb1dc21
3 changed files with 48 additions and 67 deletions
@@ -8,10 +8,10 @@
// !!!!!!!!! use window.pdfjsLib and not pdfjsLib
var PDFSlidesViewer = (function(){
function PDFSlidesViewer(pdf_url, $canvas, disableWorker){
function PDFSlidesViewer(pdf_url, $canvas) {
// pdf variables
this.pdf = null;
this.pdf_url = pdf_url || false;
this.pdf_url = pdf_url;
this.pdf_page_total = 0;
this.pdf_page_current = 1; // default is the first page
this.pdf_zoom = 1; // 1 = scale to fit to available space
@@ -21,32 +21,16 @@ var PDFSlidesViewer = (function(){
//canvas
this.canvas = $canvas;
this.canvas_context = $canvas.getContext('2d');
// PDF JS business
/**
* Disable the web worker and run all code on the main thread. This will happen
* automatically if the browser doesn't support workers or sending typed arrays
* to workers.
* @var {boolean}
*
* disableWorker should be 'true' if the document came from another origin than the
* page (typically the 'embed case').
* @see http://en.wikipedia.org/wiki/Cross-origin_resource_sharing.
* this is equivalent to the use_cors option in openerpframework.js
*/
};
}
/**
* Load the PDF document
* @param (optional) url : the url of the document to load
*/
PDFSlidesViewer.prototype.loadDocument = function(url) {
var self = this;
var pdf_url = url || this.pdf_url;
return window.pdfjsLib.getDocument(pdf_url).then(function (file_content) {
self.pdf = file_content;
self.pdf_page_total = file_content.numPages;
return file_content;
});
PDFSlidesViewer.prototype.loadDocument = async function() {
const file_content = await window.pdfjsLib.getDocument(this.pdf_url).promise;
this.pdf = file_content;
this.pdf_page_total = file_content.numPages;
return file_content;
};
/**
@@ -19,7 +19,7 @@ $(function () {
this.defaultpage = parseInt($viewer.find('#PDFSlideViewer').data('defaultpage'));
this.canvas = $viewer.find('canvas')[0];
this.pdf_viewer = new PDFSlidesViewer(this.slide_url, this.canvas, true);
this.pdf_viewer = new PDFSlidesViewer(this.slide_url, this.canvas);
this.pdf_viewer.loadDocument().then(function () {
self.on_loaded_file();
});
@@ -1,6 +1,6 @@
/** @odoo-module **/
import { qweb as QWeb, _t } from 'web.core';
import {_t, qweb as QWeb} from 'web.core';
import Dialog from 'web.Dialog';
import publicWidget from 'web.public.widget';
import utils from 'web.utils';
@@ -540,7 +540,6 @@ var SlideUploadDialog = Dialog.extend({
var $input = $(ev.currentTarget);
var preventOnchange = $input.data('preventOnchange');
var $preview = self.$('#slide-image');
var file = ev.target.files[0];
if (!file) {
@@ -565,27 +564,22 @@ var SlideUploadDialog = Dialog.extend({
return;
}
utils.getDataURLFromFile(file).then(function (buffer) {
if (isImage) {
$preview.attr('src', buffer);
}
buffer = buffer.split(',')[1];
self.file.data = buffer;
self._showPreviewColumn();
});
if (file.type === 'application/pdf') {
const preview = document.getElementById("slide-image");
if (file.type !== 'application/pdf') {
utils.getDataURLFromFile(file).then(dataURL => {
if (isImage) {
preview.src = dataURL;
}
this.file.data = dataURL.split(',', 1)[1];
this._showPreviewColumn();
});
} else {
var ArrayReader = new FileReader();
this.set('can_submit_form', false);
// file read as ArrayBuffer for pdfjsLib get_Document API
ArrayReader.readAsArrayBuffer(file);
ArrayReader.onload = function (evt) {
ArrayReader.onload = async function (evt) {
var buffer = evt.target.result;
var passwordNeeded = function () {
self._alertDisplay(_t("You can not upload password protected file."));
self._fileReset();
self.set('can_submit_form', true);
};
/**
* The following line fixes pdfjsLib 'Util' global variable.
* This is (most likely) related to #32181 which lazy loads most assets.
@@ -604,30 +598,33 @@ var SlideUploadDialog = Dialog.extend({
* cause much harm.
*/
window.Util = window.pdfjsLib.Util;
window.pdfjsLib.getDocument(new Uint8Array(buffer), null, passwordNeeded).then(function getPdf(pdf) {
self._formSetFieldValue('duration', (pdf._pdfInfo.numPages || 0) * 5);
pdf.getPage(1).then(function getFirstPage(page) {
var scale = 1;
var viewport = page.getViewport(scale);
var canvas = document.getElementById('data_canvas');
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context
page.render({
canvasContext: context,
viewport: viewport
}).then(function () {
var imageData = self.$('#data_canvas')[0].toDataURL();
$preview.attr('src', imageData);
if (loaded) {
self.set('can_submit_form', true);
}
loaded = true;
self._showPreviewColumn();
});
});
});
const pdfTask = window.pdfjsLib.getDocument(new Uint8Array(buffer));
pdfTask.onPassword = () => {
this._alertDisplay(_t("You can not upload password protected file."));
this._fileReset();
this.set('can_submit_form', true);
// fixme: throw?
};
const pdf = await pdfTask.promise;
self._formSetFieldValue('duration', (pdf.numPages || 0) * 5);
const page = await pdf.getPage(1)
var viewport = page.getViewport({scale: 1});
var canvas = document.getElementById('data_canvas');
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context
await page.render({
canvasContext: context,
viewport: viewport
}).promise;
preview.src = canvas.toDataURL();
if (loaded) {
self.set('can_submit_form', true);
}
loaded = true;
self._showPreviewColumn();
};
}