diff --git a/css/converse.css b/css/converse.css index 732e57764..451c2477d 100644 --- a/css/converse.css +++ b/css/converse.css @@ -1989,6 +1989,9 @@ #conversejs .chatroom .room-invite .tt-dropdown-menu .tt-suggestion .tt-highlight { background-color: #D24E2B; } +#conversejs .chatbox.headlines .chat-head.chat-head-chatbox { + background-color: #2A9D8F; } + #conversejs #minimized-chats { border-top-left-radius: 4px; border-top-right-radius: 4px; diff --git a/docs/CHANGES.md b/docs/CHANGES.md index 46f80444f..4567dc208 100755 --- a/docs/CHANGES.md +++ b/docs/CHANGES.md @@ -2,8 +2,11 @@ ## 0.11.0 (Unreleased) +- Add support for messages with type `headline`, often used for notifications + from the server. [jcbrand] - Add stanza-specific event listener `converse.listen.stanza`. - As a result `converse.listen.on('message');` has been deprecated, use `converse.stanza.on('message');` instead. [jcbrand] + As a result `converse.listen.on('message');` has been deprecated, use + `converse.stanza.on('message');` instead. [jcbrand] - Emit an event `chatBoxInitialized` once a chat box's initialize method has been called. [jcbrand] - Emit an event `statusInitialized` once the user's own status has been initialized upon startup. [jcbrand] - New config option [chatstate_notification_blacklist](https://conversejs.org/docs/html/configuration.html#chatstate_notification_blacklist) [jcbrand] @@ -12,8 +15,9 @@ encrypted session. [jcbrand] - Bugfix: RID, SID and JID tokens ignored when `keepalive` set to `true`. [jcbrand] - Removed the `account.logout` API, instead use `user.logout`. [jcbrand] -- Use `rel=noopener` with links that contain `target=_blank` to prevent potential phishing attacks. - [More info here](https://mathiasbynens.github.io/rel-noopener/) [jcbrand] +- Use `rel=noopener` with links that contain `target=_blank` to prevent potential + phishing attacks. [More info here](https://mathiasbynens.github.io/rel-noopener/) + [jcbrand] - #261 `show_controlbox_by_default` config not working [diditopher] - #443 HTML5 notifications of received messages [jcbrand] - #534 Updated Russian translation [badfiles] @@ -22,7 +26,8 @@ - #577 New config variable [message_archiving_timeout](https://conversejs.org/docs/html/configuration.html#message_archiving_timeout) [jcbrand] - #587 Fix issue when logging out with `auto_logout=true` [davec82] - #589 Save scroll position on minimize and restore it on maximize [rlanvin] -- #592 Add random resource for `auto_login`, add method generateResource to generate random resource [davec82] +- #592 Add random resource for `auto_login`, add method generateResource to + generate random resource [davec82] - #598 Add option `synchronize_availability` [davec82] - #600 Fix change xmpp status also on icon-status click [davec82] diff --git a/sass/_headline.scss b/sass/_headline.scss new file mode 100644 index 000000000..2ab179278 --- /dev/null +++ b/sass/_headline.scss @@ -0,0 +1,10 @@ +#conversejs { + .chatbox.headlines { + .chat-head { + &.chat-head-chatbox { + background-color: $headline-head-color; + } + } + } +} + diff --git a/sass/_variables.scss b/sass/_variables.scss index 581c96ac0..8fdc19de5 100644 --- a/sass/_variables.scss +++ b/sass/_variables.scss @@ -63,6 +63,8 @@ $chatroom-head-color: #E76F51 !default; $chatroom-color-light: #FF977C !default; $chatroom-color-dark: #D24E2B !default; +$headline-head-color: #2A9D8F !default; + $box-close-button-padding-top: 4px !default; $box-close-button-padding-bottom: 4px !default; $box-close-button-padding-left: 4px !default; diff --git a/sass/converse.scss b/sass/converse.scss index 6ca0be033..03f16eba7 100644 --- a/sass/converse.scss +++ b/sass/converse.scss @@ -15,4 +15,5 @@ @import "controlbox"; @import "roster"; @import "chatrooms"; +@import "headline"; @import "minimized_chats"; diff --git a/spec/headline.js b/spec/headline.js new file mode 100644 index 000000000..a7703a301 --- /dev/null +++ b/spec/headline.js @@ -0,0 +1,56 @@ +/*global converse */ +(function (root, factory) { + define([ + "jquery", + "mock", + "test_utils" + ], function ($, mock, test_utils) { + return factory($, mock, test_utils); + } + ); +} (this, function ($, mock, test_utils) { + "use strict"; + var $msg = converse_api.env.$msg, + _ = converse_api.env._; + + describe("When a headline message is received", function () { + + it("a chat box will open and display it", function () { + /* + * + * SIEVE + * <juliet@example.com> You got mail. + * + * + * imap://romeo@example.com/INBOX;UIDVALIDITY=385759043/;UID=18 + * + * + * + */ + runs(function () { + var stanza = $msg({ + 'type': 'headline', + 'from': 'notify.example.com', + 'to': 'dummy@localhost', + 'xml:lang': 'en' + }) + .c('subject').t('SIEVE').up() + .c('body').t('<juliet@example.com> You got mail.').up() + .c('x', {'xmlns': 'jabber:x:oob'}) + .c('url').t('imap://romeo@example.com/INBOX;UIDVALIDITY=385759043/;UID=18'); + converse.connection._dataRecv(test_utils.createRequest(stanza)); + }); + waits(250); + runs(function () { + expect( + _.contains( + converse.chatboxviews.keys(), + 'notify.example.com') + ).toBeTruthy(); + }); + }); + }); +})); diff --git a/src/converse-core.js b/src/converse-core.js index c56dbc764..ef4139276 100755 --- a/src/converse-core.js +++ b/src/converse-core.js @@ -1264,8 +1264,7 @@ }); } }); - - + this.ChatBoxes = Backbone.Collection.extend({ model: converse.ChatBox, comparator: 'time_opened', diff --git a/src/converse-headline.js b/src/converse-headline.js index 1d0d9c7f5..920547256 100644 --- a/src/converse-headline.js +++ b/src/converse-headline.js @@ -4,25 +4,113 @@ // Copyright (c) 2012-2016, Jan-Carel Brand // Licensed under the Mozilla Public License (MPLv2) // -/*global define */ +/*global define, window */ (function (root, factory) { define("converse-headline", [ "converse-core", "converse-api", - // TODO: remove this dependency "converse-chatview" ], factory); }(this, function (converse, converse_api) { "use strict"; + var $ = converse_api.env.jQuery, + _ = converse_api.env._, + utils = converse_api.env.utils, + __ = utils.__.bind(converse); + + var onHeadlineMessage = function (message) { + /* Handler method for all incoming messages of type "headline". + */ + var $message = $(message), + bare_jid = $message.attr('from'); + converse.chatboxes.create({ + 'id': bare_jid, + 'jid': bare_jid, + 'fullname': bare_jid, + 'type': 'headline' + }).createMessage($message); + converse.emit('message', message); + return true; + }; converse_api.plugins.add('headline', { + 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. + + ChatBoxViews: { + onChatBoxAdded: function (item) { + var view = this.get(item.get('id')); + if (!view && item.get('type') === 'headline') { + view = new converse.HeadlinesBoxView({model: item}); + this.add(item.get('id'), view); + return view; + } else { + return this._super.onChatBoxAdded.apply(this, arguments); + } + } + } + }, + initialize: function () { /* The initialize function gets called as soon as the plugin is * loaded by converse.js's plugin machinery. */ - // TODO + converse.HeadlinesBoxView = converse.ChatBoxView.extend({ + className: 'chatbox headlines', + + events: { + 'click .close-chatbox-button': 'close', + 'click .toggle-chatbox-button': 'minimize', + 'keypress textarea.chat-textarea': 'keyPressed', + 'mousedown .dragresize-top': 'onStartVerticalResize', + 'mousedown .dragresize-left': 'onStartHorizontalResize', + 'mousedown .dragresize-topleft': 'onStartDiagonalResize' + }, + + initialize: function () { + $(window).on('resize', _.debounce(this.setDimensions.bind(this), 100)); + this.model.messages.on('add', this.onMessageAdded, this); + this.model.on('show', this.show, this); + this.model.on('destroy', this.hide, this); + this.model.on('change:minimized', this.onMinimizedChanged, this); + this.render().fetchMessages().insertIntoPage().hide(); + converse.emit('chatBoxInitialized', this); + }, + + render: function () { + this.$el.attr('id', this.model.get('box_id')) + .html(converse.templates.chatbox( + _.extend(this.model.toJSON(), { + show_toolbar: converse.show_toolbar, + show_textarea: false, + title: this.model.get('fullname'), + info_close: __('Close this box'), + info_minimize: __('Minimize this box'), + label_personal_message: '' + } + ) + ) + ); + this.setWidth(); + this.$content = this.$el.find('.chat-content'); + converse.emit('chatBoxOpened', this); + window.setTimeout(utils.refreshWebkit, 50); + return this; + }, + }); + + var registerHeadlineHandler = function () { + converse.connection.addHandler( + onHeadlineMessage, null, 'message', 'headline'); + }; + converse.on('connected', registerHeadlineHandler); + converse.on('reconnected', registerHeadlineHandler); } }); })); diff --git a/src/converse-muc.js b/src/converse-muc.js index 8cb9a4092..ef2ad5fac 100755 --- a/src/converse-muc.js +++ b/src/converse-muc.js @@ -4,7 +4,7 @@ // Copyright (c) 2012-2016, Jan-Carel Brand // Licensed under the Mozilla Public License (MPLv2) // -/*global Backbone, define, window, setTimeout */ +/*global Backbone, define, window */ /* This is a Converse.js plugin which add support for multi-user chat rooms, as * specified in XEP-0045 Multi-user chat. @@ -14,8 +14,8 @@ "converse-core", "converse-api", "typeahead", - // TODO remove next two dependencies "converse-chatview", + // XXX: should we remove this dependency? "converse-controlbox" ], factory); }(this, function (converse, converse_api) { @@ -221,6 +221,7 @@ length: 300, tagName: 'div', className: 'chatbox chatroom', + is_chatroom: true, events: { 'click .close-chatbox-button': 'close', 'click .toggle-chatbox-button': 'minimize', @@ -235,7 +236,6 @@ 'mousedown .dragresize-left': 'onStartHorizontalResize', 'mousedown .dragresize-topleft': 'onStartDiagonalResize' }, - is_chatroom: true, initialize: function () { $(window).on('resize', _.debounce(this.setDimensions.bind(this), 100)); @@ -278,7 +278,7 @@ this.renderChatArea(); this.$content.on('scroll', _.debounce(this.onScroll.bind(this), 100)); this.setWidth(); - setTimeout(converse.refreshWebkit, 50); + window.setTimeout(converse.refreshWebkit, 50); return this; }, diff --git a/tests/main.js b/tests/main.js index 39aea35aa..8a5c42905 100644 --- a/tests/main.js +++ b/tests/main.js @@ -73,6 +73,7 @@ require([ "spec/notification", "spec/profiling", "spec/ping", + "spec/headline", "spec/register", "spec/xmppstatus" ], function () {