Update with new message markup

This commit is contained in:
JC Brand 2018-07-20 15:54:59 +02:00
parent 6a462f6c2c
commit acd9a18696
17 changed files with 386 additions and 428 deletions

View File

@ -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; }

182
dist/converse.js vendored
View File

@ -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 += '<!-- src/templates/action.html -->\n<div class="message chat-msg chat-action ' +
__e(o.extra_classes) +
'" data-isodate="' +
__e(o.time) +
'" data-from="' +
__e(o.from) +
'">\n <span class="chat-msg-heading">\n <span class="chat-msg-author">**' +
__e(o.username) +
'</span>\n </span>\n <p class="chat-msg-text"><!-- message gets added here via renderMessage --></p>\n</div>\n';
return __p
};
/***/ }),
/***/ "./src/templates/add_chatroom_modal.html":
/*!***********************************************!*\
!*** ./src/templates/add_chatroom_modal.html ***!
@ -85230,7 +85204,7 @@ __p += '<!-- src/templates/file_progress.html -->\n<div class="message chat-msg"
__e(o.time) +
'" data-msgid="' +
__e(o.msgid) +
'">\n <canvas class="avatar" height="36" width="36"></canvas>\n <div class="chat-msg-content">\n <span class="chat-msg-text">Uploading file: <strong>' +
'">\n <canvas class="avatar chat-msg__avatar" height="36" width="36"></canvas>\n <div class="chat-msg__content">\n <span class="chat-msg__text">Uploading file: <strong>' +
__e(o.file.name) +
'</strong>, ' +
__e(o.filesize) +
@ -85699,7 +85673,11 @@ var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
function print() { __p += __j.call(arguments, '') }
__p += '<!-- src/templates/message.html -->\n<div class="message chat-msg ' +
__e(o.type) +
' ' +
' ';
if (o.is_me_message) { ;
__p += ' chat-msg--action ';
} ;
__p += ' ' +
__e(o.extra_classes) +
'" data-isodate="' +
__e(o.time) +
@ -85708,10 +85686,26 @@ __e(o.msgid) +
'" data-from="' +
__e(o.from) +
'">\n ';
if (o.type !== 'headline') { ;
__p += '\n <canvas class="avatar" height="36" width="36"></canvas>\n ';
if (o.type !== 'headline' && !o.is_me_message) { ;
__p += '\n <canvas class="avatar chat-msg__avatar" height="36" width="36"></canvas>\n ';
} ;
__p += '\n <div class="chat-msg-content">\n <span class="chat-msg-heading">\n <span class="chat-msg-author">' +
__p += '\n <div class="chat-msg__content ';
if (o.is_me_message) { ;
__p += 'chat-msg__content--action';
} ;
__p += '">\n <span class="chat-msg__heading">\n ';
if (o.is_me_message) { ;
__p += '<time timestamp="' +
__e(o.isodate) +
'" class="chat-msg__time">' +
__e(o.pretty_time) +
'</time>';
} ;
__p += '\n <span class="chat-msg__author">';
if (o.is_me_message) { ;
__p += '**';
}; ;
__p +=
__e(o.username) +
'\n ';
o.roles.forEach(function (role) { ;
@ -85719,17 +85713,49 @@ __p += ' <span class="badge badge-secondary">' +
__e(role) +
'</span> ';
}); ;
__p += '\n </span>\n <time timestamp="' +
__p += '\n </span>\n ';
if (!o.is_me_message) { ;
__p += '<time timestamp="' +
__e(o.isodate) +
'" class="chat-msg-time">' +
'" class="chat-msg__time">' +
__e(o.pretty_time) +
'</time>\n </span>\n ';
'</time>';
} ;
__p += '\n </span>\n ';
if (!o.is_me_message) { ;
__p += '<div class="chat-msg__body">';
} ;
__p += ' \n ';
if (o.edited) { ;
__p += ' <i title="' +
__e(o.__('This message has been edited')) +
'" class="fa fa-edit chat-msg-edited"></i> ';
} ;
__p += '\n <span class="chat-msg-text"></span>\n <div class="chat-msg-media"></div>\n </div>\n</div>\n';
__p += '\n ';
if (!o.is_me_message) { ;
__p += '<div class="chat-msg__message">';
} ;
__p += ' \n ';
if (o.is_spoiler) { ;
__p += '\n <div class="chat-msg__spoiler-hint">\n <span class="spoiler-hint">' +
__e(o.spoiler_hint) +
'</span>\n <a class="badge badge-info spoiler-toggle" data-toggle-state="closed" href="#"><i class="fa fa-eye"></i>' +
__e(o.label_show) +
'</a>\n </div>\n ';
} ;
__p += '\n <div class="chat-msg__text';
if (o.is_spoiler) { ;
__p += ' spoiler collapsed';
} ;
__p += '"><!-- message gets added here via renderMessage --></div>\n <div class="chat-msg__media"></div>\n ';
if (!o.is_me_message) { ;
__p += '</div>';
} ;
__p += '\n ';
if (!o.is_me_message) { ;
__p += '</div>';
} ;
__p += ' \n </div>\n</div>\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 += '<!-- src/templates/spoiler_message.html -->\n<div class="message chat-msg ' +
__e(o.extra_classes) +
'" data-isodate="' +
__e(o.time) +
'" data-msgid="' +
__e(o.msgid) +
'">\n <canvas class="avatar" height="36" width="36"></canvas>\n <div class="chat-msg-content">\n <span class="chat-msg-heading">\n <span class="chat-msg-author">' +
__e(o.username) +
'</span>\n <span class="chat-msg-time">' +
__e(o.pretty_time) +
'</span>\n </span>\n <div>\n <span class="spoiler-hint">' +
__e(o.spoiler_hint) +
'</span>\n <a class="badge badge-info spoiler-toggle" data-toggle-state="closed" href="#"><i class="fa fa-eye"></i>' +
__e(o.label_show) +
'</a>\n </div>\n <div class="chat-msg-text spoiler collapsed"><!-- message gets added here via renderMessage --></div>\n </div>\n</div>\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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
};
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 `<a target="_blank" rel="noopener" href="${u.escapeHTML(url)}">${u.escapeHTML(uri.readable())}</a>`;
url = u.escapeHTML(u.escapeURL(url));
return `<a target="_blank" rel="noopener" href="${url}">${u.escapeHTML(uri.readable())}</a>`;
});
};

View File

@ -45,8 +45,11 @@
Romeo Montague has entered the room</div>
<div class="message chat-msg chat-msg--action" data-isodate="2018-04-36T18:07:38+02:00">
<div class="chat-msg__content">
<span class="chat-msg__heading"><span class="chat-msg__author">**Romeo Montague</span></span>
<div class="chat-msg__content chat-msg__content--action">
<span class="chat-msg__heading">
<time timestamp="2018-12-29" class="chat-msg__time">15:29</time>
<span class="chat-msg__author">**Romeo Montague</span>
</span>
<span class="chat-msg__text">looks around</span>
</div>
</div>
@ -177,7 +180,7 @@
</div>
<div class="chat-msg__body">
<div class="chat-msg__message">
<div class="chat-msg-media">
<div class="chat-msg__media">
<a href="https://images.unsplash.com/photo-1496660067708-010ebdd7ce72?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=ea3514e6e00d8ce25c24d992b97929d9&dpr=1&auto=format&fit=crop&w=1000&q=80&cs=tinysrgb"
target="_blank" rel="noopener">
<img class="chat-image img-thumbnail" src="https://images.unsplash.com/photo-1496660067708-010ebdd7ce72?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=ea3514e6e00d8ce25c24d992b97929d9&dpr=1&auto=format&fit=crop&w=1000&q=80&cs=tinysrgb">
@ -227,6 +230,7 @@
<span class="chat-msg__time">19:49</span>
</div>
<div class="chat-msg__body">
<i title="This message has been edited" class="fa fa-edit chat-msg__edit-modal"></i>
<div class="chat-msg__message">
<span class="chat-msg__text">I mean, sir, in delay We waste our lights in vain, like lamps by day.</span>
</div>

View File

@ -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;

View File

@ -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 {

View File

@ -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(
'<a target="_blank" rel="noopener" href="https://www.openstreetmap.org/?mlat=37.786971&amp;'+
'mlon=-122.399677#map=18/37.786971/-122.399677">https://www.openstreetmap.org/?mlat=37.7869'+

View File

@ -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.

View File

@ -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(
'<!-- src/templates/image.html -->\n'+
'<a href="http://localhost:8000/logo/conversejs-filled.svg" target="_blank" rel="noopener">'+
'<img class="chat-image img-thumbnail" src="http://localhost:8000/logo/conversejs-filled.svg">'+
@ -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(
'<!-- src/templates/image.html -->\n'+
'<a href="http://localhost:8000/logo/conversejs-filled.svg" target="_blank" rel="noopener">'+
'<img class="chat-image img-thumbnail" src="http://localhost:8000/logo/conversejs-filled.svg"></a>')
@ -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;

View File

@ -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);
/* <message xmlns="jabber:client"
@ -571,7 +571,7 @@
// 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: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);
return test_utils.waitUntil(function () {
return u.isVisible(chatboxview.el.querySelector('.new-msgs-indicator'));
@ -634,7 +634,7 @@
expect(_converse.chatboxes.getChatBox).toHaveBeenCalled();
var chatboxview = _converse.chatboxviews.get(sender_jid);
var $chat_content = $(chatboxview.el).find('.chat-content:last');
var msg_txt = $chat_content.find('.chat-msg').find('.chat-msg-text').text();
var msg_txt = $chat_content.find('.chat-msg').find('.chat-msg__text').text();
expect(msg_txt).toEqual(message);
done();
});
@ -781,10 +781,10 @@
expect($time.text()).toEqual('Sunday Dec 31st 2017')
$day = $chat_content.find('.date-separator:first');
expect($day[0].nextElementSibling.querySelector('.chat-msg-text').textContent).toBe('Older message');
expect($day[0].nextElementSibling.querySelector('.chat-msg__text').textContent).toBe('Older message');
var $el = $chat_content.find('.chat-msg:first').find('.chat-msg-text')
expect($el.hasClass('chat-msg-followup')).toBe(false);
var $el = $chat_content.find('.chat-msg:first').find('.chat-msg__text')
expect($el.hasClass('chat-msg--followup')).toBe(false);
expect($el.text()).toEqual('Older message');
$time = $chat_content.find('time.separator-text:eq(1)');
@ -792,35 +792,35 @@
$day = $chat_content.find('.date-separator:eq(1)');
expect($day.data('isodate')).toEqual(moment('2018-01-01T00:00:00').format());
expect($day[0].nextElementSibling.querySelector('.chat-msg-text').textContent).toBe('Inbetween message');
expect($day[0].nextElementSibling.querySelector('.chat-msg__text').textContent).toBe('Inbetween message');
$el = $chat_content.find('.chat-msg:eq(1)');
expect($el.find('.chat-msg-text').text()).toEqual('Inbetween message');
expect($el[0].nextElementSibling.querySelector('.chat-msg-text').textContent).toEqual('another inbetween message');
expect($el.find('.chat-msg__text').text()).toEqual('Inbetween message');
expect($el[0].nextElementSibling.querySelector('.chat-msg__text').textContent).toEqual('another inbetween message');
$el = $chat_content.find('.chat-msg:eq(2)');
expect($el.find('.chat-msg-text').text()).toEqual('another inbetween message');
expect($el.hasClass('chat-msg-followup')).toBe(true);
expect($el.find('.chat-msg__text').text()).toEqual('another inbetween message');
expect($el.hasClass('chat-msg--followup')).toBe(true);
$time = $chat_content.find('time.separator-text:nth(2)');
expect($time.text()).toEqual("Tuesday Jan 2nd 2018");
$day = $chat_content.find('.date-separator:nth(2)');
expect($day.data('isodate')).toEqual(moment('2018-01-02T00:00:00').format());
expect($day[0].nextElementSibling.querySelector('.chat-msg-text').textContent).toBe('An earlier message on the next day');
expect($day[0].nextElementSibling.querySelector('.chat-msg__text').textContent).toBe('An earlier message on the next day');
$el = $chat_content.find('.chat-msg:eq(3)');
expect($el.find('.chat-msg-text').text()).toEqual('An earlier message on the next day');
expect($el.hasClass('chat-msg-followup')).toBe(false);
expect($el.find('.chat-msg__text').text()).toEqual('An earlier message on the next day');
expect($el.hasClass('chat-msg--followup')).toBe(false);
$el = $chat_content.find('.chat-msg:eq(4)');
expect($el.find('.chat-msg-text').text()).toEqual('message');
expect($el[0].nextElementSibling.querySelector('.chat-msg-text').textContent).toEqual('newer message from the next day');
expect($el.hasClass('chat-msg-followup')).toBe(false);
expect($el.find('.chat-msg__text').text()).toEqual('message');
expect($el[0].nextElementSibling.querySelector('.chat-msg__text').textContent).toEqual('newer message from the next day');
expect($el.hasClass('chat-msg--followup')).toBe(false);
$day = $chat_content.find('.date-separator:last');
expect($day.data('isodate')).toEqual(moment().startOf('day').format());
expect($day[0].nextElementSibling.querySelector('.chat-msg-text').textContent).toBe('latest message');
expect($el.hasClass('chat-msg-followup')).toBe(false);
expect($day[0].nextElementSibling.querySelector('.chat-msg__text').textContent).toBe('latest message');
expect($el.hasClass('chat-msg--followup')).toBe(false);
done();
});
}));
@ -839,7 +839,7 @@
sinon.spy(_converse, 'log');
sinon.spy(_converse.chatboxes, 'getChatBox');
sinon.spy(u, 'isHeadlineMessage');
var msg = $msg({
const msg = $msg({
from: 'localhost',
to: _converse.bare_jid,
type: 'chat',
@ -902,12 +902,12 @@
expect(msg_obj.get('sender')).toEqual('them');
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(msgtext);
expect(chat_content.querySelector('.chat-msg-time').textContent.match(/^[0-9][0-9]:[0-9][0-9]/)).toBeTruthy();
const chat_content = chatboxview.el.querySelector('.chat-content');
expect(chat_content.querySelector('.chat-msg .chat-msg__text').textContent).toEqual(msgtext);
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') === '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('&lt;p&gt;This message contains &lt;em&gt;some&lt;/em&gt; &lt;b&gt;markup&lt;/b&gt;&lt;/p&gt;');
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: <a target="_blank" rel="noopener" href="http://www.opkode.com">www.opkode.com</a>');
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('<a target="_blank" rel="noopener" href="http://www.opkode.com/%27onmouseover=%27alert%281%29%27whatever">http://www.opkode.com/\'onmouseover=\'alert(1)\'whatever</a>');
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('<a target="_blank" rel="noopener" href="http://www.opkode.com/%22onmouseover=%22alert%281%29%22whatever">http://www.opkode.com/"onmouseover="alert(1)"whatever</a>');
@ -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('<a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Ender%27s_Game">'+message+'</a>');
@ -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('<a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Ender%27s_Game">'+message+'</a>');
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<br>Have you heard the news?');
expect(chat_content.querySelector('.chat-msg__text').innerHTML).toBe('Hey<br>Have you heard the news?');
stanza = Strophe.xmlHtmlNode(
"<message from='"+contact_jid+"'"+
@ -1301,7 +1302,7 @@
" <body>Hey\n\n\nHave you heard the news?</body>"+
"</message>").firstChild;
_converse.connection._dataRecv(test_utils.createRequest(stanza));
expect(chat_content.querySelector('.message:last-child .chat-msg-text').innerHTML).toBe('Hey<br><br>Have you heard the news?');
expect(chat_content.querySelector('.message:last-child .chat-msg__text').innerHTML).toBe('Hey<br><br>Have you heard the news?');
stanza = Strophe.xmlHtmlNode(
"<message from='"+contact_jid+"'"+
@ -1310,7 +1311,7 @@
" <body>Hey\nHave you heard\nthe news?</body>"+
"</message>").firstChild;
_converse.connection._dataRecv(test_utils.createRequest(stanza));
expect(chat_content.querySelector('.message:last-child .chat-msg-text').innerHTML).toBe('Hey<br>Have you heard<br>the news?');
expect(chat_content.querySelector('.message:last-child .chat-msg__text').innerHTML).toBe('Hey<br>Have you heard<br>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(
'<!-- src/templates/image.html -->\n'+
'<a href="'+base_url+'/logo/conversejs-filled.svg" target="_blank" rel="noopener"><img class="chat-image img-thumbnail"'+
@ -1340,7 +1341,7 @@
return test_utils.waitUntil(() => 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(
'<!-- src/templates/image.html -->\n'+
'<a href="'+base_url+'/logo/conversejs-filled.svg?param1=val1&amp;param2=val2" target="_blank" rel="noopener"><img'+
@ -1352,7 +1353,7 @@
return test_utils.waitUntil(() => 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(
"<message from='"+contact_jid+"'"+
" type='chat'"+
" to='dummy@localhost/resource'>"+
@ -1576,19 +1577,17 @@
"</message>").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('<span class="chat-msg-text">Have you heard this funny audio?</span>');
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('<div class="chat-msg__text">Have you heard this funny audio?</div>');
let media = view.el.querySelector('.chat-msg .chat-msg__media');
expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual(
'<!-- src/templates/audio.html -->'+
'<audio controls=""><source src="http://localhost/audio.mp3" type="audio/mpeg"></audio>'+
'<a target="_blank" rel="noopener" href="http://localhost/audio.mp3">Download audio file</a>');
// If the <url> and <body> contents is the same, don't duplicate.
var stanza = Strophe.xmlHtmlNode(
const stanza = Strophe.xmlHtmlNode(
"<message from='"+contact_jid+"'"+
" type='chat'"+
" to='dummy@localhost/resource'>"+
@ -1597,9 +1596,9 @@
"</message>").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('<!-- message gets added here via renderMessage -->'); // Emtpy
media = view.el.querySelector('.chat-msg:last-child .chat-msg__media');
expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual(
'<!-- src/templates/audio.html -->'+
'<audio controls=""><source src="http://localhost/audio.mp3" type="audio/mpeg"></audio>'+
@ -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(
"<message from='"+contact_jid+"'"+
" type='chat'"+
" to='dummy@localhost/resource'>"+
@ -1628,19 +1627,17 @@
"</message>").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('<span class="chat-msg-text">Have you seen this funny video?</span>');
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('<div class="chat-msg__text">Have you seen this funny video?</div>');
let media = view.el.querySelector('.chat-msg .chat-msg__media');
expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual(
'<!-- src/templates/video.html -->'+
'<video controls=""><source src="http://localhost/video.mp4" type="video/mp4"></video>'+
'<a target="_blank" rel="noopener" href="http://localhost/video.mp4">Download video file</a>');
// If the <url> and <body> contents is the same, don't duplicate.
var stanza = Strophe.xmlHtmlNode(
const stanza = Strophe.xmlHtmlNode(
"<message from='"+contact_jid+"'"+
" type='chat'"+
" to='dummy@localhost/resource'>"+
@ -1649,9 +1646,9 @@
"</message>").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('<!-- message gets added here via renderMessage -->'); // Emtpy
media = view.el.querySelector('.chat-msg:last-child .chat-msg__media');
expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual(
'<!-- src/templates/video.html -->'+
'<video controls=""><source src="http://localhost/video.mp4" type="video/mp4"></video>'+
@ -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(
"<message from='"+contact_jid+"'"+
" type='chat'"+
" to='dummy@localhost/resource'>"+
@ -1680,12 +1677,10 @@
"</message>").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('<span class="chat-msg-text">Have you downloaded this funny file?</span>');
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('<div class="chat-msg__text">Have you downloaded this funny file?</div>');
const media = view.el.querySelector('.chat-msg .chat-msg__media');
expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual(
'<!-- src/templates/file.html -->'+
'<a target="_blank" rel="noopener" href="http://localhost/funny.pdf">Download "funny.pdf"</a>');
@ -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(
"<message from='"+contact_jid+"'"+
" type='chat'"+
" to='dummy@localhost/resource'>"+
@ -1715,12 +1710,10 @@
"</message>").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('<span class="chat-msg-text">Have you seen this funny image?</span>');
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('<div class="chat-msg__text">Have you seen this funny image?</div>');
const media = view.el.querySelector('.chat-msg .chat-msg__media');
expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual(
'<!-- src/templates/image.html -->'+
'<a href="http://localhost:8000/logo/conversejs-filled.svg" target="_blank" rel="noopener">'+
@ -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?'});

View File

@ -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();

View File

@ -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);
}
},

View File

@ -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(

View File

@ -1,6 +0,0 @@
<div class="message chat-msg chat-action {{{o.extra_classes}}}" data-isodate="{{{o.time}}}" data-from="{{{o.from}}}">
<span class="chat-msg-heading">
<span class="chat-msg-author">**{{{o.username}}}</span>
</span>
<p class="chat-msg-text"><!-- message gets added here via renderMessage --></p>
</div>

View File

@ -1,7 +1,7 @@
<div class="message chat-msg" data-isodate="{{{o.time}}}" data-msgid="{{{o.msgid}}}">
<canvas class="avatar" height="36" width="36"></canvas>
<div class="chat-msg-content">
<span class="chat-msg-text">Uploading file: <strong>{{{o.file.name}}}</strong>, {{{o.filesize}}}</span>
<canvas class="avatar chat-msg__avatar" height="36" width="36"></canvas>
<div class="chat-msg__content">
<span class="chat-msg__text">Uploading file: <strong>{{{o.file.name}}}</strong>, {{{o.filesize}}}</span>
<progress value="{{{o.progress}}}"/>
</div>
</div>

View File

@ -1,16 +1,27 @@
<div class="message chat-msg {{{o.type}}} {{{o.extra_classes}}}" data-isodate="{{{o.time}}}" data-msgid="{{{o.msgid}}}" data-from="{{{o.from}}}">
{[ if (o.type !== 'headline') { ]}
<canvas class="avatar" height="36" width="36"></canvas>
<div class="message chat-msg {{{o.type}}} {[ if (o.is_me_message) { ]} chat-msg--action {[ } ]} {{{o.extra_classes}}}" data-isodate="{{{o.time}}}" data-msgid="{{{o.msgid}}}" data-from="{{{o.from}}}">
{[ if (o.type !== 'headline' && !o.is_me_message) { ]}
<canvas class="avatar chat-msg__avatar" height="36" width="36"></canvas>
{[ } ]}
<div class="chat-msg-content">
<span class="chat-msg-heading">
<span class="chat-msg-author">{{{o.username}}}
<div class="chat-msg__content {[ if (o.is_me_message) { ]}chat-msg__content--action{[ } ]}">
<span class="chat-msg__heading">
{[ if (o.is_me_message) { ]}<time timestamp="{{{o.isodate}}}" class="chat-msg__time">{{{o.pretty_time}}}</time>{[ } ]}
<span class="chat-msg__author">{[ if (o.is_me_message) { ]}**{[ }; ]}{{{o.username}}}
{[o.roles.forEach(function (role) { ]} <span class="badge badge-secondary">{{{role}}}</span> {[ }); ]}
</span>
<time timestamp="{{{o.isodate}}}" class="chat-msg-time">{{{o.pretty_time}}}</time>
{[ if (!o.is_me_message) { ]}<time timestamp="{{{o.isodate}}}" class="chat-msg__time">{{{o.pretty_time}}}</time>{[ } ]}
</span>
{[ if (!o.is_me_message) { ]}<div class="chat-msg__body">{[ } ]}
{[ if (o.edited) { ]} <i title="{{{o.__('This message has been edited')}}}" class="fa fa-edit chat-msg-edited"></i> {[ } ]}
<span class="chat-msg-text"></span>
<div class="chat-msg-media"></div>
{[ if (!o.is_me_message) { ]}<div class="chat-msg__message">{[ } ]}
{[ if (o.is_spoiler) { ]}
<div class="chat-msg__spoiler-hint">
<span class="spoiler-hint">{{{o.spoiler_hint}}}</span>
<a class="badge badge-info spoiler-toggle" data-toggle-state="closed" href="#"><i class="fa fa-eye"></i>{{{o.label_show}}}</a>
</div>
{[ } ]}
<div class="chat-msg__text{[ if (o.is_spoiler) { ]} spoiler collapsed{[ } ]}"><!-- message gets added here via renderMessage --></div>
<div class="chat-msg__media"></div>
{[ if (!o.is_me_message) { ]}</div>{[ } ]}
{[ if (!o.is_me_message) { ]}</div>{[ } ]}
</div>
</div>

View File

@ -1,14 +0,0 @@
<div class="message chat-msg {{{o.extra_classes}}}" data-isodate="{{{o.time}}}" data-msgid="{{{o.msgid}}}">
<canvas class="avatar" height="36" width="36"></canvas>
<div class="chat-msg-content">
<span class="chat-msg-heading">
<span class="chat-msg-author">{{{o.username}}}</span>
<span class="chat-msg-time">{{{o.pretty_time}}}</span>
</span>
<div>
<span class="spoiler-hint">{{{o.spoiler_hint}}}</span>
<a class="badge badge-info spoiler-toggle" data-toggle-state="closed" href="#"><i class="fa fa-eye"></i>{{{o.label_show}}}</a>
</div>
<div class="chat-msg-text spoiler collapsed"><!-- message gets added here via renderMessage --></div>
</div>
</div>

View File

@ -210,6 +210,10 @@
.replace(/"/g, "&quot;");
};
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 `<a target="_blank" rel="noopener" href="${u.escapeHTML(url)}">${u.escapeHTML(uri.readable())}</a>`;
url = u.escapeHTML(u.escapeURL(url));
return `<a target="_blank" rel="noopener" href="${url}">${u.escapeHTML(uri.readable())}</a>`;
});
};
@ -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') ||