[REF] web,*: hide buttons that doesn't work in webviews

Some features of the PDF.js library doesn't work in the
webview of the mobile apps.

Initially 'window.print' is defined as an empty function in
webviews unlike browsers where it is already ready.
After that, PDF.js needs to monkey patch 'window.print' and
saves a reference to the original definition, which is not
yet fulfilled in by the mobile app (Java part).
So the print of PDF.js doesn't work in webviews and end
users will need to download the file before printing it.

Regarding the Download button, the 'download' attribute is
not supported by the webview as you can see in:
https://bugs.chromium.org/p/chromium/issues/detail?id=432414
As there's many ways to download a file in Odoo it's not
a big deal to simply hide it in PDF.js.

Because it's quite complicated to fix this, we decided
to hide the features that don't work (Download / Print)
or don't make sense (Open file).

Task-id: 2200168

--
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr

closes odoo/odoo#70375

Related: odoo/enterprise#18134
Signed-off-by: Adrien Dieudonné (adr) <adr@odoo.com>
This commit is contained in:
Odoo's Mergebot
2021-05-07 14:01:44 +02:00
committed by GitHub
9 changed files with 98 additions and 36 deletions
@@ -3530,6 +3530,7 @@ odoo.define('im_livechat.legacy.mail.DocumentViewer', function (require) {
var core = require('web.core');
var Widget = require('web.Widget');
var { hidePDFJSButtons } = require('@web/js/libs/pdfjs');
var QWeb = core.qweb;
@@ -3658,6 +3659,9 @@ var DocumentViewer = Widget.extend({
this.$('.o_viewer_content').html(QWeb.render('im_livechat.legacy.mail.DocumentViewer.Content', {
widget: this
}));
if (this.activeAttachment.fileType === 'application/pdf') {
hidePDFJSButtons(this.$('.o_viewer_content')[0]);
}
this.$('.o_viewer_img').on("load", _.bind(this._onImageLoaded, this));
this.$('[data-toggle="tooltip"]').tooltip({ delay: 0 });
this._reset();
@@ -5,6 +5,8 @@ import useShouldUpdateBasedOnProps from '@mail/component_hooks/use_should_update
import useStore from '@mail/component_hooks/use_store/use_store';
import { link } from '@mail/model/model_field_command';
import { hidePDFJSButtons } from '@web/js/libs/pdfjs';
const { Component, QWeb } = owl;
const { useRef } = owl.hooks;
@@ -53,6 +55,10 @@ class AttachmentViewer extends Component {
* transformation on image visualisation.
*/
this._zoomerRef = useRef('zoomer');
/**
* Reference of the IFRAME node when the attachment is a PDF.
*/
this._iframeViewerPdfRef = useRef('iframeViewerPdf');
/**
* Tracked translate transformations on image visualisation. This is
* not observed with `useStore` because they are used to compute zoomer
@@ -67,6 +73,7 @@ class AttachmentViewer extends Component {
mounted() {
this.el.focus();
this._handleImageLoad();
this._hideUnwantedPdfJsButtons();
document.addEventListener('click', this._onClickGlobal);
}
@@ -75,6 +82,7 @@ class AttachmentViewer extends Component {
*/
patched() {
this._handleImageLoad();
this._hideUnwantedPdfJsButtons();
}
willUnmount() {
@@ -169,6 +177,17 @@ class AttachmentViewer extends Component {
}
}
/**
* @see 'hidePDFJSButtons'
*
* @private
*/
_hideUnwantedPdfJsButtons() {
if (this._iframeViewerPdfRef.el) {
hidePDFJSButtons(this._iframeViewerPdfRef.el);
}
}
/**
* Display the previous attachment in the list of attachments.
*
@@ -46,7 +46,7 @@
</div>
</t>
<t t-if="attachmentViewer.attachment.fileType === 'application/pdf'">
<iframe class="o_AttachmentViewer_view o_AttachmentViewer_viewIframe o_AttachmentViewer_viewPdf" t-att-class="{ 'o-isMobile': env.messaging.device.isMobile }" t-att-src="attachmentViewer.attachment.defaultSource"/>
<iframe class="o_AttachmentViewer_view o_AttachmentViewer_viewIframe o_AttachmentViewer_viewPdf" t-ref="iframeViewerPdf" t-att-class="{ 'o-isMobile': env.messaging.device.isMobile }" t-att-src="attachmentViewer.attachment.defaultSource"/>
</t>
<t t-if="attachmentViewer.attachment.isTextFile">
<iframe class="o_AttachmentViewer_view o_AttachmentViewer_viewIframe o_text" t-att-src="attachmentViewer.attachment.defaultSource"/>
@@ -2,6 +2,7 @@
import core from 'web.core';
import Widget from 'web.Widget';
import { hidePDFJSButtons } from '@web/js/libs/pdfjs';
var QWeb = core.qweb;
@@ -74,6 +75,15 @@ var DocumentViewer = Widget.extend({
this.modelName = 'ir.attachment';
this._reset();
},
/**
* Do some actions after the widget is appended to the DOM
* @override
*/
setElement: function () {
const result = this._super(...arguments);
this._hidePdfButtonsIfPresent();
return result;
},
/**
* Open a modal displaying the active attachment
* @override
@@ -101,6 +111,15 @@ var DocumentViewer = Widget.extend({
// Private
//---------------------------------------------------------------------------
/**
* Hide some buttons in PDF.js
* @override
*/
_hidePdfButtonsIfPresent: function () {
if (this.activeAttachment.mimetype === 'application/pdf') {
hidePDFJSButtons(this.el);
}
},
/**
* @private
*/
@@ -137,6 +156,7 @@ var DocumentViewer = Widget.extend({
widget: this
}));
this.$('.o_viewer_img').on("load", _.bind(this._onImageLoaded, this));
this._hidePdfButtonsIfPresent();
this.$('[data-toggle="tooltip"]').tooltip({delay: 0});
this._reset();
},
+1
View File
@@ -388,6 +388,7 @@ This module provides the core of the Odoo Web Client.
'web/static/src/js/libs/fullcalendar.js',
'web/static/src/js/libs/jquery.js',
'web/static/src/js/libs/underscore.js',
'web/static/src/js/libs/pdfjs.js',
'web/static/src/js/libs/popper.js',
'web/static/src/js/libs/zoomodoo.js',
'web/static/src/js/libs/jSignatureCustom.js',
-19
View File
@@ -253,25 +253,6 @@ function getViewerConfiguration() {
function webViewerLoad() {
var config = getViewerConfiguration();
// Start Odoo patch
// Source https://github.com/mozilla/pdf.js/pull/11246 (Detect Android and iOS)
const userAgent = (typeof navigator !== 'undefined' && navigator.userAgent) || '';
const platform = (typeof navigator !== 'undefined' && navigator.platform) || '';
const maxTouchPoints = (typeof navigator !== 'undefined' && navigator.maxTouchPoints) || 1;
const isAndroid = /Android/.test(userAgent);
const isIOS = /\b(iPad|iPhone|iPod)(?=;)/.test(userAgent) || (platform === 'MacIntel' && maxTouchPoints > 1);
// Hide Open Button
config.toolbar.openFile.setAttribute('hidden', 'true');
config.secondaryToolbar.openFileButton.setAttribute('hidden', 'true');
// Hide Download Button
config.toolbar.download.setAttribute('hidden', 'true');
config.secondaryToolbar.downloadButton.setAttribute('hidden', 'true');
if (isAndroid || isIOS) {
// Hide Print Button
config.toolbar.print.setAttribute('hidden', 'true');
config.secondaryToolbar.printButton.setAttribute('hidden', 'true');
}
// End Odoo patch
window.PDFViewerApplication = pdfjsWebApp.PDFViewerApplication;
window.PDFViewerApplicationOptions = pdfjsWebAppOptions.AppOptions;
var event = document.createEvent('CustomEvent');
@@ -25,6 +25,7 @@ var view_dialogs = require('web.view_dialogs');
var field_utils = require('web.field_utils');
var time = require('web.time');
const {ColorpickerDialog} = require('web.Colorpicker');
const { hidePDFJSButtons } = require('@web/js/libs/pdfjs');
let FieldBoolean = deprecatedFields.FieldBoolean;
@@ -2253,13 +2254,6 @@ var FieldPdfViewer = FieldBinaryFile.extend({
// Private
//--------------------------------------------------------------------------
/**
* @private
* @param {DOMElement} iframe
*/
_disableButtons: function (iframe) {
$(iframe).contents().find('button#openFile').hide();
},
/**
* @private
* @param {string} [fileURI] file URI if specified
@@ -2292,7 +2286,6 @@ var FieldPdfViewer = FieldBinaryFile.extend({
$iFrame.on('load', function () {
self.PDFViewerApplication = this.contentWindow.window.PDFViewerApplication;
self._disableButtons(this);
});
if (this.mode === "readonly" && this.value) {
$iFrame.attr('src', this._getURI());
@@ -2309,6 +2302,7 @@ var FieldPdfViewer = FieldBinaryFile.extend({
$selectUpload.removeClass('o_hidden');
}
}
hidePDFJSButtons($iFrame[0]);
},
//--------------------------------------------------------------------------
+45 -1
View File
@@ -1,5 +1,49 @@
/** @odoo-module **/
import config from 'web.config';
/**
* Until we have our own implementation of the /web/static/lib/pdfjs/web/viewer.{html,js,css}
* (currently based on Firefox), this method allows us to hide the buttons that we do not want:
* * "Open File"
* * "Print" (Hidden on mobile)
* * "Download"
*
* @link https://mozilla.github.io/pdf.js/getting_started/
*
* @param {Element} rootElement
*/
export function hidePDFJSButtons(rootElement) {
const cssStyle = document.createElement("style");
cssStyle.rel = "stylesheet";
cssStyle.innerHTML = `button#secondaryDownload.secondaryToolbarButton, button#download.toolbarButton,
button#secondaryOpenFile.secondaryToolbarButton, button#openFile.toolbarButton {
display: none !important;
}`;
if (config.device.isMobileDevice) {
cssStyle.innerHTML = `${cssStyle.innerHTML}
button#secondaryPrint.secondaryToolbarButton, button#print.toolbarButton{
display: none !important;
}`;
}
const iframe = rootElement.tagName === 'IFRAME' ? rootElement : rootElement.querySelector('iframe');
if (iframe) {
if (!iframe.dataset.hideButtons) {
iframe.dataset.hideButtons = 'true';
iframe.addEventListener('load', event => {
if (iframe.contentDocument && iframe.contentDocument.head) {
iframe.contentDocument.head.appendChild(cssStyle);
}
});
}
} else {
console.warn('No IFRAME found');
}
}
/*
* There is no changes to pdf.js in this file, but only a note about a change that has been done in it.
* List of changes made in the library
* There is no changes to pdf.js in this section, but only a note about changes that has been done in /web/static/lib/pdfjs/.
*
* In the module account_invoice_extract, the the code need to react to the 'pagerendered' event triggered by
* pdf.js. However in recent version of pdf.js, event are not visible outside of the library, except if the
+6 -7
View File
@@ -14,6 +14,11 @@ const bus = new Bus();
* this file someday.
*/
const maxTouchPoints = navigator.maxTouchPoints || 1;
const isAndroid = /Android/i.test(navigator.userAgent);
const isIOS = /(iPad|iPhone|iPod)/i.test(navigator.userAgent) || (navigator.platform === 'MacIntel' && maxTouchPoints > 1);
const isOtherMobileDevice = /(webOS|BlackBerry|Windows Phone)/i.test(navigator.userAgent);
var config = {
device: {
/**
@@ -52,13 +57,7 @@ var config = {
*
* @return {boolean}
*/
isMobileDevice: navigator.userAgent.match(/Android/i) ||
navigator.userAgent.match(/webOS/i) ||
navigator.userAgent.match(/iPhone/i) ||
navigator.userAgent.match(/iPad/i) ||
navigator.userAgent.match(/iPod/i) ||
navigator.userAgent.match(/BlackBerry/i) ||
navigator.userAgent.match(/Windows Phone/i),
isMobileDevice: isAndroid || isIOS || isOtherMobileDevice,
/**
* Mapping between the numbers 0,1,2,3,4,5,6 and some descriptions
*/