From b1a51bdbf4f8a1eb4c92d9108a10b77005a07e96 Mon Sep 17 00:00:00 2001 From: Pierre Paridans Date: Thu, 24 Sep 2020 12:47:09 +0000 Subject: [PATCH] [FIX] website_event_track: listen for pwa install event earlier To display the PWA's install banner, the browser triggers a `beforeinstallprompt` event when he estimates that all the requirements for installation are fulfilled (e.g. Service-worker, manifest...). But we have observed that the browser can trigger this event really early in the loading of the page and even before our listener has been registered, failing to display the banner. This commit moves the event listener's registration out of the lifecycle of our widget to allow it to be registered as soon as possible, drastically reducing the risk of missed-events. X-original-commit: a014a6c9e3baced22b158d6d8b4199bdae7562b9 --- .../static/src/js/website_event_pwa_widget.js | 74 ++++++++++--------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/addons/website_event_track/static/src/js/website_event_pwa_widget.js b/addons/website_event_track/static/src/js/website_event_pwa_widget.js index 1eb93a9cc22..7953c9c132b 100644 --- a/addons/website_event_track/static/src/js/website_event_pwa_widget.js +++ b/addons/website_event_track/static/src/js/website_event_pwa_widget.js @@ -1,6 +1,21 @@ odoo.define("website_event_track.website_event_pwa_widget", function (require) { "use strict"; + /* + * The "deferredPrompt" Promise will resolve only if the "beforeinstallprompt" event + * has been triggered. It allows to register this listener as soon as possible + * to avoid missed-events (as the browser can trigger it very early in the page lifecycle). + */ + var deferredPrompt = new Promise(function (resolve, reject) { + if (!("serviceWorker" in navigator)) { + return reject(); + } + window.addEventListener("beforeinstallprompt", function (ev) { + ev.preventDefault(); + resolve(ev); + }); + }); + var config = require("web.config"); var publicWidget = require("web.public.widget"); var utils = require("web.utils"); @@ -35,23 +50,21 @@ odoo.define("website_event_track.website_event_pwa_widget", function (require) { prompt_close_bar: "_onPromptCloseBar", }, - /** - * - * @override - */ - init: function () { - this._super.apply(this, arguments); - this.beforeInstallPromptHandler = this._onBeforeInstallPrompt.bind(this); - }, - /** * * @override */ start: function () { - var superProm = this._super.apply(this, arguments); - window.addEventListener("beforeinstallprompt", this.beforeInstallPromptHandler); - return superProm.then(this._registerServiceWorker.bind(this)).then(this._prefetch.bind(this)); + var self = this; + return this._super.apply(this, arguments) + .then(this._registerServiceWorker.bind(this)) + .then(function () { + // Don't wait for the prompt's Promise as it may never resolve. + deferredPrompt.then(self._showInstallBanner.bind(self)).catch(function () { + console.log("ServiceWorker not supported"); + }); + }) + .then(this._prefetch.bind(this)); }, /** @@ -59,7 +72,6 @@ odoo.define("website_event_track.website_event_pwa_widget", function (require) { * @override */ destroy: function () { - window.removeEventListener("beforeinstallprompt", this.beforeInstallPromptHandler); this._super.apply(this, arguments); }, @@ -156,6 +168,9 @@ odoo.define("website_event_track.website_event_pwa_widget", function (require) { * @private */ _showInstallBanner: function () { + if (!config.device.isMobile) { + return; + } var self = this; this.installBanner = new PWAInstallBanner(this); this.installBanner.appendTo(this.$el).then(function () { @@ -169,18 +184,6 @@ odoo.define("website_event_track.website_event_pwa_widget", function (require) { // Handlers //-------------------------------------------------------------------------- - /** - * @private - * @param ev {Event} - */ - _onBeforeInstallPrompt: function (ev) { - if (!config.device.isMobile) { - return; - } - ev.preventDefault(); - this.deferredPrompt = ev; - this._showInstallBanner(); - }, /** * @private * @param ev {Event} @@ -195,15 +198,20 @@ odoo.define("website_event_track.website_event_pwa_widget", function (require) { */ _onPromptInstall: function (ev) { ev.stopPropagation(); - this.deferredPrompt.prompt(); this._hideInstallBanner(); - this.deferredPrompt.userChoice.then(function (choiceResult) { - if (choiceResult.outcome === "accepted") { - console.log("User accepted the install prompt"); - } else { - console.log("User dismissed the install prompt"); - } - }); + deferredPrompt.then(function (prompt) { + prompt.prompt(); + prompt.userChoice.then(function (choiceResult) { + if (choiceResult.outcome === "accepted") { + console.log("User accepted the install prompt"); + } else { + console.log("User dismissed the install prompt"); + } + }); + }) + .catch(function () { + console.log("ServiceWorker not supported"); + }); }, });