From acd9a18696e34f014ae2d5316bda7beb3963dc0a Mon Sep 17 00:00:00 2001 From: JC Brand Date: Fri, 20 Jul 2018 15:54:59 +0200 Subject: [PATCH] Update with new message markup --- css/converse.css | 46 ++-- dist/converse.js | 182 +++++++-------- mockup/chatroom.html | 10 +- sass/_chatbox.scss | 32 +-- sass/_messages.scss | 18 +- spec/chatbox.js | 28 +-- spec/chatroom.js | 16 +- spec/http-file-upload.js | 6 +- spec/messages.js | 347 ++++++++++++++--------------- spec/spoilers.js | 16 +- src/converse-chatview.js | 12 +- src/converse-message-view.js | 33 ++- src/templates/action.html | 6 - src/templates/file_progress.html | 6 +- src/templates/message.html | 31 ++- src/templates/spoiler_message.html | 14 -- src/utils/core.js | 11 +- 17 files changed, 386 insertions(+), 428 deletions(-) delete mode 100644 src/templates/action.html delete mode 100644 src/templates/spoiler_message.html diff --git a/css/converse.css b/css/converse.css index 905ac2440..a0894e33e 100644 --- a/css/converse.css +++ b/css/converse.css @@ -7381,7 +7381,7 @@ body.reset { background-color: #3AA569; box-shadow: 1px 3px 5px 3px rgba(0, 0, 0, 0.4); z-index: 1; - overflow-y: scroll; + overflow-y: hidden; width: 100%; } @media screen and (max-height: 450px) { #conversejs .chatbox .box-flyout { @@ -7648,18 +7648,6 @@ body.reset { #conversejs.converse-overlayed .chatbox .box-flyout { min-width: 250px !important; width: 250px; } - #conversejs.converse-embedded .chatbox .chat-body .chat-message, - #conversejs.converse-overlayed .chatbox .chat-body .chat-message { - line-height: 20px; } - #conversejs.converse-embedded .chatbox .chat-body .chat-message .chat-msg-author, - #conversejs.converse-overlayed .chatbox .chat-body .chat-message .chat-msg-author { - line-height: 20px; } - #conversejs.converse-embedded .chatbox .chat-body .chat-message .chat-msg-content, - #conversejs.converse-overlayed .chatbox .chat-body .chat-message .chat-msg-content { - line-height: 20px; } - #conversejs.converse-embedded .chatbox .chat-body .chat-message .chat-msg-content .emojione, - #conversejs.converse-overlayed .chatbox .chat-body .chat-message .chat-msg-content .emojione { - margin-bottom: -5px; } #conversejs.converse-embedded .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu, #conversejs.converse-overlayed .chatbox form.sendXMPPMessage .chat-toolbar li .toolbar-menu { min-width: 235px; } @@ -7746,16 +7734,6 @@ body.reset { background-color: #3AA569; border-top-left-radius: 4px; border-top-right-radius: 4px; } - #conversejs.converse-fullscreen .chatbox .chat-body .chat-message { - line-height: 16px; - font-size: 12px; } - #conversejs.converse-fullscreen .chatbox .chat-body .chat-message .chat-msg-author { - line-height: 16px; } - #conversejs.converse-fullscreen .chatbox .chat-body .chat-message .chat-msg-content { - line-height: 16px; } - #conversejs.converse-fullscreen .chatbox .chat-body .chat-message .chat-msg-content .emojione { - height: 16px; - margin-bottom: -4px; } #conversejs.converse-fullscreen .chatbox .chat-content { border-top-left-radius: 4px; border-top-right-radius: 4px; } @@ -8884,6 +8862,8 @@ body.reset { align-items: stretch; margin-left: 0.5rem; width: 100%; } + #conversejs .message.chat-msg .chat-msg__content--action { + margin-left: 0; } #conversejs .message.chat-msg .chat-msg__body { display: flex; flex-direction: row; @@ -8893,8 +8873,9 @@ body.reset { display: flex; flex-direction: column; width: 100%; } - #conversejs .message.chat-msg .chat-msg-edited { - cursor: pointer; } + #conversejs .message.chat-msg .chat-msg__edit-modal { + cursor: pointer; + padding-right: 0.5em; } #conversejs .message.chat-msg.headline .chat-msg__body { margin-left: 0; } #conversejs .message.chat-msg .chat-msg__text { @@ -8906,11 +8887,12 @@ body.reset { word-break: break-all; } #conversejs .message.chat-msg .chat-msg__text .emojione { margin-bottom: -6px; } - #conversejs .message.chat-msg .chat-msg-media { - margin-top: 0.25rem; } - #conversejs .message.chat-msg .chat-msg-media a { + #conversejs .message.chat-msg .chat-msg__media { + margin-top: 0.25rem; + word-break: break-all; } + #conversejs .message.chat-msg .chat-msg__media a { word-wrap: break-word; } - #conversejs .message.chat-msg .chat-msg-media audio { + #conversejs .message.chat-msg .chat-msg__media audio { width: 100%; } #conversejs .message.chat-msg .chat-msg__actions .chat-msg__action { height: 14px; @@ -8934,6 +8916,7 @@ body.reset { padding-bottom: 0.25rem; display: block; } #conversejs .message.chat-msg .chat-msg__heading .chat-msg__author { + white-space: nowrap; font-family: "Century Gothic", futura, "URW Gothic L", Verdana, sans-serif; font-size: 115%; } #conversejs .message.chat-msg .chat-msg__heading .chat-msg__author .badge { @@ -8943,6 +8926,7 @@ body.reset { padding-left: 0.25em; color: #8c8c8c; } #conversejs .message.chat-msg.chat-msg--action .chat-msg__content { + flex-wrap: wrap; flex-direction: row; justify-content: flex-start; } #conversejs .message.chat-msg.chat-msg--action .chat-msg__text { @@ -8951,6 +8935,10 @@ body.reset { margin-top: 0; padding-bottom: 0; width: auto; } + #conversejs .message.chat-msg.chat-msg--action .chat-msg__author { + font-size: 14px; } + #conversejs .message.chat-msg.chat-msg--action .chat-msg__time { + margin-left: 0; } #conversejs .message.chat-msg.chat-msg--followup .chat-msg__heading, #conversejs .message.chat-msg.chat-msg--followup .chat-msg__avatar { display: none; } diff --git a/dist/converse.js b/dist/converse.js index 7b39b48ee..c0971df6a 100644 --- a/dist/converse.js +++ b/dist/converse.js @@ -69333,11 +69333,11 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ // Copyright (c) 2012-2018, the Converse.js developers // Licensed under the Mozilla Public License (MPLv2) (function (root, factory) { - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! converse-core */ "./src/converse-core.js"), __webpack_require__(/*! bootstrap */ "./node_modules/bootstrap.native/dist/bootstrap-native-v4.js"), __webpack_require__(/*! emojione */ "./node_modules/emojione/lib/js/emojione.js"), __webpack_require__(/*! xss */ "./node_modules/xss/dist/xss.js"), __webpack_require__(/*! templates/action.html */ "./src/templates/action.html"), __webpack_require__(/*! templates/chatbox.html */ "./src/templates/chatbox.html"), __webpack_require__(/*! templates/chatbox_head.html */ "./src/templates/chatbox_head.html"), __webpack_require__(/*! templates/chatbox_message_form.html */ "./src/templates/chatbox_message_form.html"), __webpack_require__(/*! templates/emojis.html */ "./src/templates/emojis.html"), __webpack_require__(/*! templates/error_message.html */ "./src/templates/error_message.html"), __webpack_require__(/*! templates/help_message.html */ "./src/templates/help_message.html"), __webpack_require__(/*! templates/info.html */ "./src/templates/info.html"), __webpack_require__(/*! templates/new_day.html */ "./src/templates/new_day.html"), __webpack_require__(/*! templates/user_details_modal.html */ "./src/templates/user_details_modal.html"), __webpack_require__(/*! templates/toolbar_fileupload.html */ "./src/templates/toolbar_fileupload.html"), __webpack_require__(/*! templates/spinner.html */ "./src/templates/spinner.html"), __webpack_require__(/*! templates/spoiler_button.html */ "./src/templates/spoiler_button.html"), __webpack_require__(/*! templates/status_message.html */ "./src/templates/status_message.html"), __webpack_require__(/*! templates/toolbar.html */ "./src/templates/toolbar.html"), __webpack_require__(/*! converse-modal */ "./src/converse-modal.js"), __webpack_require__(/*! converse-chatboxes */ "./src/converse-chatboxes.js"), __webpack_require__(/*! converse-message-view */ "./src/converse-message-view.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), + !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! converse-core */ "./src/converse-core.js"), __webpack_require__(/*! bootstrap */ "./node_modules/bootstrap.native/dist/bootstrap-native-v4.js"), __webpack_require__(/*! emojione */ "./node_modules/emojione/lib/js/emojione.js"), __webpack_require__(/*! xss */ "./node_modules/xss/dist/xss.js"), __webpack_require__(/*! templates/chatbox.html */ "./src/templates/chatbox.html"), __webpack_require__(/*! templates/chatbox_head.html */ "./src/templates/chatbox_head.html"), __webpack_require__(/*! templates/chatbox_message_form.html */ "./src/templates/chatbox_message_form.html"), __webpack_require__(/*! templates/emojis.html */ "./src/templates/emojis.html"), __webpack_require__(/*! templates/error_message.html */ "./src/templates/error_message.html"), __webpack_require__(/*! templates/help_message.html */ "./src/templates/help_message.html"), __webpack_require__(/*! templates/info.html */ "./src/templates/info.html"), __webpack_require__(/*! templates/new_day.html */ "./src/templates/new_day.html"), __webpack_require__(/*! templates/user_details_modal.html */ "./src/templates/user_details_modal.html"), __webpack_require__(/*! templates/toolbar_fileupload.html */ "./src/templates/toolbar_fileupload.html"), __webpack_require__(/*! templates/spinner.html */ "./src/templates/spinner.html"), __webpack_require__(/*! templates/spoiler_button.html */ "./src/templates/spoiler_button.html"), __webpack_require__(/*! templates/status_message.html */ "./src/templates/status_message.html"), __webpack_require__(/*! templates/toolbar.html */ "./src/templates/toolbar.html"), __webpack_require__(/*! converse-modal */ "./src/converse-modal.js"), __webpack_require__(/*! converse-chatboxes */ "./src/converse-chatboxes.js"), __webpack_require__(/*! converse-message-view */ "./src/converse-message-view.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); -})(void 0, function (converse, bootstrap, emojione, xss, tpl_action, tpl_chatbox, tpl_chatbox_head, tpl_chatbox_message_form, tpl_emojis, tpl_error_message, tpl_help_message, tpl_info, tpl_new_day, tpl_user_details_modal, tpl_toolbar_fileupload, tpl_spinner, tpl_spoiler_button, tpl_status_message, tpl_toolbar) { +})(void 0, function (converse, bootstrap, emojione, xss, tpl_chatbox, tpl_chatbox_head, tpl_chatbox_message_form, tpl_emojis, tpl_error_message, tpl_help_message, tpl_info, tpl_new_day, tpl_user_details_modal, tpl_toolbar_fileupload, tpl_spinner, tpl_spoiler_button, tpl_status_message, tpl_toolbar) { "use strict"; const _converse$env = converse.env, @@ -70055,18 +70055,18 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ date = moment(el.getAttribute('data-isodate')), next_el = el.nextElementSibling; - if (!u.hasClass('chat-action', el) && !u.hasClass('chat-action', previous_el) && previous_el.getAttribute('data-from') === from && date.isBefore(moment(previous_el.getAttribute('data-isodate')).add(10, 'minutes'))) { - u.addClass('chat-msg-followup', el); + if (!u.hasClass('chat-msg--action', el) && !u.hasClass('chat-msg--action', previous_el) && previous_el.getAttribute('data-from') === from && date.isBefore(moment(previous_el.getAttribute('data-isodate')).add(10, 'minutes'))) { + u.addClass('chat-msg--followup', el); } if (!next_el) { return; } - if (!u.hasClass('chat-action', 'el') && next_el.getAttribute('data-from') === from && moment(next_el.getAttribute('data-isodate')).isBefore(date.add(10, 'minutes'))) { - u.addClass('chat-msg-followup', next_el); + if (!u.hasClass('chat-msg--action', 'el') && next_el.getAttribute('data-from') === from && moment(next_el.getAttribute('data-isodate')).isBefore(date.add(10, 'minutes'))) { + u.addClass('chat-msg--followup', next_el); } else { - u.removeClass('chat-msg-followup', next_el); + u.removeClass('chat-msg--followup', next_el); } }, @@ -74581,11 +74581,11 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ // Copyright (c) 2013-2018, the Converse.js developers // Licensed under the Mozilla Public License (MPLv2) (function (root, factory) { - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! converse-core */ "./src/converse-core.js"), __webpack_require__(/*! xss */ "./node_modules/xss/dist/xss.js"), __webpack_require__(/*! emojione */ "./node_modules/emojione/lib/js/emojione.js"), __webpack_require__(/*! filesize */ "./node_modules/filesize/lib/filesize.js"), __webpack_require__(/*! templates/action.html */ "./src/templates/action.html"), __webpack_require__(/*! templates/csn.html */ "./src/templates/csn.html"), __webpack_require__(/*! templates/file_progress.html */ "./src/templates/file_progress.html"), __webpack_require__(/*! templates/info.html */ "./src/templates/info.html"), __webpack_require__(/*! templates/message.html */ "./src/templates/message.html"), __webpack_require__(/*! templates/message_versions_modal.html */ "./src/templates/message_versions_modal.html"), __webpack_require__(/*! templates/spoiler_message.html */ "./src/templates/spoiler_message.html")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), + !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! converse-core */ "./src/converse-core.js"), __webpack_require__(/*! xss */ "./node_modules/xss/dist/xss.js"), __webpack_require__(/*! emojione */ "./node_modules/emojione/lib/js/emojione.js"), __webpack_require__(/*! filesize */ "./node_modules/filesize/lib/filesize.js"), __webpack_require__(/*! templates/csn.html */ "./src/templates/csn.html"), __webpack_require__(/*! templates/file_progress.html */ "./src/templates/file_progress.html"), __webpack_require__(/*! templates/info.html */ "./src/templates/info.html"), __webpack_require__(/*! templates/message.html */ "./src/templates/message.html"), __webpack_require__(/*! templates/message_versions_modal.html */ "./src/templates/message_versions_modal.html")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); -})(void 0, function (converse, xss, emojione, filesize, tpl_action, tpl_csn, tpl_file_progress, tpl_info, tpl_message, tpl_message_versions_modal, tpl_spoiler_message) { +})(void 0, function (converse, xss, emojione, filesize, tpl_csn, tpl_file_progress, tpl_info, tpl_message, tpl_message_versions_modal) { "use strict"; const _converse$env = converse.env, @@ -74654,7 +74654,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ }, render() { - const is_followup = u.hasClass('chat-msg-followup', this.el); + const is_followup = u.hasClass('chat-msg--followup', this.el); let msg; if (this.model.isOnlyChatStateNotification()) { @@ -74668,7 +74668,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ } if (is_followup) { - u.addClass('chat-msg-followup', this.el); + u.addClass('chat-msg--followup', this.el); } return this.el; @@ -74693,21 +74693,13 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ }, renderChatMessage() { - let template, - text = this.model.get('message'); - - if (this.isMeCommand()) { - template = tpl_action; - text = this.model.get('message').replace(/^\/me/, ''); - } else { - template = this.model.get('is_spoiler') ? tpl_spoiler_message : tpl_message; - } - - const moment_time = moment(this.model.get('time')), + const is_me_message = this.isMeCommand(), + moment_time = moment(this.model.get('time')), role = this.model.vcard.get('role'), roles = role ? role.split(',') : []; - const msg = u.stringToElement(template(_.extend(this.model.toJSON(), { + const msg = u.stringToElement(tpl_message(_.extend(this.model.toJSON(), { '__': __, + 'is_me_message': is_me_message, 'roles': roles, 'pretty_time': moment_time.format(_converse.time_format), 'time': moment_time.format(), @@ -74715,13 +74707,19 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ 'label_show': __('Show more'), 'username': this.model.getDisplayName() }))); - var url = this.model.get('oob_url'); + const url = this.model.get('oob_url'); if (url) { - msg.querySelector('.chat-msg-media').innerHTML = _.flow(_.partial(u.renderFileURL, _converse), _.partial(u.renderMovieURL, _converse), _.partial(u.renderAudioURL, _converse), _.partial(u.renderImageURL, _converse))(url); + msg.querySelector('.chat-msg__media').innerHTML = _.flow(_.partial(u.renderFileURL, _converse), _.partial(u.renderMovieURL, _converse), _.partial(u.renderAudioURL, _converse), _.partial(u.renderImageURL, _converse))(url); } - const msg_content = msg.querySelector('.chat-msg-text'); + let text = this.model.get('message'); + + if (is_me_message) { + text = text.replace(/^\/me/, ''); + } + + const msg_content = msg.querySelector('.chat-msg__text'); if (text !== url) { text = xss.filterXSS(text, { @@ -83939,30 +83937,6 @@ if (!String.prototype.trim) { /***/ }), -/***/ "./src/templates/action.html": -/*!***********************************!*\ - !*** ./src/templates/action.html ***! - \***********************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -var _ = {escape:__webpack_require__(/*! ./node_modules/lodash/escape.js */ "./node_modules/lodash/escape.js")}; -module.exports = function(o) { -var __t, __p = '', __e = _.escape; -__p += '\n
\n \n **' + -__e(o.username) + -'\n \n

\n
\n'; -return __p -}; - -/***/ }), - /***/ "./src/templates/add_chatroom_modal.html": /*!***********************************************!*\ !*** ./src/templates/add_chatroom_modal.html ***! @@ -85230,7 +85204,7 @@ __p += '\n
\n \n
\n Uploading file: ' + +'">\n \n
\n Uploading file: ' + __e(o.file.name) + ', ' + __e(o.filesize) + @@ -85699,7 +85673,11 @@ var __t, __p = '', __e = _.escape, __j = Array.prototype.join; function print() { __p += __j.call(arguments, '') } __p += '\n
\n '; - if (o.type !== 'headline') { ; -__p += '\n \n '; + if (o.type !== 'headline' && !o.is_me_message) { ; +__p += '\n \n '; } ; -__p += '\n
\n \n ' + +__p += '\n
\n \n '; + if (o.is_me_message) { ; +__p += ''; + } ; +__p += '\n '; + if (o.is_me_message) { ; +__p += '**'; + }; ; +__p += __e(o.username) + '\n '; o.roles.forEach(function (role) { ; @@ -85719,17 +85713,49 @@ __p += ' ' + __e(role) + ' '; }); ; -__p += '\n \n \n \n '; +''; + } ; +__p += '\n \n '; + if (!o.is_me_message) { ; +__p += '
'; + } ; +__p += ' \n '; if (o.edited) { ; __p += ' '; } ; -__p += '\n \n
\n
\n
\n'; +__p += '\n '; + if (!o.is_me_message) { ; +__p += '
'; + } ; +__p += ' \n '; + if (o.is_spoiler) { ; +__p += '\n
\n ' + +__e(o.spoiler_hint) + +'\n ' + +__e(o.label_show) + +'\n
\n '; + } ; +__p += '\n
\n
\n '; + if (!o.is_me_message) { ; +__p += '
'; + } ; +__p += '\n '; + if (!o.is_me_message) { ; +__p += '
'; + } ; +__p += ' \n
\n
\n'; return __p }; @@ -86751,36 +86777,6 @@ return __p /***/ }), -/***/ "./src/templates/spoiler_message.html": -/*!********************************************!*\ - !*** ./src/templates/spoiler_message.html ***! - \********************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -var _ = {escape:__webpack_require__(/*! ./node_modules/lodash/escape.js */ "./node_modules/lodash/escape.js")}; -module.exports = function(o) { -var __t, __p = '', __e = _.escape; -__p += '\n
\n \n
\n \n ' + -__e(o.username) + -'\n ' + -__e(o.pretty_time) + -'\n \n
\n ' + -__e(o.spoiler_hint) + -'\n ' + -__e(o.label_show) + -'\n
\n \n
\n
\n'; -return __p -}; - -/***/ }), - /***/ "./src/templates/status_message.html": /*!*******************************************!*\ !*** ./src/templates/status_message.html ***! @@ -87275,6 +87271,10 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ return string.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); }; + u.escapeURL = function (url) { + return encodeURI(decodeURI(url)).replace(/[!'()]/g, escape).replace(/\*/g, "%2A"); + }; + u.addHyperlinks = function (text) { return URI.withinString(text, function (url) { var uri = new URI(url); @@ -87284,8 +87284,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ url = 'http://' + url; } - url = encodeURI(decodeURI(url)).replace(/[!'()]/g, escape).replace(/\*/g, "%2A"); - return `${u.escapeHTML(uri.readable())}`; + url = u.escapeHTML(u.escapeURL(url)); + return `${u.escapeHTML(uri.readable())}`; }); }; diff --git a/mockup/chatroom.html b/mockup/chatroom.html index 4fb5ac073..c8ec12ebe 100644 --- a/mockup/chatroom.html +++ b/mockup/chatroom.html @@ -45,8 +45,11 @@ Romeo Montague has entered the room
-
- **Romeo Montague +
+ + + **Romeo Montague + looks around
@@ -177,7 +180,7 @@
-
+
+
I mean, sir, in delay We waste our lights in vain, like lamps by day.
diff --git a/sass/_chatbox.scss b/sass/_chatbox.scss index e7a9fb0fc..a73ebbcd8 100644 --- a/sass/_chatbox.scss +++ b/sass/_chatbox.scss @@ -124,7 +124,7 @@ background-color: $chat-head-color; box-shadow: 1px 3px 5px 3px rgba(0, 0, 0, 0.4); z-index: 1; - overflow-y: scroll; + overflow-y: hidden; width: 100%; @media screen and (max-height: $mobile-landscape-height) { @@ -464,21 +464,6 @@ min-width: $overlayed-chat-width!important; width: $overlayed-chat-width; } - - .chat-body { - .chat-message { - line-height: $line-height-large; - .chat-msg-author { - line-height: $line-height-large; - } - .chat-msg-content { - line-height: $line-height-large; - .emojione { - margin-bottom: -5px; - } - } - } - } } .chatbox { form.sendXMPPMessage { @@ -597,21 +582,6 @@ background-color: $chat-head-color; border-top-left-radius: $chatbox-border-radius; border-top-right-radius: $chatbox-border-radius; - - .chat-message { - line-height: $line-height; - font-size: $font-size-small; - .chat-msg-author { - line-height: $line-height; - } - .chat-msg-content { - line-height: $line-height; - .emojione { - height: $line-height; - margin-bottom: -$line-height/4; - } - } - } } .chat-content { border-top-left-radius: $chatbox-border-radius; diff --git a/sass/_messages.scss b/sass/_messages.scss index 7fb41bcf3..75b5e877d 100644 --- a/sass/_messages.scss +++ b/sass/_messages.scss @@ -104,6 +104,7 @@ whitespace: nowrap; } } + .chat-msg__content { display: flex; flex-direction: column; @@ -112,6 +113,9 @@ margin-left: 0.5rem; width: 100%; } + .chat-msg__content--action { + margin-left: 0; + } .chat-msg__body { display: flex; @@ -126,8 +130,9 @@ width: 100%; } - .chat-msg-edited { + .chat-msg__edit-modal { cursor: pointer; + padding-right: 0.5em; } &.headline { .chat-msg__body { @@ -148,8 +153,9 @@ } } - .chat-msg-media { + .chat-msg__media { margin-top: 0.25rem; + word-break: break-all; a { word-wrap: break-word; } @@ -188,6 +194,7 @@ display: block; .chat-msg__author { + white-space: nowrap; font-family: $heading-font; font-size: 115%; .badge { @@ -202,6 +209,7 @@ } &.chat-msg--action { .chat-msg__content { + flex-wrap: wrap; flex-direction: row; justify-content: flex-start; } @@ -213,6 +221,12 @@ padding-bottom: 0; width: auto; } + .chat-msg__author { + font-size: $message-font-size; + } + .chat-msg__time { + margin-left: 0; + } } &.chat-msg--followup { diff --git a/spec/chatbox.js b/spec/chatbox.js index 388223ae4..2ad792de4 100644 --- a/spec/chatbox.js +++ b/spec/chatbox.js @@ -76,33 +76,33 @@ test_utils.waitUntil(function () { return u.isVisible(view.el); }).then(function () { - expect(view.el.querySelectorAll('.chat-action').length).toBe(1); - expect(_.includes(view.el.querySelector('.chat-msg-author').textContent, '**Max Frankfurter')).toBeTruthy(); - expect($(view.el).find('.chat-msg-text').text()).toBe(' is tired'); + expect(view.el.querySelectorAll('.chat-msg--action').length).toBe(1); + expect(_.includes(view.el.querySelector('.chat-msg__author').textContent, '**Max Frankfurter')).toBeTruthy(); + expect($(view.el).find('.chat-msg__text').text()).toBe(' is tired'); message = '/me is as well'; test_utils.sendMessage(view, message); - expect(view.el.querySelectorAll('.chat-action').length).toBe(2); + expect(view.el.querySelectorAll('.chat-msg--action').length).toBe(2); - return test_utils.waitUntil(() => $(view.el).find('.chat-msg-author:last').text() === '**Max Mustermann'); + return test_utils.waitUntil(() => $(view.el).find('.chat-msg__author:last').text().trim() === '**Max Mustermann'); }).then(function () { - expect($(view.el).find('.chat-msg-text:last').text()).toBe(' is as well'); - expect($(view.el).find('.chat-msg:last').hasClass('chat-msg-followup')).toBe(false); + expect($(view.el).find('.chat-msg__text:last').text()).toBe(' is as well'); + expect($(view.el).find('.chat-msg:last').hasClass('chat-msg--followup')).toBe(false); // Check that /me messages after a normal message don't - // get the 'chat-msg-followup' class. + // get the 'chat-msg--followup' class. message = 'This a normal message'; test_utils.sendMessage(view, message); let message_el = view.el.querySelector('.message:last-child'); - expect(u.hasClass('chat-msg-followup', message_el)).toBeFalsy(); + expect(u.hasClass('chat-msg--followup', message_el)).toBeFalsy(); message = '/me wrote a 3rd person message'; test_utils.sendMessage(view, message); message_el = view.el.querySelector('.message:last-child'); - expect(view.el.querySelectorAll('.chat-action').length).toBe(3); - expect($(view.el).find('.chat-msg-text:last').text()).toBe(' wrote a 3rd person message'); - expect($(view.el).find('.chat-msg-author:last').is(':visible')).toBeTruthy(); - expect(u.hasClass('chat-msg-followup', message_el)).toBeFalsy(); + expect(view.el.querySelectorAll('.chat-msg--action').length).toBe(3); + expect($(view.el).find('.chat-msg__text:last').text()).toBe(' wrote a 3rd person message'); + expect($(view.el).find('.chat-msg__author:last').is(':visible')).toBeTruthy(); + expect(u.hasClass('chat-msg--followup', message_el)).toBeFalsy(); done(); }); }); @@ -1627,7 +1627,7 @@ return $(view.el).find('.chat-content').find('.chat-msg').length; }, 1000).then(function () { expect(view.model.sendMessage).toHaveBeenCalled(); - var msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg-text'); + var msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg__text'); expect(msg.html()).toEqual( '
https://www.openstreetmap.org/?mlat=37.7869'+ diff --git a/spec/chatroom.js b/spec/chatroom.js index f069ec268..c97e0b491 100644 --- a/spec/chatroom.js +++ b/spec/chatroom.js @@ -867,8 +867,8 @@ 'type': 'groupchat' }).c('body').t(message).tree(); view.model.onMessage(msg); - expect(_.includes($(view.el).find('.chat-msg-author').text(), '**Dyon van de Wege')).toBeTruthy(); - expect($(view.el).find('.chat-msg-text').text()).toBe(' is tired'); + expect(_.includes($(view.el).find('.chat-msg__author').text(), '**Dyon van de Wege')).toBeTruthy(); + expect($(view.el).find('.chat-msg__text').text()).toBe(' is tired'); message = '/me is as well'; msg = $msg({ @@ -878,8 +878,8 @@ type: 'groupchat' }).c('body').t(message).tree(); view.model.onMessage(msg); - expect(_.includes($(view.el).find('.chat-msg-author:last').text(), '**Max Mustermann')).toBeTruthy(); - expect($(view.el).find('.chat-msg-text:last').text()).toBe(' is as well'); + expect(_.includes($(view.el).find('.chat-msg__author:last').text(), '**Max Mustermann')).toBeTruthy(); + expect($(view.el).find('.chat-msg__text:last').text()).toBe(' is as well'); done(); }); })); @@ -1545,7 +1545,7 @@ view.model.onMessage(message.nodeTree); var $chat_content = $(view.el).find('.chat-content'); expect($chat_content.find('.chat-msg').length).toBe(1); - expect($chat_content.find('.chat-msg-text').text()).toBe(text); + expect($chat_content.find('.chat-msg__text').text()).toBe(text); expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object)); done(); }); @@ -1583,7 +1583,7 @@ }).c('body').t(text); view.model.onMessage(message.nodeTree); expect($chat_content.find('.chat-msg').length).toBe(1); - expect($chat_content.find('.chat-msg-text').last().text()).toBe(text); + expect($chat_content.find('.chat-msg__text').last().text()).toBe(text); // We don't emit an event if it's our own message expect(_converse.emit.calls.count(), 1); done(); @@ -1624,7 +1624,7 @@ // Now check that the message appears inside the chatbox in the DOM var $chat_content = $(view.el).find('.chat-content'); - var msg_txt = $chat_content.find('.chat-msg:last').find('.chat-msg-text').text(); + var msg_txt = $chat_content.find('.chat-msg:last').find('.chat-msg__text').text(); expect(msg_txt).toEqual(message); expect(view.content.scrollTop).toBe(0); done(); @@ -3475,7 +3475,7 @@ var messages = view.el.querySelectorAll('.message'); expect(messages.length).toBe(8); expect(view.el.querySelectorAll('.chat-msg').length).toBe(1); - expect(view.el.querySelector('.chat-msg .chat-msg-text').textContent).toBe('hello world'); + expect(view.el.querySelector('.chat-msg .chat-msg__text').textContent).toBe('hello world'); // Test that the composing notifications get removed // via timeout. diff --git a/spec/http-file-upload.js b/spec/http-file-upload.js index 707d0520f..077be88b5 100644 --- a/spec/http-file-upload.js +++ b/spec/http-file-upload.js @@ -364,7 +364,7 @@ }, 1000); }).then(function () { // Check that the image renders - expect(view.el.querySelector('.chat-msg .chat-msg-media').innerHTML.trim()).toEqual( + expect(view.el.querySelector('.chat-msg .chat-msg__media').innerHTML.trim()).toEqual( '\n'+ ''+ ''+ @@ -472,7 +472,7 @@ }, 1000); }).then(function () { // Check that the image renders - expect(view.el.querySelector('.chat-msg .chat-msg-media').innerHTML.trim()).toEqual( + expect(view.el.querySelector('.chat-msg .chat-msg__media').innerHTML.trim()).toEqual( '\n'+ ''+ '') @@ -683,7 +683,7 @@ expect(view.el.querySelector('.chat-content progress').getAttribute('value')).toBe('0.5'); message.set('progress', 1); expect(view.el.querySelector('.chat-content progress').getAttribute('value')).toBe('1'); - expect(view.el.querySelector('.chat-content .chat-msg-text').textContent).toBe('Uploading file: my-juliet.jpg, 22.91 KB'); + expect(view.el.querySelector('.chat-content .chat-msg__text').textContent).toBe('Uploading file: my-juliet.jpg, 22.91 KB'); done(); }); var sent_stanza; diff --git a/spec/messages.js b/spec/messages.js index cf90ad2ec..1324f213a 100644 --- a/spec/messages.js +++ b/spec/messages.js @@ -45,7 +45,7 @@ keyCode: 13 // Enter }); expect(view.el.querySelectorAll('.chat-msg').length).toBe(1); - expect(view.el.querySelector('.chat-msg-text').textContent) + expect(view.el.querySelector('.chat-msg__text').textContent) .toBe('But soft, what light through yonder airlock breaks?'); const first_msg = view.model.messages.findWhere({'message': 'But soft, what light through yonder airlock breaks?'}); @@ -152,11 +152,11 @@ expect(textarea.value).toBe(''); const messages = view.el.querySelectorAll('.chat-msg'); expect(messages.length).toBe(3); - expect(messages[0].querySelector('.chat-msg-text').textContent) + expect(messages[0].querySelector('.chat-msg__text').textContent) .toBe('But soft, what light through yonder window breaks?'); - expect(messages[1].querySelector('.chat-msg-text').textContent) + expect(messages[1].querySelector('.chat-msg__text').textContent) .toBe('It is the east, and Juliet is the sun.'); - expect(messages[2].querySelector('.chat-msg-text').textContent) + expect(messages[2].querySelector('.chat-msg__text').textContent) .toBe('Arise, fair sun, and kill the envious moon'); expect(view.model.messages.at(0).get('correcting')).toBeFalsy(); @@ -209,11 +209,11 @@ expect(msg_obj.get('is_delayed')).toEqual(false); // Now check that the message appears inside the chatbox in the DOM const chat_content = chatboxview.el.querySelector('.chat-content'); - expect(chat_content.querySelector('.chat-msg .chat-msg-text').textContent).toEqual(message); - expect(chat_content.querySelector('.chat-msg-time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); + expect(chat_content.querySelector('.chat-msg .chat-msg__text').textContent).toEqual(message); + expect(chat_content.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); return test_utils.waitUntil(() => chatbox.vcard.get('fullname') === mock.cur_names[0]) .then(function () { - expect(chat_content.querySelector('span.chat-msg-author').textContent.trim()).toBe('Max Frankfurter'); + expect(chat_content.querySelector('span.chat-msg__author').textContent.trim()).toBe('Max Frankfurter'); done(); }); }); @@ -240,7 +240,7 @@ var chatboxview = _converse.chatboxviews.get(sender_jid); expect(chatboxview.el.querySelectorAll('.chat-msg').length).toBe(1); - expect(chatboxview.el.querySelector('.chat-msg-text').textContent) + expect(chatboxview.el.querySelector('.chat-msg__text').textContent) .toBe('But soft, what light through yonder airlock breaks?'); _converse.chatboxes.onMessage($msg({ @@ -251,11 +251,11 @@ }).c('body').t('But soft, what light through yonder chimney breaks?').up() .c('replace', {'id': msg_id, 'xmlns': 'urn:xmpp:message-correct:0'}).tree()); - test_utils.waitUntil(() => chatboxview.el.querySelector('.chat-msg-text').textContent === + test_utils.waitUntil(() => chatboxview.el.querySelector('.chat-msg__text').textContent === 'But soft, what light through yonder chimney breaks?').then(() => { expect(chatboxview.el.querySelectorAll('.chat-msg').length).toBe(1); - expect(chatboxview.el.querySelectorAll('.chat-msg-content .fa-edit').length).toBe(1); + expect(chatboxview.el.querySelectorAll('.chat-msg__content .fa-edit').length).toBe(1); _converse.chatboxes.onMessage($msg({ 'from': sender_jid, @@ -265,12 +265,12 @@ }).c('body').t('But soft, what light through yonder window breaks?').up() .c('replace', {'id': msg_id, 'xmlns': 'urn:xmpp:message-correct:0'}).tree()); - return test_utils.waitUntil(() => chatboxview.el.querySelector('.chat-msg-text').textContent === + return test_utils.waitUntil(() => chatboxview.el.querySelector('.chat-msg__text').textContent === 'But soft, what light through yonder window breaks?'); }).then(() => { expect(chatboxview.el.querySelectorAll('.chat-msg').length).toBe(1); - expect(chatboxview.el.querySelectorAll('.chat-msg-content .fa-edit').length).toBe(1); - chatboxview.el.querySelector('.chat-msg-content .fa-edit').click(); + expect(chatboxview.el.querySelectorAll('.chat-msg__content .fa-edit').length).toBe(1); + chatboxview.el.querySelector('.chat-msg__content .fa-edit').click(); const modal = chatboxview.model.messages.at(0).message_versions_modal; return test_utils.waitUntil(() => u.isVisible(modal.el), 1000); }).then(() => { @@ -324,7 +324,7 @@ expect(chatbox).toBeDefined(); expect(chatboxview).toBeDefined(); - var author_el = chatboxview.el.querySelector('.chat-msg-author'); + var author_el = chatboxview.el.querySelector('.chat-msg__author'); expect(chatbox.get('fullname') === sender_jid); expect( _.includes(author_el.textContent.trim(), 'max.frankfurter@localhost')).toBeTruthy(); @@ -333,7 +333,7 @@ expect(_converse.api.vcard.get).toHaveBeenCalled(); return test_utils.waitUntil(() => chatbox.vcard.get('fullname') === mock.cur_names[0]) }).then(function () { - var author_el = chatboxview.el.querySelector('.chat-msg-author'); + var author_el = chatboxview.el.querySelector('.chat-msg__author'); expect( _.includes(author_el.textContent.trim(), 'Max Frankfurter')).toBeTruthy(); done(); }); @@ -389,9 +389,9 @@ expect(msg_obj.get('is_delayed')).toEqual(false); // Now check that the message appears inside the chatbox in the DOM var chat_content = chatboxview.el.querySelector('.chat-content'); - expect(chat_content.querySelector('.chat-msg .chat-msg-text').textContent).toEqual(message); - expect(chat_content.querySelector('.chat-msg-time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); - expect(chat_content.querySelector('span.chat-msg-author').textContent.trim()).toBe('max.frankfurter@localhost'); + expect(chat_content.querySelector('.chat-msg .chat-msg__text').textContent).toEqual(message); + expect(chat_content.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); + expect(chat_content.querySelector('span.chat-msg__author').textContent.trim()).toBe('max.frankfurter@localhost'); done(); })); }); @@ -436,7 +436,7 @@ }); view.model.sendMessage(message); var $chat_content = $(view.el).find('.chat-content'); - var msg_txt = $chat_content.find('.chat-msg:last').find('.chat-msg-text').text(); + var msg_txt = $chat_content.find('.chat-msg:last').find('.chat-msg__text').text(); expect(msg_txt).toEqual(msg_text); // We send another message, for which an error will @@ -451,7 +451,7 @@ 'message': msg_text }); view.model.sendMessage(message); - msg_txt = $chat_content.find('.chat-msg:last').find('.chat-msg-text').text(); + msg_txt = $chat_content.find('.chat-msg:last').find('.chat-msg__text').text(); expect(msg_txt).toEqual(msg_text); /* chatbox.vcard.get('fullname') === 'Candice van der Knijff') .then(function () { - expect(chat_content.querySelector('span.chat-msg-author').textContent.trim()).toBe('Candice van der Knijff'); + expect(chat_content.querySelector('span.chat-msg__author').textContent.trim()).toBe('Candice van der Knijff'); done(); }); })); @@ -917,16 +917,15 @@ null, ['rosterGroupsFetched'], {}, function (done, _converse) { - var contact, sent_stanza, IQ_id, stanza; test_utils.waitUntilDiscoConfirmed(_converse, 'localhost', [], ['vcard-temp']).then(function () { test_utils.createContacts(_converse, 'current'); test_utils.openControlBox(); // Send a message from a different resource spyOn(_converse, 'log'); - var msgtext = 'This is a sent carbon message'; - var recipient_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost'; - var msg = $msg({ + const msgtext = 'This is a sent carbon message'; + const recipient_jid = mock.cur_names[5].replace(/ /g,'.').toLowerCase() + '@localhost'; + const msg = $msg({ 'from': _converse.bare_jid, 'id': (new Date()).getTime(), 'to': _converse.connection.jid, @@ -943,20 +942,19 @@ _converse.chatboxes.onMessage(msg); // Check that the chatbox and its view now exist - var chatbox = _converse.chatboxes.get(recipient_jid); - var chatboxview = _converse.chatboxviews.get(recipient_jid); + const chatbox = _converse.chatboxes.get(recipient_jid); + const chatboxview = _converse.chatboxviews.get(recipient_jid); expect(chatbox).toBeDefined(); expect(chatboxview).toBeDefined(); // Check that the message was received and check the message parameters expect(chatbox.messages.length).toEqual(1); - var msg_obj = chatbox.messages.models[0]; + const msg_obj = chatbox.messages.models[0]; expect(msg_obj.get('message')).toEqual(msgtext); expect(msg_obj.get('fullname')).toEqual(_converse.xmppstatus.get('fullname')); expect(msg_obj.get('sender')).toEqual('me'); expect(msg_obj.get('is_delayed')).toEqual(false); // Now check that the message appears inside the chatbox in the DOM - var $chat_content = $(chatboxview.el).find('.chat-content'); - var msg_txt = $chat_content.find('.chat-msg').find('.chat-msg-text').text(); + const msg_txt = chatboxview.el.querySelector('.chat-content .chat-msg .chat-msg__text').textContent; expect(msg_txt).toEqual(msgtext); done(); }); @@ -1014,6 +1012,9 @@ null, ['rosterGroupsFetched'], {}, function (done, _converse) { + if (_converse.view_mode === 'fullscreen') { + return done(); + } test_utils.createContacts(_converse, 'current'); test_utils.openControlBox(); test_utils.waitUntil(function () { @@ -1089,7 +1090,6 @@ var message = 'This is a day old message'; var chatbox = _converse.chatboxes.get(contact_jid); var chatboxview = _converse.chatboxviews.get(contact_jid); - var $chat_content = $(chatboxview.el).find('.chat-content'); var msg_obj; var msg_txt; var sender_txt; @@ -1113,16 +1113,17 @@ return test_utils.waitUntil(() => chatbox.vcard.get('fullname') === 'Candice van der Knijff') .then(function () { - var chat_content = chatboxview.el.querySelector('.chat-content'); - expect(chat_content.querySelector('.chat-msg .chat-msg-text').textContent).toEqual(message); - expect(chat_content.querySelector('.chat-msg-time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); - expect(chat_content.querySelector('span.chat-msg-author').textContent.trim()).toBe('Candice van der Knijff'); + const chat_content = chatboxview.el.querySelector('.chat-content'); + expect(chat_content.querySelector('.chat-msg .chat-msg__text').textContent).toEqual(message); + expect(chat_content.querySelector('.chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); + expect(chat_content.querySelector('span.chat-msg__author').textContent.trim()).toBe('Candice van der Knijff'); - var $day = $chat_content.find('.date-separator'); - expect($day.length).toEqual(1); - expect($day.attr('class')).toEqual('message date-separator'); - expect($day.data('isodate')).toEqual(moment(one_day_ago.startOf('day')).format()); + expect(chat_content.querySelectorAll('.date-separator').length).toEqual(1); + const day = chat_content.querySelector('.date-separator'); + expect(day.getAttribute('class')).toEqual('message date-separator'); + expect(day.getAttribute('data-isodate')).toEqual(moment(one_day_ago.startOf('day')).format()); + const $chat_content = $(chat_content); var $time = $chat_content.find('time.separator-text'); expect($time.text()).toEqual(moment(one_day_ago.startOf('day')).format("dddd MMM Do YYYY")); @@ -1141,7 +1142,7 @@ expect($chat_content[0].querySelectorAll('time.separator-text').length).toEqual(2); // There are now two time elements var message_date = new Date(); - $day = $chat_content.find('.date-separator:last'); + const $day = $chat_content.find('.date-separator:last'); expect($day.length).toEqual(1); expect($day.attr('class')).toEqual('message date-separator'); expect($day.data('isodate')).toEqual(moment(message_date).startOf('day').format()); @@ -1156,12 +1157,12 @@ expect(msg_obj.get('fullname')).toEqual(contact_name); expect(msg_obj.get('sender')).toEqual('them'); expect(msg_obj.get('is_delayed')).toEqual(false); - msg_txt = $chat_content.find('.chat-msg').last().find('.chat-msg-text').text(); + msg_txt = $chat_content.find('.chat-msg').last().find('.chat-msg__text').text(); expect(msg_txt).toEqual(message); - expect(chat_content.querySelector('.chat-msg:last-child .chat-msg-text').textContent).toEqual(message); - expect(chat_content.querySelector('.chat-msg:last-child .chat-msg-time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); - expect(chat_content.querySelector('.chat-msg:last-child .chat-msg-author').textContent.trim()).toBe('Candice van der Knijff'); + expect(chat_content.querySelector('.chat-msg:last-child .chat-msg__text').textContent).toEqual(message); + expect(chat_content.querySelector('.chat-msg:last-child .chat-msg__time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy(); + expect(chat_content.querySelector('.chat-msg:last-child .chat-msg__author').textContent.trim()).toBe('Candice van der Knijff'); done(); }); }); @@ -1186,7 +1187,7 @@ expect(view.model.sendMessage).toHaveBeenCalled(); expect(view.model.messages.length, 2); expect(_converse.emit.calls.mostRecent().args, ['messageSend', message]); - expect($(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg-text').text()).toEqual(message); + expect($(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg__text').text()).toEqual(message); done(); })); @@ -1205,7 +1206,7 @@ spyOn(view.model, 'sendMessage').and.callThrough(); test_utils.sendMessage(view, message); expect(view.model.sendMessage).toHaveBeenCalled(); - var msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg-text'); + var msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg__text'); expect(msg.text()).toEqual(message); expect(msg.html()).toEqual('<p>This message contains <em>some</em> <b>markup</b></p>'); done(); @@ -1226,7 +1227,7 @@ spyOn(view.model, 'sendMessage').and.callThrough(); test_utils.sendMessage(view, message); expect(view.model.sendMessage).toHaveBeenCalled(); - var msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg-text'); + var msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg__text'); expect(msg.text()).toEqual(message); expect(msg.html()).toEqual('This message contains a hyperlink: www.opkode.com'); done(); @@ -1248,14 +1249,14 @@ message = "http://www.opkode.com/'onmouseover='alert(1)'whatever"; test_utils.sendMessage(view, message); expect(view.model.sendMessage).toHaveBeenCalled(); - msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg-text'); + msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg__text'); expect(msg.text()).toEqual(message); expect(msg.html()).toEqual('http://www.opkode.com/\'onmouseover=\'alert(1)\'whatever'); message = 'http://www.opkode.com/"onmouseover="alert(1)"whatever'; test_utils.sendMessage(view, message); expect(view.model.sendMessage).toHaveBeenCalled(); - msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg-text'); + msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg__text'); expect(msg.text()).toEqual(message); expect(msg.html()).toEqual('http://www.opkode.com/"onmouseover="alert(1)"whatever'); @@ -1263,7 +1264,7 @@ test_utils.sendMessage(view, message); expect(view.model.sendMessage).toHaveBeenCalled(); - msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg-text'); + msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg__text'); expect(msg.text()).toEqual(message); expect(msg.html()).toEqual(''+message+''); @@ -1271,7 +1272,7 @@ test_utils.sendMessage(view, message); expect(view.model.sendMessage).toHaveBeenCalled(); - msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg-text'); + msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg__text'); expect(msg.text()).toEqual(message); expect(msg.html()).toEqual(''+message+''); done(); @@ -1292,7 +1293,7 @@ const view = _converse.chatboxviews.get(contact_jid); const chat_content = view.el.querySelector('.chat-content'); - expect(chat_content.querySelector('.chat-msg-text').innerHTML).toBe('Hey
Have you heard the news?'); + expect(chat_content.querySelector('.chat-msg__text').innerHTML).toBe('Hey
Have you heard the news?'); stanza = Strophe.xmlHtmlNode( "Hey\n\n\nHave you heard the news?"+ "").firstChild; _converse.connection._dataRecv(test_utils.createRequest(stanza)); - expect(chat_content.querySelector('.message:last-child .chat-msg-text').innerHTML).toBe('Hey

Have you heard the news?'); + expect(chat_content.querySelector('.message:last-child .chat-msg__text').innerHTML).toBe('Hey

Have you heard the news?'); stanza = Strophe.xmlHtmlNode( "Hey\nHave you heard\nthe news?"+ "").firstChild; _converse.connection._dataRecv(test_utils.createRequest(stanza)); - expect(chat_content.querySelector('.message:last-child .chat-msg-text').innerHTML).toBe('Hey
Have you heard
the news?'); + expect(chat_content.querySelector('.message:last-child .chat-msg__text').innerHTML).toBe('Hey
Have you heard
the news?'); done(); })); @@ -1319,18 +1320,18 @@ null, ['rosterGroupsFetched'], {}, function (done, _converse) { - test_utils.createContacts(_converse, 'current'); - var base_url = document.URL.split(window.location.pathname)[0]; - var message = base_url+"/logo/conversejs-filled.svg"; - var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; + test_utils.createContacts(_converse, 'current', 1); + const base_url = document.URL.split(window.location.pathname)[0]; + let message = base_url+"/logo/conversejs-filled.svg"; + const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; test_utils.openChatBoxFor(_converse, contact_jid); - var view = _converse.chatboxviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); spyOn(view.model, 'sendMessage').and.callThrough(); test_utils.sendMessage(view, message); test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-image').length, 1000).then(() => { expect(view.model.sendMessage).toHaveBeenCalled(); - var msg = $(view.el).find('.chat-content .chat-msg').last().find('.chat-msg-text'); + const msg = $(view.el).find('.chat-content .chat-msg').last().find('.chat-msg__text'); expect(msg.html().trim()).toEqual( '\n'+ ' view.el.querySelectorAll('.chat-content .chat-image').length === 2, 1000); }).then(() => { expect(view.model.sendMessage).toHaveBeenCalled(); - var msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg-text'); + const msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg__text'); expect(msg.html().trim()).toEqual( '\n'+ ' view.el.querySelectorAll('.chat-content .chat-image').length === 4, 1000); }).then(function () { expect(view.model.sendMessage).toHaveBeenCalled(); - var msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg-text'); + const msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg__text'); expect(msg[0].textContent.trim()).toEqual('hello world'); expect(msg[0].querySelectorAll('img').length).toEqual(2); done(); @@ -1377,10 +1378,10 @@ expect(chatbox.messages.models.length, 1); var msg_object = chatbox.messages.models[0]; - var msg_author = view.el.querySelector('.chat-content .chat-msg:last-child .chat-msg-author'); + var msg_author = view.el.querySelector('.chat-content .chat-msg:last-child .chat-msg__author'); expect(msg_author.textContent.trim()).toBe('Max Mustermann'); - var msg_time = view.el.querySelector('.chat-content .chat-msg:last-child .chat-msg-time'); + var msg_time = view.el.querySelector('.chat-content .chat-msg:last-child .chat-msg__time'); var time = moment(msg_object.get('time')).format(_converse.time_format); expect(msg_time.textContent).toBe(time); done(); @@ -1394,7 +1395,7 @@ test_utils.createContacts(_converse, 'current'); test_utils.openControlBox(); - test_utils.waitUntil(() => $(_converse.rosterview.el).find('.roster-group').length, 300) + test_utils.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length, 300) .then(function () { const base_time = new Date(); const ONE_MINUTE_LATER = 60000; @@ -1468,19 +1469,19 @@ var chat_content = view.el.querySelector('.chat-content'); expect(chat_content.querySelectorAll('.message').length).toBe(6); expect(chat_content.querySelectorAll('.chat-msg').length).toBe(5); - expect(u.hasClass('chat-msg-followup', chat_content.querySelector('.message:nth-child(2)'))).toBe(false); - expect(chat_content.querySelector('.message:nth-child(2) .chat-msg-text').textContent).toBe("A message"); - expect(u.hasClass('chat-msg-followup', chat_content.querySelector('.message:nth-child(3)'))).toBe(true); - expect(chat_content.querySelector('.message:nth-child(3) .chat-msg-text').textContent).toBe( + expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(2)'))).toBe(false); + expect(chat_content.querySelector('.message:nth-child(2) .chat-msg__text').textContent).toBe("A message"); + expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(3)'))).toBe(true); + expect(chat_content.querySelector('.message:nth-child(3) .chat-msg__text').textContent).toBe( "Another message 3 minutes later"); - expect(u.hasClass('chat-msg-followup', chat_content.querySelector('.message:nth-child(4)'))).toBe(false); - expect(chat_content.querySelector('.message:nth-child(4) .chat-msg-text').textContent).toBe( + expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(4)'))).toBe(false); + expect(chat_content.querySelector('.message:nth-child(4) .chat-msg__text').textContent).toBe( "Another message 14 minutes since we started"); - expect(u.hasClass('chat-msg-followup', chat_content.querySelector('.message:nth-child(5)'))).toBe(true); - expect(chat_content.querySelector('.message:nth-child(5) .chat-msg-text').textContent).toBe( + expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(5)'))).toBe(true); + expect(chat_content.querySelector('.message:nth-child(5) .chat-msg__text').textContent).toBe( "Another message 1 minute and 1 second since the previous one"); - expect(u.hasClass('chat-msg-followup', chat_content.querySelector('.message:nth-child(6)'))).toBe(false); - expect(chat_content.querySelector('.message:nth-child(6) .chat-msg-text').textContent).toBe( + expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(6)'))).toBe(false); + expect(chat_content.querySelector('.message:nth-child(6) .chat-msg__text').textContent).toBe( "Another message within 10 minutes, but from a different person"); // Let's add a delayed, inbetween message @@ -1499,21 +1500,21 @@ expect(chat_content.querySelectorAll('.message').length).toBe(7); expect(chat_content.querySelectorAll('.chat-msg').length).toBe(6); - expect(u.hasClass('chat-msg-followup', chat_content.querySelector('.message:nth-child(2)'))).toBe(false); - expect(chat_content.querySelector('.message:nth-child(2) .chat-msg-text').textContent).toBe("A message"); - expect(u.hasClass('chat-msg-followup', chat_content.querySelector('.message:nth-child(3)'))).toBe(true); - expect(chat_content.querySelector('.message:nth-child(3) .chat-msg-text').textContent).toBe( + expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(2)'))).toBe(false); + expect(chat_content.querySelector('.message:nth-child(2) .chat-msg__text').textContent).toBe("A message"); + expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(3)'))).toBe(true); + expect(chat_content.querySelector('.message:nth-child(3) .chat-msg__text').textContent).toBe( "Another message 3 minutes later"); - expect(u.hasClass('chat-msg-followup', chat_content.querySelector('.message:nth-child(4)'))).toBe(true); - expect(chat_content.querySelector('.message:nth-child(4) .chat-msg-text').textContent).toBe( + expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(4)'))).toBe(true); + expect(chat_content.querySelector('.message:nth-child(4) .chat-msg__text').textContent).toBe( "A delayed message, sent 5 minutes since we started"); - expect(u.hasClass('chat-msg-followup', chat_content.querySelector('.message:nth-child(5)'))).toBe(true); - expect(chat_content.querySelector('.message:nth-child(5) .chat-msg-text').textContent).toBe( + expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(5)'))).toBe(true); + expect(chat_content.querySelector('.message:nth-child(5) .chat-msg__text').textContent).toBe( "Another message 14 minutes since we started"); - expect(u.hasClass('chat-msg-followup', chat_content.querySelector('.message:nth-child(6)'))).toBe(true); - expect(chat_content.querySelector('.message:nth-child(6) .chat-msg-text').textContent).toBe( + expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(6)'))).toBe(true); + expect(chat_content.querySelector('.message:nth-child(6) .chat-msg__text').textContent).toBe( "Another message 1 minute and 1 second since the previous one"); - expect(u.hasClass('chat-msg-followup', chat_content.querySelector('.message:nth-child(7)'))).toBe(false); + expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(7)'))).toBe(false); _converse.chatboxes.onMessage($msg({'id': 'aeb213', 'to': _converse.bare_jid}) .c('forwarded', {'xmlns': 'urn:xmpp:forward:0'}) @@ -1527,25 +1528,25 @@ .tree()); expect(chat_content.querySelectorAll('.message').length).toBe(8); expect(chat_content.querySelectorAll('.chat-msg').length).toBe(7); - expect(u.hasClass('chat-msg-followup', chat_content.querySelector('.message:nth-child(2)'))).toBe(false); - expect(chat_content.querySelector('.message:nth-child(2) .chat-msg-text').textContent).toBe("A message"); - expect(u.hasClass('chat-msg-followup', chat_content.querySelector('.message:nth-child(3)'))).toBe(true); - expect(chat_content.querySelector('.message:nth-child(3) .chat-msg-text').textContent).toBe( + expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(2)'))).toBe(false); + expect(chat_content.querySelector('.message:nth-child(2) .chat-msg__text').textContent).toBe("A message"); + expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(3)'))).toBe(true); + expect(chat_content.querySelector('.message:nth-child(3) .chat-msg__text').textContent).toBe( "Another message 3 minutes later"); - expect(u.hasClass('chat-msg-followup', chat_content.querySelector('.message:nth-child(4)'))).toBe(false); - expect(chat_content.querySelector('.message:nth-child(4) .chat-msg-text').textContent).toBe( + expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(4)'))).toBe(false); + expect(chat_content.querySelector('.message:nth-child(4) .chat-msg__text').textContent).toBe( "A carbon message 4 minutes later"); - expect(u.hasClass('chat-msg-followup', chat_content.querySelector('.message:nth-child(5)'))).toBe(false); - expect(chat_content.querySelector('.message:nth-child(5) .chat-msg-text').textContent).toBe( + expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(5)'))).toBe(false); + expect(chat_content.querySelector('.message:nth-child(5) .chat-msg__text').textContent).toBe( "A delayed message, sent 5 minutes since we started"); - expect(u.hasClass('chat-msg-followup', chat_content.querySelector('.message:nth-child(6)'))).toBe(true); - expect(chat_content.querySelector('.message:nth-child(6) .chat-msg-text').textContent).toBe( + expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(6)'))).toBe(true); + expect(chat_content.querySelector('.message:nth-child(6) .chat-msg__text').textContent).toBe( "Another message 14 minutes since we started"); - expect(u.hasClass('chat-msg-followup', chat_content.querySelector('.message:nth-child(7)'))).toBe(true); - expect(chat_content.querySelector('.message:nth-child(7) .chat-msg-text').textContent).toBe( + expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(7)'))).toBe(true); + expect(chat_content.querySelector('.message:nth-child(7) .chat-msg__text').textContent).toBe( "Another message 1 minute and 1 second since the previous one"); - expect(u.hasClass('chat-msg-followup', chat_content.querySelector('.message:nth-child(8)'))).toBe(false); - expect(chat_content.querySelector('.message:nth-child(8) .chat-msg-text').textContent).toBe( + expect(u.hasClass('chat-msg--followup', chat_content.querySelector('.message:nth-child(8)'))).toBe(false); + expect(chat_content.querySelector('.message:nth-child(8) .chat-msg__text').textContent).toBe( "Another message within 10 minutes, but from a different person"); jasmine.clock().uninstall(); @@ -1561,13 +1562,13 @@ null, ['rosterGroupsFetched'], {}, function (done, _converse) { - test_utils.createContacts(_converse, 'current'); - var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; + test_utils.createContacts(_converse, 'current', 1); + const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; test_utils.openChatBoxFor(_converse, contact_jid); - var view = _converse.chatboxviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); spyOn(view.model, 'sendMessage').and.callThrough(); - var stanza = Strophe.xmlHtmlNode( + const stanza = Strophe.xmlHtmlNode( ""+ @@ -1576,19 +1577,17 @@ "").firstChild; _converse.connection._dataRecv(test_utils.createRequest(stanza)); - test_utils.waitUntil(function () { - return view.el.querySelectorAll('.chat-content .chat-msg audio').length; - }, 1000).then(function () { - var msg = view.el.querySelector('.chat-msg .chat-msg-text'); - expect(msg.outerHTML).toEqual('Have you heard this funny audio?'); - var media = view.el.querySelector('.chat-msg .chat-msg-media'); + test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-msg audio').length, 1000).then(function () { + let msg = view.el.querySelector('.chat-msg .chat-msg__text'); + expect(msg.outerHTML).toEqual('
Have you heard this funny audio?
'); + let media = view.el.querySelector('.chat-msg .chat-msg__media'); expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual( ''+ ''+ '
Download audio file'); // If the and contents is the same, don't duplicate. - var stanza = Strophe.xmlHtmlNode( + const stanza = Strophe.xmlHtmlNode( ""+ @@ -1597,9 +1596,9 @@ "").firstChild; _converse.connection._dataRecv(test_utils.createRequest(stanza)); - msg = view.el.querySelector('.chat-msg:last-child .chat-msg-text'); - expect(msg.innerHTML).toEqual(''); - media = view.el.querySelector('.chat-msg:last-child .chat-msg-media'); + msg = view.el.querySelector('.chat-msg:last-child .chat-msg__text'); + expect(msg.innerHTML).toEqual(''); // Emtpy + media = view.el.querySelector('.chat-msg:last-child .chat-msg__media'); expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual( ''+ ''+ @@ -1614,12 +1613,12 @@ function (done, _converse) { test_utils.createContacts(_converse, 'current'); - var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; + const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; test_utils.openChatBoxFor(_converse, contact_jid); - var view = _converse.chatboxviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); spyOn(view.model, 'sendMessage').and.callThrough(); - var stanza = Strophe.xmlHtmlNode( + const stanza = Strophe.xmlHtmlNode( ""+ @@ -1628,19 +1627,17 @@ "").firstChild; _converse.connection._dataRecv(test_utils.createRequest(stanza)); - test_utils.waitUntil(function () { - return view.el.querySelectorAll('.chat-content .chat-msg video').length; - }, 2000).then(function () { - var msg = view.el.querySelector('.chat-msg .chat-msg-text'); - expect(msg.outerHTML).toEqual('Have you seen this funny video?'); - var media = view.el.querySelector('.chat-msg .chat-msg-media'); + test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-msg video').length, 2000).then(function () { + let msg = view.el.querySelector('.chat-msg .chat-msg__text'); + expect(msg.outerHTML).toEqual('
Have you seen this funny video?
'); + let media = view.el.querySelector('.chat-msg .chat-msg__media'); expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual( ''+ ''+ 'Download video file'); // If the and contents is the same, don't duplicate. - var stanza = Strophe.xmlHtmlNode( + const stanza = Strophe.xmlHtmlNode( ""+ @@ -1649,9 +1646,9 @@ "").firstChild; _converse.connection._dataRecv(test_utils.createRequest(stanza)); - msg = view.el.querySelector('.chat-msg:last-child .chat-msg-text'); - expect(msg.innerHTML).toEqual(''); - media = view.el.querySelector('.chat-msg:last-child .chat-msg-media'); + msg = view.el.querySelector('.chat-msg:last-child .chat-msg__text'); + expect(msg.innerHTML).toEqual(''); // Emtpy + media = view.el.querySelector('.chat-msg:last-child .chat-msg__media'); expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual( ''+ ''+ @@ -1665,13 +1662,13 @@ null, ['rosterGroupsFetched'], {}, function (done, _converse) { - test_utils.createContacts(_converse, 'current'); - var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; + test_utils.createContacts(_converse, 'current', 1); + const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; test_utils.openChatBoxFor(_converse, contact_jid); - var view = _converse.chatboxviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); spyOn(view.model, 'sendMessage').and.callThrough(); - var stanza = Strophe.xmlHtmlNode( + const stanza = Strophe.xmlHtmlNode( ""+ @@ -1680,12 +1677,10 @@ "").firstChild; _converse.connection._dataRecv(test_utils.createRequest(stanza)); - test_utils.waitUntil(function () { - return view.el.querySelectorAll('.chat-content .chat-msg a').length; - }, 1000).then(function () { - var msg = view.el.querySelector('.chat-msg .chat-msg-text'); - expect(msg.outerHTML).toEqual('Have you downloaded this funny file?'); - var media = view.el.querySelector('.chat-msg .chat-msg-media'); + test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-msg a').length, 1000).then(function () { + const msg = view.el.querySelector('.chat-msg .chat-msg__text'); + expect(msg.outerHTML).toEqual('
Have you downloaded this funny file?
'); + const media = view.el.querySelector('.chat-msg .chat-msg__media'); expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual( ''+ 'Download "funny.pdf"'); @@ -1699,14 +1694,14 @@ function (done, _converse) { test_utils.createContacts(_converse, 'current'); - var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; + const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; test_utils.openChatBoxFor(_converse, contact_jid); - var view = _converse.chatboxviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); spyOn(view.model, 'sendMessage').and.callThrough(); - var base_url = document.URL.split(window.location.pathname)[0]; - var url = base_url+"/logo/conversejs-filled.svg"; + const base_url = document.URL.split(window.location.pathname)[0]; + const url = base_url+"/logo/conversejs-filled.svg"; - var stanza = Strophe.xmlHtmlNode( + const stanza = Strophe.xmlHtmlNode( ""+ @@ -1715,12 +1710,10 @@ "").firstChild; _converse.connection._dataRecv(test_utils.createRequest(stanza)); - test_utils.waitUntil(function () { - return view.el.querySelectorAll('.chat-content .chat-msg img').length; - }, 2000).then(function () { - var msg = view.el.querySelector('.chat-msg .chat-msg-text'); - expect(msg.outerHTML).toEqual('Have you seen this funny image?'); - var media = view.el.querySelector('.chat-msg .chat-msg-media'); + test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-msg img').length, 2000).then(function () { + const msg = view.el.querySelector('.chat-msg .chat-msg__text'); + expect(msg.outerHTML).toEqual('
Have you seen this funny image?
'); + const media = view.el.querySelector('.chat-msg .chat-msg__media'); expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual( ''+ ''+ @@ -1768,7 +1761,7 @@ }).c('body').t('But soft, what light through yonder airlock breaks?').tree()); expect(view.el.querySelectorAll('.chat-msg').length).toBe(1); - expect(view.el.querySelector('.chat-msg-text').textContent) + expect(view.el.querySelector('.chat-msg__text').textContent) .toBe('But soft, what light through yonder airlock breaks?'); view.model.onMessage($msg({ @@ -1779,11 +1772,11 @@ }).c('body').t('But soft, what light through yonder chimney breaks?').up() .c('replace', {'id': msg_id, 'xmlns': 'urn:xmpp:message-correct:0'}).tree()); - return test_utils.waitUntil(() => view.el.querySelector('.chat-msg-text').textContent === + return test_utils.waitUntil(() => view.el.querySelector('.chat-msg__text').textContent === 'But soft, what light through yonder chimney breaks?'); }).then(() => { expect(view.el.querySelectorAll('.chat-msg').length).toBe(1); - expect(view.el.querySelectorAll('.chat-msg-content .fa-edit').length).toBe(1); + expect(view.el.querySelectorAll('.chat-msg__content .fa-edit').length).toBe(1); view.model.onMessage($msg({ 'from': 'lounge@localhost/newguy', @@ -1793,12 +1786,12 @@ }).c('body').t('But soft, what light through yonder window breaks?').up() .c('replace', {'id': msg_id, 'xmlns': 'urn:xmpp:message-correct:0'}).tree()); - return test_utils.waitUntil(() => view.el.querySelector('.chat-msg-text').textContent === + return test_utils.waitUntil(() => view.el.querySelector('.chat-msg__text').textContent === 'But soft, what light through yonder window breaks?'); }).then(() => { expect(view.el.querySelectorAll('.chat-msg').length).toBe(1); - expect(view.el.querySelectorAll('.chat-msg-content .fa-edit').length).toBe(1); - view.el.querySelector('.chat-msg-content .fa-edit').click(); + expect(view.el.querySelectorAll('.chat-msg__content .fa-edit').length).toBe(1); + view.el.querySelector('.chat-msg__content .fa-edit').click(); const modal = view.model.messages.at(0).message_versions_modal; return test_utils.waitUntil(() => u.isVisible(modal.el), 1000); }).then(() => { @@ -1838,7 +1831,7 @@ keyCode: 13 // Enter }); expect(view.el.querySelectorAll('.chat-msg').length).toBe(1); - expect(view.el.querySelector('.chat-msg-text').textContent) + expect(view.el.querySelector('.chat-msg__text').textContent) .toBe('But soft, what light through yonder airlock breaks?'); const first_msg = view.model.messages.findWhere({'message': 'But soft, what light through yonder airlock breaks?'}); diff --git a/spec/spoilers.js b/spec/spoilers.js index 79c969548..a63789855 100644 --- a/spec/spoilers.js +++ b/spec/spoilers.js @@ -40,9 +40,9 @@ return test_utils.waitUntil(() => view.model.vcard.get('fullname') === 'Max Frankfurter') .then(function () { - expect(view.el.querySelector('.chat-msg-author').textContent).toBe('Max Frankfurter'); + expect(view.el.querySelector('.chat-msg__author').textContent.trim()).toBe('Max Frankfurter'); - var message_content = view.el.querySelector('.chat-msg-text'); + var message_content = view.el.querySelector('.chat-msg__text'); expect(message_content.textContent).toBe(spoiler); var spoiler_hint_el = view.el.querySelector('.spoiler-hint'); @@ -79,9 +79,9 @@ var view = _converse.chatboxviews.get(sender_jid); return test_utils.waitUntil(() => view.model.vcard.get('fullname') === 'Max Frankfurter') .then(function () { - expect(_.includes(view.el.querySelector('.chat-msg-author').textContent, 'Max Frankfurter')).toBeTruthy(); + expect(_.includes(view.el.querySelector('.chat-msg__author').textContent, 'Max Frankfurter')).toBeTruthy(); - var message_content = view.el.querySelector('.chat-msg-text'); + var message_content = view.el.querySelector('.chat-msg__text'); expect(message_content.textContent).toBe(spoiler); var spoiler_hint_el = view.el.querySelector('.spoiler-hint'); @@ -148,9 +148,9 @@ expect(body_el.textContent).toBe('This is the spoiler'); /* Test the HTML spoiler message */ - expect(view.el.querySelector('.chat-msg-author').textContent).toBe('Max Mustermann'); + expect(view.el.querySelector('.chat-msg__author').textContent.trim()).toBe('Max Mustermann'); - var spoiler_msg_el = view.el.querySelector('.chat-msg-text.spoiler'); + var spoiler_msg_el = view.el.querySelector('.chat-msg__text.spoiler'); expect(spoiler_msg_el.textContent).toBe('This is the spoiler'); expect(_.includes(spoiler_msg_el.classList, 'collapsed')).toBeTruthy(); @@ -227,9 +227,9 @@ expect(body_el.textContent).toBe('This is the spoiler'); /* Test the HTML spoiler message */ - expect(view.el.querySelector('.chat-msg-author').textContent).toBe('Max Mustermann'); + expect(view.el.querySelector('.chat-msg__author').textContent.trim()).toBe('Max Mustermann'); - var spoiler_msg_el = view.el.querySelector('.chat-msg-text.spoiler'); + var spoiler_msg_el = view.el.querySelector('.chat-msg__text.spoiler'); expect(spoiler_msg_el.textContent).toBe('This is the spoiler'); expect(_.includes(spoiler_msg_el.classList, 'collapsed')).toBeTruthy(); diff --git a/src/converse-chatview.js b/src/converse-chatview.js index 77bdfb63c..7bd2e6e96 100644 --- a/src/converse-chatview.js +++ b/src/converse-chatview.js @@ -9,7 +9,6 @@ "bootstrap", "emojione", "xss", - "templates/action.html", "templates/chatbox.html", "templates/chatbox_head.html", "templates/chatbox_message_form.html", @@ -33,7 +32,6 @@ bootstrap, emojione, xss, - tpl_action, tpl_chatbox, tpl_chatbox_head, tpl_chatbox_message_form, @@ -747,19 +745,19 @@ date = moment(el.getAttribute('data-isodate')), next_el = el.nextElementSibling; - if (!u.hasClass('chat-action', el) && !u.hasClass('chat-action', previous_el) && + if (!u.hasClass('chat-msg--action', el) && !u.hasClass('chat-msg--action', previous_el) && previous_el.getAttribute('data-from') === from && date.isBefore(moment(previous_el.getAttribute('data-isodate')).add(10, 'minutes'))) { - u.addClass('chat-msg-followup', el); + u.addClass('chat-msg--followup', el); } if (!next_el) { return; } - if (!u.hasClass('chat-action', 'el') && + if (!u.hasClass('chat-msg--action', 'el') && next_el.getAttribute('data-from') === from && moment(next_el.getAttribute('data-isodate')).isBefore(date.add(10, 'minutes'))) { - u.addClass('chat-msg-followup', next_el); + u.addClass('chat-msg--followup', next_el); } else { - u.removeClass('chat-msg-followup', next_el); + u.removeClass('chat-msg--followup', next_el); } }, diff --git a/src/converse-message-view.js b/src/converse-message-view.js index ad4f2c71f..5acafe858 100644 --- a/src/converse-message-view.js +++ b/src/converse-message-view.js @@ -10,26 +10,22 @@ "xss", "emojione", "filesize", - "templates/action.html", "templates/csn.html", "templates/file_progress.html", "templates/info.html", "templates/message.html", "templates/message_versions_modal.html", - "templates/spoiler_message.html" ], factory); }(this, function ( converse, xss, emojione, filesize, - tpl_action, tpl_csn, tpl_file_progress, tpl_info, tpl_message, - tpl_message_versions_modal, - tpl_spoiler_message + tpl_message_versions_modal ) { "use strict"; const { Backbone, _, moment } = converse.env; @@ -101,7 +97,7 @@ }, render () { - const is_followup = u.hasClass('chat-msg-followup', this.el); + const is_followup = u.hasClass('chat-msg--followup', this.el); let msg; if (this.model.isOnlyChatStateNotification()) { this.renderChatStateNotification() @@ -113,7 +109,7 @@ this.renderChatMessage(); } if (is_followup) { - u.addClass('chat-msg-followup', this.el); + u.addClass('chat-msg--followup', this.el); } return this.el; }, @@ -135,21 +131,16 @@ }, renderChatMessage () { - let template, text = this.model.get('message'); - if (this.isMeCommand()) { - template = tpl_action; - text = this.model.get('message').replace(/^\/me/, ''); - } else { - template = this.model.get('is_spoiler') ? tpl_spoiler_message : tpl_message; - } - const moment_time = moment(this.model.get('time')), + const is_me_message = this.isMeCommand(), + moment_time = moment(this.model.get('time')), role = this.model.vcard.get('role'), roles = role ? role.split(',') : []; - const msg = u.stringToElement(template( + const msg = u.stringToElement(tpl_message( _.extend( this.model.toJSON(), { '__': __, + 'is_me_message': is_me_message, 'roles': roles, 'pretty_time': moment_time.format(_converse.time_format), 'time': moment_time.format(), @@ -159,16 +150,20 @@ }) )); - var url = this.model.get('oob_url'); + const url = this.model.get('oob_url'); if (url) { - msg.querySelector('.chat-msg-media').innerHTML = _.flow( + msg.querySelector('.chat-msg__media').innerHTML = _.flow( _.partial(u.renderFileURL, _converse), _.partial(u.renderMovieURL, _converse), _.partial(u.renderAudioURL, _converse), _.partial(u.renderImageURL, _converse))(url); } - const msg_content = msg.querySelector('.chat-msg-text'); + let text = this.model.get('message'); + if (is_me_message) { + text = text.replace(/^\/me/, ''); + } + const msg_content = msg.querySelector('.chat-msg__text'); if (text !== url) { text = xss.filterXSS(text, {'whiteList': {}}); msg_content.innerHTML = _.flow( diff --git a/src/templates/action.html b/src/templates/action.html deleted file mode 100644 index ba26a745f..000000000 --- a/src/templates/action.html +++ /dev/null @@ -1,6 +0,0 @@ -
- - **{{{o.username}}} - -

-
diff --git a/src/templates/file_progress.html b/src/templates/file_progress.html index 3e20855aa..d8559c428 100644 --- a/src/templates/file_progress.html +++ b/src/templates/file_progress.html @@ -1,7 +1,7 @@
- -
- Uploading file: {{{o.file.name}}}, {{{o.filesize}}} + +
+ Uploading file: {{{o.file.name}}}, {{{o.filesize}}}
diff --git a/src/templates/message.html b/src/templates/message.html index 379ab2a3c..4b80f46ff 100644 --- a/src/templates/message.html +++ b/src/templates/message.html @@ -1,16 +1,27 @@ -
- {[ if (o.type !== 'headline') { ]} - +
+ {[ if (o.type !== 'headline' && !o.is_me_message) { ]} + {[ } ]} - diff --git a/src/templates/spoiler_message.html b/src/templates/spoiler_message.html deleted file mode 100644 index 0c87b874d..000000000 --- a/src/templates/spoiler_message.html +++ /dev/null @@ -1,14 +0,0 @@ - diff --git a/src/utils/core.js b/src/utils/core.js index 81d3d56e5..0b794228e 100644 --- a/src/utils/core.js +++ b/src/utils/core.js @@ -210,6 +210,10 @@ .replace(/"/g, """); }; + u.escapeURL = function (url) { + return encodeURI(decodeURI(url)).replace(/[!'()]/g, escape).replace(/\*/g, "%2A"); + }; + u.addHyperlinks = function (text) { return URI.withinString(text, function (url) { var uri = new URI(url); @@ -217,8 +221,8 @@ if (!url.startsWith('http://') && !url.startsWith('https://')) { url = 'http://' + url; } - url = encodeURI(decodeURI(url)).replace(/[!'()]/g, escape).replace(/\*/g, "%2A"); - return `${u.escapeHTML(uri.readable())}`; + url = u.escapeHTML(u.escapeURL(url)); + return `${u.escapeHTML(uri.readable())}`; }); }; @@ -255,7 +259,8 @@ }; u.renderFileURL = function (_converse, url) { - const uri = new URI(url), { __ } = _converse, + const uri = new URI(url), + { __ } = _converse, filename = uri.filename(); if (!_.includes(["https", "http"], uri.protocol()) || filename.endsWith('mp3') || filename.endsWith('mp4') ||