[IMP] mail, bus: display native notifications if user away

This commit introduces native notifications (if available) to the
discuss application.

Those notifications will only appear if the user grants the permission
for that.  A notification bar will appear in the discuss application if
necessary to prompt the user.

Also, it always is the master bus that will be the one sending the
notification.

For this change, it was necessary to be able to detect if the user has
the focus on some other odoo tabs.  For this reason, the bus was
extended.
This commit is contained in:
Géry Debongnie
2015-12-29 14:47:40 +01:00
parent 04fce95875
commit cc8c355ecb
5 changed files with 85 additions and 36 deletions
+13 -7
View File
@@ -32,8 +32,9 @@ bus.Bus = Widget.extend({
this.trigger('window_focus', this.is_master);
}
});
$(window).on("focus", _.bind(this.window_focus, this));
$(window).on("blur", _.bind(this.window_blur, this));
$(window).on("focus", _.bind(this.focus_change, this, true));
$(window).on("blur", _.bind(this.focus_change, this, false));
$(window).on("unload", _.bind(this.focus_change, this, false));
_.each('click,keydown,keyup'.split(','), function(evtype) {
$(window).on(evtype, function() {
self.last_presence = new Date().getTime();
@@ -93,11 +94,8 @@ bus.Bus = Widget.extend({
this.channels = _.without(this.channels, channel);
},
// bus presence : window focus/unfocus
window_focus: function() {
this.set("window_focus", true);
},
window_blur: function() {
this.set("window_focus", false);
focus_change: function(focus) {
this.set("window_focus", focus);
},
is_odoo_focused: function () {
return this.get("window_focus");
@@ -211,6 +209,10 @@ var CrossTabBus = bus.Bus.extend({
if(e.key === 'bus.options'){
this.options = JSON.parse(value);
}
// update focus
if(e.key === 'bus.focus'){
this.set('window_focus', JSON.parse(value));
}
},
add_channel: function(){
this._super.apply(this, arguments);
@@ -231,6 +233,10 @@ var CrossTabBus = bus.Bus.extend({
this._super.apply(this, arguments);
setItem('bus.options', this.options);
},
focus_change: function(focus) {
this._super.apply(this, arguments);
setItem('bus.focus', focus);
},
});
+28 -29
View File
@@ -11,7 +11,7 @@ var web_client = require('web.web_client');
var _t = core._t;
var LIMIT = 100;
var preview_msg_max_size = 200;
var preview_msg_max_size = 350; // optimal for native english speakers
var MessageModel = new Model('mail.message', session.context);
var ChannelModel = new Model('mail.channel', session.context);
@@ -44,25 +44,36 @@ var beep = (function () {
bus.on("window_focus", null, function() {
global_unread_counter = 0;
notify();
web_client.set_title_part("_chat");
});
function increment_global_unread_counter () {
if (!bus.is_odoo_focused()) {
global_unread_counter++;
notify(bus.is_master);
function notify_incoming_message (msg, options) {
var title = _t('New message');
if (msg.author_id[1]) {
title += _t(' from ') + _.escape(msg.author_id[1]);
}
}
var content = $(msg.body).text().substr(0, preview_msg_max_size);
function notify (play_sound) {
var title;
if (global_unread_counter > 0) {
title = _.str.sprintf(_t("%d Messages"), global_unread_counter);
if (play_sound) {
beep();
if (bus.is_odoo_focused()) {
if (!options.is_displayed) {
web_client.do_notify(title, content);
}
} else {
global_unread_counter++;
var tab_title = _.str.sprintf(_t("%d Messages"), global_unread_counter);
web_client.set_title_part("_chat", tab_title);
if (Notification && Notification.permission === "granted") {
if (bus.is_master) {
new Notification(title, {body: content, icon: "/web/static/src/img/odoo.png", silent: false});
}
} else {
web_client.do_notify(title, content);
if (bus.is_master) {
beep();
}
}
}
web_client.set_title_part("_chat", title);
}
// Message and channel manipulation helpers
@@ -93,22 +104,10 @@ function add_message (data, options) {
channel.hidden = false;
chat_manager.bus.trigger('new_channel', channel);
}
if (is_chat && options.show_notification) {
var query = { is_displayed: false };
if (is_chat && options.show_notification && (!msg.author_id || msg.author_id[0] !== session.partner_id)) {
var query = {is_displayed: false};
chat_manager.bus.trigger('anyone_listening', channel, query);
if (!query.is_displayed) {
var title = _t('New message');
if (msg.author_id[1]) {
title += _t(' from ') + _.escape(msg.author_id[1]);
}
var trunc_text = function (t, limit) {
return (t.length > limit) ? t.substr(0, limit-1)+'…' : t;
};
web_client.do_notify(title, trunc_text(msg.body, preview_msg_max_size));
}
}
if (is_chat && options.increment_unread && (!msg.author_id || msg.author_id[0] !== session.partner_id)) {
increment_global_unread_counter();
notify_incoming_message(msg, query);
}
});
if (!options.silent) {
@@ -116,6 +116,14 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
chat_manager.undo_mark_as_read(msgs_ids, channel);
});
},
"click .o_mail_annoying_notification_bar .fa-close": function (event) {
this.$(".o_mail_annoying_notification_bar").slideUp();
},
"click .o_mail_request_permission": function (event) {
event.preventDefault();
this.$(".o_mail_annoying_notification_bar").slideUp();
window.Notification.requestPermission();
},
},
on_attach_callback: function () {
@@ -135,6 +143,7 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
this.options = options || {};
this.channels_scrolltop = {};
this.throttled_render_sidebar = _.throttle(this.render_sidebar.bind(this), 100, { leading: false });
this.notification_bar = (window.Notification.permission === "default");
},
willStart: function () {
@@ -10,6 +10,35 @@
height: auto;
}
.o_mail_annoying_notification_bar {
height: 40px;
background-color: #DFA941;
color: white;
text-shadow: 0px 1px 1px rgba(0, 0, 0, 0.25);
.o-flex-display();
border-bottom: 1px solid @odoo-main-color-muted;
.o_mail_request_permission {
.o-flex-display();
justify-content: center;
.o-flex(1,1, auto);
}
> span {
font-size: 16px;
line-height: 40px;
> a {
color: white;
margin-left: 5px;
text-decoration: underline;
}
&.fa-close {
margin-right: 10px;
cursor: pointer;
}
}
}
.o_mail_chat_sidebar {
width: @mail-chat-sidebar-width;
height: 100%;
@@ -4,6 +4,12 @@
<!-- Client Action -->
<t t-name="mail.client_action">
<div class="o_mail_chat">
<t t-if="widget.notification_bar">
<div class="o_mail_annoying_notification_bar">
<span class="o_mail_request_permission">Odoo needs your permission to <a href="#"> enable desktop notifications</a>.</span>
<span class="fa fa-close"></span>
</div>
</t>
<div class="o_mail_chat_sidebar"/>
<div class="o_mail_chat_content"/>
</div>