浏览代码

Move playing of sounds to the notification plugin.

Also add a config setting for the icon shown in HTML5 notificatins.

updates #443
JC Brand 9 年之前
父节点
当前提交
26cb98d963
共有 4 个文件被更改,包括 127 次插入114 次删除
  1. 8 0
      docs/source/configuration.rst
  2. 4 4
      spec/chatroom.js
  3. 34 79
      src/converse-core.js
  4. 81 31
      src/converse-notification.js

+ 8 - 0
docs/source/configuration.rst

@@ -538,6 +538,14 @@ different approach.
 If you're using MAM for archiving chat room messages, you might want to set
 If you're using MAM for archiving chat room messages, you might want to set
 this option to zero.
 this option to zero.
 
 
+notification_icon
+-----------------
+
+* Default: ``'/logo/conversejs.png'``
+
+This option specifies which icon is shown in HTML5 notifications, as provided
+by the ``src/converse-notification.js`` plugin.
+
 
 
 ping_interval
 ping_interval
 -------------
 -------------

+ 4 - 4
spec/chatroom.js

@@ -196,7 +196,7 @@
                 test_utils.openChatRoom('lounge', 'localhost', 'dummy');
                 test_utils.openChatRoom('lounge', 'localhost', 'dummy');
                 spyOn(converse, 'emit');
                 spyOn(converse, 'emit');
                 converse.play_sounds = true;
                 converse.play_sounds = true;
-                spyOn(converse, 'notifyOfNewMessage');
+                spyOn(converse, 'playSoundNotification');
                 var view = this.chatboxviews.get('lounge@localhost');
                 var view = this.chatboxviews.get('lounge@localhost');
                 if (!view.$el.find('.chat-area').length) { view.renderChatArea(); }
                 if (!view.$el.find('.chat-area').length) { view.renderChatArea(); }
                 var text = 'This message will play a sound because it mentions dummy';
                 var text = 'This message will play a sound because it mentions dummy';
@@ -207,7 +207,7 @@
                     type: 'groupchat'
                     type: 'groupchat'
                 }).c('body').t(text);
                 }).c('body').t(text);
                 view.onChatRoomMessage(message.nodeTree);
                 view.onChatRoomMessage(message.nodeTree);
-                expect(converse.notifyOfNewMessage).toHaveBeenCalled();
+                expect(converse.playSoundNotification).toHaveBeenCalled();
 
 
                 text = "This message won't play a sound";
                 text = "This message won't play a sound";
                 message = $msg({
                 message = $msg({
@@ -217,7 +217,7 @@
                     type: 'groupchat'
                     type: 'groupchat'
                 }).c('body').t(text);
                 }).c('body').t(text);
                 view.onChatRoomMessage(message.nodeTree);
                 view.onChatRoomMessage(message.nodeTree);
-                expect(converse.notifyOfNewMessage, 1);
+                expect(converse.playSoundNotification, 1);
                 converse.play_sounds = false;
                 converse.play_sounds = false;
 
 
                 text = "This message won't play a sound because it is sent by dummy";
                 text = "This message won't play a sound because it is sent by dummy";
@@ -228,7 +228,7 @@
                     type: 'groupchat'
                     type: 'groupchat'
                 }).c('body').t(text);
                 }).c('body').t(text);
                 view.onChatRoomMessage(message.nodeTree);
                 view.onChatRoomMessage(message.nodeTree);
-                expect(converse.notifyOfNewMessage, 1);
+                expect(converse.playSoundNotification, 1);
                 converse.play_sounds = false;
                 converse.play_sounds = false;
             }.bind(converse));
             }.bind(converse));
 
 

+ 34 - 79
src/converse-core.js

@@ -106,14 +106,6 @@
         9: 'REDIRECT'
         9: 'REDIRECT'
     };
     };
 
 
-    // XEP-0085 Chat states
-    // http://xmpp.org/extensions/xep-0085.html
-    var INACTIVE = 'inactive';
-    var ACTIVE = 'active';
-    var COMPOSING = 'composing';
-    var PAUSED = 'paused';
-    var GONE = 'gone';
-
     // TODO Refactor into external MAM plugin
     // TODO Refactor into external MAM plugin
     // XEP-0059 Result Set Management
     // XEP-0059 Result Set Management
     var RSM_ATTRIBUTES = ['max', 'first', 'last', 'after', 'before', 'index', 'count'];
     var RSM_ATTRIBUTES = ['max', 'first', 'last', 'after', 'before', 'index', 'count'];
