diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/bus/static/src/js/services | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/bus/static/src/js/services')
| -rw-r--r-- | addons/bus/static/src/js/services/bus_service.js | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/addons/bus/static/src/js/services/bus_service.js b/addons/bus/static/src/js/services/bus_service.js new file mode 100644 index 00000000..39b61da5 --- /dev/null +++ b/addons/bus/static/src/js/services/bus_service.js @@ -0,0 +1,154 @@ +odoo.define('bus.BusService', function (require) { +"use strict"; + +var CrossTab = require('bus.CrossTab'); +var core = require('web.core'); +var ServicesMixin = require('web.ServicesMixin'); +const session = require('web.session'); + +var BusService = CrossTab.extend(ServicesMixin, { + dependencies : ['local_storage'], + + // properties + _audio: null, + + /** + * As the BusService doesn't extend AbstractService, we have to replicate + * here what is done in AbstractService + * + * @param {Object} env + */ + init: function (env) { + this.env = env; + this._super(); + }, + + /** + * Replicate the behavior of AbstractService: + * + * Directly calls the requested service, instead of triggering a + * 'call_service' event up, which wouldn't work as services have no parent. + * + * @param {OdooEvent} ev + */ + _trigger_up: function (ev) { + if (ev.name === 'call_service') { + const payload = ev.data; + let args = payload.args || []; + if (payload.service === 'ajax' && payload.method === 'rpc') { + // ajax service uses an extra 'target' argument for rpc + args = args.concat(ev.target); + } + const service = this.env.services[payload.service]; + const result = service[payload.method].apply(service, args); + payload.callback(result); + } + }, + /** + * This method is necessary in order for this Class to be used to instantiate services + * + * @abstract + */ + start: function () {}, + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * Send a notification, and notify once per browser's tab + * + * @param {string} title + * @param {string} content + * @param {function} [callback] if given callback will be called when user clicks on notification + */ + sendNotification: function (title, content, callback) { + if (window.Notification && Notification.permission === "granted") { + if (this.isMasterTab()) { + try { + this._sendNativeNotification(title, content, callback); + } catch (error) { + // Notification without Serviceworker in Chrome Android doesn't works anymore + // So we fallback to do_notify() in this case + // https://bugs.chromium.org/p/chromium/issues/detail?id=481856 + if (error.message.indexOf('ServiceWorkerRegistration') > -1) { + this.do_notify(title, content); + this._beep(); + } else { + throw error; + } + } + } + } else { + this.do_notify(title, content); + if (this.isMasterTab()) { + this._beep(); + } + } + }, + /** + * Register listeners on notifications received on this bus service + * + * @param {Object} receiver + * @param {function} func + */ + onNotification: function () { + this.on.apply(this, ["notification"].concat(Array.prototype.slice.call(arguments))); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * Lazily play the 'beep' audio on sent notification + * + * @private + */ + _beep: function () { + if (typeof(Audio) !== "undefined") { + if (!this._audio) { + this._audio = new Audio(); + var ext = this._audio.canPlayType("audio/ogg; codecs=vorbis") ? ".ogg" : ".mp3"; + this._audio.src = session.url("/mail/static/src/audio/ting" + ext); + } + Promise.resolve(this._audio.play()).catch(_.noop); + } + }, + /** + * Show a browser notification + * + * @private + * @param {string} title + * @param {string} content + * @param {function} [callback] if given callback will be called when user clicks on notification + */ + _sendNativeNotification: function (title, content, callback) { + var notification = new Notification( + // The native Notification API works with plain text and not HTML + // unescaping is safe because done only at the **last** step + _.unescape(title), + { + body: _.unescape(content), + icon: "/mail/static/src/img/odoobot_transparent.png" + }); + notification.onclick = function () { + window.focus(); + if (this.cancel) { + this.cancel(); + } else if (this.close) { + this.close(); + } + if (callback) { + callback(); + } + }; + }, + +}); + +core.serviceRegistry.add('bus_service', BusService); + +return BusService; + +}); |