@@ -201,20 +193,6 @@
     };
     };
 
 
 
 
-    converse.isOnlyChatStateNotification = function ($msg) {
-        // See XEP-0085 Chat State Notification
-        return (
-            $msg.find('body').length === 0 && (
-                $msg.find(ACTIVE).length !== 0 ||
-                $msg.find(COMPOSING).length !== 0 ||
-                $msg.find(INACTIVE).length !== 0 ||
-                $msg.find(PAUSED).length !== 0 ||
-                $msg.find(GONE).length !== 0
-            )
-        );
-    };
-
-
     converse.log = function (txt, level) {
     converse.log = function (txt, level) {
         var logger;
         var logger;
         if (typeof console === "undefined" || typeof console.log === "undefined") {
         if (typeof console === "undefined" || typeof console.log === "undefined") {
@@ -261,11 +239,21 @@
         Strophe.addNamespace('RSM', 'http://jabber.org/protocol/rsm');
         Strophe.addNamespace('RSM', 'http://jabber.org/protocol/rsm');
         Strophe.addNamespace('XFORM', 'jabber:x:data');
         Strophe.addNamespace('XFORM', 'jabber:x:data');
 
 
+        // Instance level constants
         this.TIMEOUTS = { // Set as module attr so that we can override in tests.
         this.TIMEOUTS = { // Set as module attr so that we can override in tests.
             'PAUSED':     20000,
             'PAUSED':     20000,
             'INACTIVE':   90000
             'INACTIVE':   90000
         };
         };
 
 
+        // XEP-0085 Chat states
+        // http://xmpp.org/extensions/xep-0085.html
+        this.INACTIVE = 'inactive';
+        this.ACTIVE = 'active';
+        this.COMPOSING = 'composing';
+        this.PAUSED = 'paused';
+        this.GONE = 'gone';
+
+
         // Detect support for the user's locale
         // Detect support for the user's locale
         // ------------------------------------
         // ------------------------------------
         this.isConverseLocale = function (locale) { return typeof locales[locale] !== "undefined"; };
         this.isConverseLocale = function (locale) { return typeof locales[locale] !== "undefined"; };
@@ -378,7 +366,6 @@
             message_carbons: false, // Support for XEP-280
             message_carbons: false, // Support for XEP-280
             no_trimming: false, // Set to true for phantomjs tests (where browser apparently has no width)
             no_trimming: false, // Set to true for phantomjs tests (where browser apparently has no width)
             password: undefined,
             password: undefined,
-            play_sounds: false,
             prebind: false, // XXX: Deprecated, use "authentication" instead.
             prebind: false, // XXX: Deprecated, use "authentication" instead.
             prebind_url: null,
             prebind_url: null,
             rid: undefined,
             rid: undefined,
@@ -386,7 +373,6 @@
             show_only_online_users: false,
             show_only_online_users: false,
             show_toolbar: true,
             show_toolbar: true,
             sid: undefined,
             sid: undefined,
-            sounds_path: '/sounds/',
             storage: 'session',
             storage: 'session',
             synchronize_availability: true, // Set to false to not sync with other clients or with resource name of the particular client that it should synchronize with
             synchronize_availability: true, // Set to false to not sync with other clients or with resource name of the particular client that it should synchronize with
             use_vcards: true,
             use_vcards: true,
@@ -453,7 +439,7 @@
             /* Send out a Chat Status Notification (XEP-0352) */
             /* Send out a Chat Status Notification (XEP-0352) */
             if (converse.features[Strophe.NS.CSI] || true) {
             if (converse.features[Strophe.NS.CSI] || true) {
                 converse.connection.send($build(stat, {xmlns: Strophe.NS.CSI}));
                 converse.connection.send($build(stat, {xmlns: Strophe.NS.CSI}));
-                this.inactive = (stat === INACTIVE) ? true : false;
+                this.inactive = (stat === converse.INACTIVE) ? true : false;
             }
             }
         };
         };
 
 
@@ -468,7 +454,7 @@
                 return;
                 return;
             }
             }
             if (this.inactive) {
             if (this.inactive) {
-                this.sendCSI(ACTIVE);
+                this.sendCSI(converse.ACTIVE);
             }
             }
             if (this.auto_changed_status === true) {
             if (this.auto_changed_status === true) {
                 this.auto_changed_status = false;
                 this.auto_changed_status = false;
@@ -489,7 +475,7 @@
             var stat = this.xmppstatus.getStatus();
             var stat = this.xmppstatus.getStatus();
             this.idle_seconds++;
             this.idle_seconds++;
             if (this.csi_waiting_time > 0 && this.idle_seconds > this.csi_waiting_time && !this.inactive) {
             if (this.csi_waiting_time > 0 && this.idle_seconds > this.csi_waiting_time && !this.inactive) {
-                this.sendCSI(INACTIVE);
+                this.sendCSI(converse.INACTIVE);
             }
             }
             if (this.auto_away > 0 && this.idle_seconds > this.auto_away && stat !== 'away' && stat !== 'xa') {
             if (this.auto_away > 0 && this.idle_seconds > this.auto_away && stat !== 'away' && stat !== 'xa') {
                 this.auto_changed_status = true;
                 this.auto_changed_status = true;
@@ -514,36 +500,6 @@
             window.setInterval(this.onEverySecond.bind(this), 1000);
             window.setInterval(this.onEverySecond.bind(this), 1000);
         };
         };
 
 
-        this.shouldNotifyOfNewMessage = function ($message) {
-            var $forwarded = $message.find('forwarded');
-            if ($forwarded.length) {
-                return false;
-            }
-            var is_me = Strophe.getBareJidFromJid($message.attr('from')) === converse.bare_jid;
-            return !converse.isOnlyChatStateNotification($message) && !is_me;
-        };
-
-        this.notifyOfNewMessage = function ($message) {
-            /* Plays a sound to notify that a new message was recieved.
-             *
-             * Returns true if the notification was made and false otherwise.
-             */
-            if (!this.shouldNotifyOfNewMessage($message)) {
-                return false;
-            }
-            var audio;
-            if (converse.play_sounds && typeof Audio !== "undefined") {
-                audio = new Audio(converse.sounds_path+"msg_received.ogg");
-                if (audio.canPlayType('/audio/ogg')) {
-                    audio.play();
-                } else {
-                    audio = new Audio(converse.sounds_path+"msg_received.mp3");
-                    audio.play();
-                }
-            }
-            return true;
-        };
-
         this.giveFeedback = function (message, klass) {
         this.giveFeedback = function (message, klass) {
             $('.conn-feedback').each(function (idx, el) {
             $('.conn-feedback').each(function (idx, el) {
                 var $el = $(el);
                 var $el = $(el);
@@ -1413,11 +1369,11 @@
                     fullname = this.get('fullname'),
                     fullname = this.get('fullname'),
                     is_groupchat = $message.attr('type') === 'groupchat',
                     is_groupchat = $message.attr('type') === 'groupchat',
                     msgid = $message.attr('id'),
                     msgid = $message.attr('id'),
-                    chat_state = $message.find(COMPOSING).length && COMPOSING ||
-                        $message.find(PAUSED).length && PAUSED ||
-                        $message.find(INACTIVE).length && INACTIVE ||
-                        $message.find(ACTIVE).length && ACTIVE ||
-                        $message.find(GONE).length && GONE,
+                    chat_state = $message.find(converse.COMPOSING).length && converse.COMPOSING ||
+                        $message.find(converse.PAUSED).length && converse.PAUSED ||
+                        $message.find(converse.INACTIVE).length && converse.INACTIVE ||
+                        $message.find(converse.ACTIVE).length && converse.ACTIVE ||
+                        $message.find(converse.GONE).length && converse.GONE,
                     stamp, time, sender, from;
                     stamp, time, sender, from;
 
 
                 if (is_groupchat) {
                 if (is_groupchat) {
@@ -1830,14 +1786,14 @@
             },
             },
 
 
             handleChatStateMessage: function (message) {
             handleChatStateMessage: function (message) {
-                if (message.get('chat_state') === COMPOSING) {
+                if (message.get('chat_state') === converse.COMPOSING) {
                     this.showStatusNotification(message.get('fullname')+' '+__('is typing'));
                     this.showStatusNotification(message.get('fullname')+' '+__('is typing'));
                     this.clear_status_timeout = window.setTimeout(this.clearStatusNotification.bind(this), 10000);
                     this.clear_status_timeout = window.setTimeout(this.clearStatusNotification.bind(this), 10000);
-                } else if (message.get('chat_state') === PAUSED) {
+                } else if (message.get('chat_state') === converse.PAUSED) {
                     this.showStatusNotification(message.get('fullname')+' '+__('has stopped typing'));
                     this.showStatusNotification(message.get('fullname')+' '+__('has stopped typing'));
-                } else if (_.contains([INACTIVE, ACTIVE], message.get('chat_state'))) {
+                } else if (_.contains([converse.INACTIVE, converse.ACTIVE], message.get('chat_state'))) {
                     this.$content.find('div.chat-event').remove();
                     this.$content.find('div.chat-event').remove();
-                } else if (message.get('chat_state') === GONE) {
+                } else if (message.get('chat_state') === converse.GONE) {
                     this.showStatusNotification(message.get('fullname')+' '+__('has gone away'));
                     this.showStatusNotification(message.get('fullname')+' '+__('has gone away'));
                 }
                 }
             },
             },
@@ -1876,7 +1832,7 @@
                             type: 'chat',
                             type: 'chat',
                             id: message.get('msgid')
                             id: message.get('msgid')
                        }).c('body').t(message.get('message')).up()
                        }).c('body').t(message.get('message')).up()
-                         .c(ACTIVE, {'xmlns': Strophe.NS.CHATSTATES}).up();
+                         .c(converse.ACTIVE, {'xmlns': Strophe.NS.CHATSTATES}).up();
             },
             },
 
 
             sendMessage: function (message) {
             sendMessage: function (message) {
@@ -1967,12 +1923,12 @@
                     window.clearTimeout(this.chat_state_timeout);
                     window.clearTimeout(this.chat_state_timeout);
                     delete this.chat_state_timeout;
                     delete this.chat_state_timeout;
                 }
                 }
-                if (state === COMPOSING) {
+                if (state === converse.COMPOSING) {
                     this.chat_state_timeout = window.setTimeout(
                     this.chat_state_timeout = window.setTimeout(
-                            this.setChatState.bind(this), converse.TIMEOUTS.PAUSED, PAUSED);
-                } else if (state === PAUSED) {
+                            this.setChatState.bind(this), converse.TIMEOUTS.PAUSED, converse.PAUSED);
+                } else if (state === converse.PAUSED) {
                     this.chat_state_timeout = window.setTimeout(
                     this.chat_state_timeout = window.setTimeout(
-                            this.setChatState.bind(this), converse.TIMEOUTS.INACTIVE, INACTIVE);
+                            this.setChatState.bind(this), converse.TIMEOUTS.INACTIVE, converse.INACTIVE);
                 }
                 }
                 if (!no_save && this.model.get('chat_state') !== state) {
                 if (!no_save && this.model.get('chat_state') !== state) {
                     this.model.set('chat_state', state);
                     this.model.set('chat_state', state);
@@ -1996,11 +1952,11 @@
                         }
                         }
                         converse.emit('messageSend', message);
                         converse.emit('messageSend', message);
                     }
                     }
-                    this.setChatState(ACTIVE);
+                    this.setChatState(converse.ACTIVE);
                 } else if (!this.model.get('chatroom')) { // chat state data is currently only for single user chat
                 } else if (!this.model.get('chatroom')) { // chat state data is currently only for single user chat
                     // Set chat state to composing if keyCode is not a forward-slash
                     // Set chat state to composing if keyCode is not a forward-slash
                     // (which would imply an internal command and not a message).
                     // (which would imply an internal command and not a message).
-                    this.setChatState(COMPOSING, ev.keyCode === KEY.FORWARD_SLASH);
+                    this.setChatState(converse.COMPOSING, ev.keyCode === KEY.FORWARD_SLASH);
                 }
                 }
             },
             },
 
 
@@ -2155,7 +2111,7 @@
                 if (ev && ev.preventDefault) { ev.preventDefault(); }
                 if (ev && ev.preventDefault) { ev.preventDefault(); }
                 if (converse.connection.connected) {
                 if (converse.connection.connected) {
                     this.model.destroy();
                     this.model.destroy();
-                    this.setChatState(INACTIVE);
+                    this.setChatState(converse.INACTIVE);
                 } else {
                 } else {
                     this.hide();
                     this.hide();
                 }
                 }
@@ -2167,7 +2123,7 @@
                 converse.chatboxviews.trimChats(this);
                 converse.chatboxviews.trimChats(this);
                 utils.refreshWebkit();
                 utils.refreshWebkit();
                 this.$content.scrollTop(this.model.get('scroll'));
                 this.$content.scrollTop(this.model.get('scroll'));
-                this.setChatState(ACTIVE).focus();
+                this.setChatState(converse.ACTIVE).focus();
                 converse.emit('chatBoxMaximized', this);
                 converse.emit('chatBoxMaximized', this);
             },
             },
 
 
@@ -2183,7 +2139,7 @@
                 // save the scroll position to restore it on maximize
                 // save the scroll position to restore it on maximize
                 this.model.save({'scroll': this.$content.scrollTop()});
                 this.model.save({'scroll': this.$content.scrollTop()});
                 // Minimizes a chat box
                 // Minimizes a chat box
-                this.setChatState(INACTIVE).model.minimize();
+                this.setChatState(converse.INACTIVE).model.minimize();
                 this.$el.hide('fast', utils.refreshwebkit);
                 this.$el.hide('fast', utils.refreshwebkit);
                 converse.emit('chatBoxMinimized', this);
                 converse.emit('chatBoxMinimized', this);
             },
             },
@@ -2282,7 +2238,7 @@
                         // localstorage
                         // localstorage
                         this.model.save();
                         this.model.save();
                     }
                     }
-                    this.setChatState(ACTIVE);
+                    this.setChatState(converse.ACTIVE);
                     this.scrollDown();
                     this.scrollDown();
                     if (focus) {
                     if (focus) {
                         this.focus();
                         this.focus();
@@ -2389,7 +2345,6 @@
                 if (msgid && chatbox.messages.findWhere({msgid: msgid})) {
                 if (msgid && chatbox.messages.findWhere({msgid: msgid})) {
                     return true; // We already have this message stored.
                     return true; // We already have this message stored.
                 }
                 }
-                converse.notifyOfNewMessage($message);
                 chatbox.createMessage($message, $delay, archive_id);
                 chatbox.createMessage($message, $delay, archive_id);
                 converse.roster.addResource(contact_jid, resource);
                 converse.roster.addResource(contact_jid, resource);
                 converse.emit('message', message);
                 converse.emit('message', message);
@@ -3160,7 +3115,7 @@
                     return;
                     return;
                 }
                 }
                 plugin.converse = converse;
                 plugin.converse = converse;
-                _.each(Object.keys(plugin.overrides), function (key) {
+                _.each(Object.keys(plugin.overrides || {}), function (key) {
                     /* We automatically override all methods and Backbone views and
                     /* We automatically override all methods and Backbone views and
                      * models that are in the "overrides" namespace.
                      * models that are in the "overrides" namespace.
                      */
                      */

+ 81 - 31
src/converse-notification.js

@@ -10,46 +10,77 @@
     define("converse-notification", ["converse-core", "converse-api"], factory);
     define("converse-notification", ["converse-core", "converse-api"], factory);
 }(this, function (converse, converse_api) {
 }(this, function (converse, converse_api) {
     "use strict";
     "use strict";
-    var utils = converse_api.env.utils;
-    var Strophe = converse_api.env.Strophe;
+    var $ = converse_api.env.jQuery,
+        utils = converse_api.env.utils,
+        Strophe = converse_api.env.Strophe,
+        _ = converse_api.env._;
     // For translations
     // For translations
     var __ = utils.__.bind(converse);
     var __ = utils.__.bind(converse);
     var ___ = utils.___;
     var ___ = utils.___;
 
 
-    if (!("Notification" in window)) {
-        // HTML5 notifications aren't supported.
-        converse.log(
-            "Not loading the notifications plugin because this browser "+
-            "doesn't support HTML5 notifications.");
-        return;
-    }
-    // Ask user to enable HTML5 notifications
-    Notification.requestPermission();
+    var supports_html5_notification = "Notification" in window;
 
 
+    if (supports_html5_notification && Notification.permission !== 'denied') {
+        // Ask user to enable HTML5 notifications
+        Notification.requestPermission();
+    }
 
 
     converse_api.plugins.add('notification', {
     converse_api.plugins.add('notification', {
 
 
-        overrides: {
-            // Overrides mentioned here will be picked up by converse.js's
-            // plugin architecture they will replace existing methods on the
-            // relevant objects or classes.
-            //
-            // New functions which don't exist yet can also be added.
-
-            notifyOfNewMessage: function ($message) {
-                var result = this._super.notifyOfNewMessage.apply(this, arguments);
-                if (result && (this.windowState === 'blur') && (Notification.permission === "granted")) {
-                    this.showMessageNotification($message);
-                }
-                return result;
-            }
-        },
-
         initialize: function () {
         initialize: function () {
             /* The initialize function gets called as soon as the plugin is
             /* The initialize function gets called as soon as the plugin is
              * loaded by converse.js's plugin machinery.
              * loaded by converse.js's plugin machinery.
              */
              */
             var converse = this.converse;
             var converse = this.converse;
+            // Configuration values for this plugin
+            var settings = {
+                play_sounds: false,
+                sounds_path: '/sounds/',
+                notification_icon: '/logo/conversejs.png'
+            };
+            _.extend(converse.default_settings, settings);
+            _.extend(converse, settings);
+            _.extend(converse, _.pick(converse.user_settings, Object.keys(settings)));
+
+            converse.isOnlyChatStateNotification = function ($msg) {
+                // See XEP-0085 Chat State Notification
+                return (
+                    $msg.find('body').length === 0 && (
+                        $msg.find(converse.ACTIVE).length !== 0 ||
+                        $msg.find(converse.COMPOSING).length !== 0 ||
+                        $msg.find(converse.INACTIVE).length !== 0 ||
+                        $msg.find(converse.PAUSED).length !== 0 ||
+                        $msg.find(converse.GONE).length !== 0
+                    )
+                );
+            };
+
+            converse.shouldNotifyOfNewMessage = function ($message) {
+                var $forwarded = $message.find('forwarded');
+                if ($forwarded.length) {
+                    return false;
+                }
+                var is_me = Strophe.getBareJidFromJid($message.attr('from')) === converse.bare_jid;
+                return !converse.isOnlyChatStateNotification($message) && !is_me;
+            };
+
+            converse.playSoundNotification = function ($message) {
+                /* Plays a sound to notify that a new message was recieved.
+                 */
+                // XXX Eventually this can be refactored to use Notification's sound
+                // feature, but no browser currently supports it.
+                // https://developer.mozilla.org/en-US/docs/Web/API/notification/sound
+                var audio;
+                if (converse.play_sounds && typeof Audio !== "undefined") {
+                    audio = new Audio(converse.sounds_path+"msg_received.ogg");
+                    if (audio.canPlayType('/audio/ogg')) {
+                        audio.play();
+                    } else {
+                        audio = new Audio(converse.sounds_path+"msg_received.mp3");
+                        audio.play();
+                    }
+                }
+            };
 
 
             converse.showChatStateNotification = function (event, contact) {
             converse.showChatStateNotification = function (event, contact) {
                 /* Show an HTML5 notification indicating that a contact changed
                 /* Show an HTML5 notification indicating that a contact changed
@@ -77,20 +108,39 @@
                 setTimeout(n.close.bind(n), 5000);
                 setTimeout(n.close.bind(n), 5000);
             };
             };
 
 
-            converse.on('contactStatusChanged',  converse.showChatStateNotification);
-
             converse.showMessageNotification = function ($message) {
             converse.showMessageNotification = function ($message) {
-                /* Show an HTML5 notification of a received message.
+                /* Shows an HTML5 Notification to indicate that a new chat
+                 * message was received.
                  */
                  */
+                if (!supports_html5_notification ||
+                        this.windowState !== 'blur' ||
+                        Notification.permission !== "granted") {
+                    return;
+                }
                 var contact_jid = Strophe.getBareJidFromJid($message.attr('from'));
                 var contact_jid = Strophe.getBareJidFromJid($message.attr('from'));
                 var roster_item = converse.roster.get(contact_jid);
                 var roster_item = converse.roster.get(contact_jid);
                 var n = new Notification(__(___("%1$s says"), roster_item.get('fullname')), {
                 var n = new Notification(__(___("%1$s says"), roster_item.get('fullname')), {
                         body: $message.children('body').text(),
                         body: $message.children('body').text(),
                         lang: converse.i18n.locale_data.converse[""].lang,
                         lang: converse.i18n.locale_data.converse[""].lang,
-                        icon: 'logo/conversejs.png'
+                        icon: converse.notification_icon
                     });
                     });
                 setTimeout(n.close.bind(n), 5000);
                 setTimeout(n.close.bind(n), 5000);
             };
             };
+
+            converse.notifyOfNewMessage = function (message) {
+                /* Event handler for the on('message') event. Will call methods
+                 * to play sounds and show HTML5 notifications.
+                 */
+                var $message = $(message);
+                if (!converse.shouldNotifyOfNewMessage($message)) {
+                    return false;
+                }
+                converse.playSoundNotification($message);
+                converse.showMessageNotification($message);
+            };
+
+            converse.on('contactStatusChanged',  converse.showChatStateNotification);
+            converse.on('message',  converse.showMessageNotification);
         }
         }
     });
     });
 }));
 }));