Commit 4bcf8e7b authored by JC Brand's avatar JC Brand

Mark followup messags so that they can be styled differently

parent 60c784a3
......@@ -37,10 +37,10 @@
var message = 'This is a received message';
var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
var msg = $msg({
from: sender_jid,
to: _converse.connection.jid,
type: 'chat',
id: (new Date()).getTime()
'from': sender_jid,
'to': _converse.connection.jid,
'type': 'chat',
'id': (new Date()).getTime()
}).c('body').t(message).up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
......@@ -575,6 +575,7 @@
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);
expect($el.text()).toEqual('Older message');
$time = $chat_content.find('time:eq(1)');
......@@ -589,6 +590,7 @@
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);
$time = $chat_content.find('time:nth(2)');
expect($time.text()).toEqual("Tuesday Jan 2nd 2018");
......@@ -599,14 +601,17 @@
$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);
$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);
$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);
done();
});
}));
......@@ -701,12 +706,7 @@
function (done, _converse) {
var contact, sent_stanza, IQ_id, stanza;
test_utils.waitUntilDiscoConfirmed(_converse, 'localhost', [], ['vcard-temp'])
.then(function () {
return test_utils.waitUntil(function () {
return _converse.xmppstatus.get('fullname');
}, 300);
}).then(function () {
test_utils.waitUntilDiscoConfirmed(_converse, 'localhost', [], ['vcard-temp']).then(function () {
test_utils.createContacts(_converse, 'current');
test_utils.openControlBox();
......@@ -1138,6 +1138,174 @@
done();
}));
it("will be correctly identified and rendered as a followup message",
mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {},
function (done, _converse) {
test_utils.createContacts(_converse, 'current');
test_utils.openControlBox();
test_utils.waitUntil(() => $(_converse.rosterview.el).find('.roster-group').length, 300)
.then(function () {
const base_time = new Date();
const ONE_MINUTE_LATER = 60000;
jasmine.clock().install();
jasmine.clock().mockDate(base_time);
var message, msg;
spyOn(_converse, 'log');
spyOn(_converse.chatboxes, 'getChatBox').and.callThrough();
_converse.filter_by_resource = true;
var sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
_converse.chatboxes.onMessage($msg({
'from': sender_jid,
'to': _converse.connection.jid,
'type': 'chat',
'id': (new Date()).getTime()
}).c('body').t('A message').up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
jasmine.clock().tick(3*ONE_MINUTE_LATER);
_converse.chatboxes.onMessage($msg({
'from': sender_jid,
'to': _converse.connection.jid,
'type': 'chat',
'id': (new Date()).getTime()
}).c('body').t("Another message 3 minutes later").up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
jasmine.clock().tick(11*ONE_MINUTE_LATER);
_converse.chatboxes.onMessage($msg({
'from': sender_jid,
'to': _converse.connection.jid,
'type': 'chat',
'id': (new Date()).getTime()
}).c('body').t("Another message 14 minutes since we started").up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
jasmine.clock().tick(1000);
// Insert <composing> message, to also check that
// text messages are inserted correctly with
// temporary chat events in the chat contents.
_converse.chatboxes.onMessage($msg({
'id': 'aeb219',
'to': _converse.bare_jid,
'xmlns': 'jabber:client',
'from': sender_jid,
'type': 'chat'})
.c('composing', {'xmlns': Strophe.NS.CHATSTATES}).up()
.tree());
jasmine.clock().tick(1*ONE_MINUTE_LATER);
_converse.chatboxes.onMessage($msg({
'from': sender_jid,
'to': _converse.connection.jid,
'type': 'chat',
'id': (new Date()).getTime()
}).c('body').t("Another message 1 minute and 1 second since the previous one").up()
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree());
jasmine.clock().tick(1*ONE_MINUTE_LATER);
var view = _converse.chatboxviews.get(sender_jid);
test_utils.sendMessage(view, "Another message within 10 minutes, but from a different person");
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(
"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(
"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(
"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(
"Another message within 10 minutes, but from a different person");
// Let's add a delayed, inbetween message
_converse.chatboxes.onMessage($msg({'id': 'aeb218', 'to': _converse.bare_jid})
.c('forwarded', {'xmlns': 'urn:xmpp:forward:0'})
.c('delay', {'xmlns': 'urn:xmpp:delay',
'stamp': moment(base_time).add(5, 'minutes').format()
}).up()
.c('message', {
'xmlns': 'jabber:client',
'to': _converse.bare_jid,
'from': sender_jid,
'type': 'chat'})
.c('body').t("A delayed message, sent 5 minutes since we started")
.tree());
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(
"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(
"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(
"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(
"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);
_converse.chatboxes.onMessage($msg({'id': 'aeb213', 'to': _converse.bare_jid})
.c('forwarded', {'xmlns': 'urn:xmpp:forward:0'})
.c('delay', {'xmlns': 'urn:xmpp:delay', 'stamp':moment(base_time).add(4, 'minutes').format()}).up()
.c('message', {
'xmlns': 'jabber:client',
'to': sender_jid,
'from': _converse.bare_jid+"/some-other-resource",
'type': 'chat'})
.c('body').t("A carbon message 4 minutes later")
.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(
"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(
"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(
"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(
"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(
"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(
"Another message within 10 minutes, but from a different person");
jasmine.clock().uninstall();
done();
});
}));
describe("which contains a OOB URL", function () {
it("will render audio from oob mp3 URLs",
......
......@@ -637,7 +637,7 @@
},
insertMessage (view) {
/* Given a view representing a message, insert it inot the
/* Given a view representing a message, insert it into the
* content area of the chat box.
*
* Parameters:
......@@ -663,6 +663,45 @@
return;
}
previous_msg_el.insertAdjacentElement('afterend', view.el);
this.markFollowups(view.el);
}
},
markFollowups (el) {
/* Given a message element, determine wether it should be
* marked as a followup message to the previous element.
*
* Also determine whether the element following it is a
* followup message or not.
*
* Followup messages are subsequent ones written by the same
* author with no other conversation elements inbetween and
* posted within 10 minutes of one another.
*
* Parameters:
* (HTMLElement) el - The message element.
*/
const from = el.getAttribute('data-from'),
previous_el = el.previousElementSibling,
date = moment(el.getAttribute('data-isodate'));
if (previous_el.getAttribute('data-from') === from &&
date.isBefore(moment(previous_el.getAttribute('data-isodate')).add(10, 'minutes'))) {
u.addClass('chat-msg-followup', el);
}
const next_el = el.nextElementSibling;
if (!next_el) {
return;
}
if (next_el.getAttribute('data-from') !== from) {
u.removeClass('chat-msg-followup', next_el);
} else {
if (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);
}
}
},
......
<div class="message chat-msg {{{o.type}}} {{{o.extra_classes}}}" data-isodate="{{{o.time}}}" data-msgid="{{{o.msgid}}}">
<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') { ]}
<img alt="User Avatar" class="avatar" height="36px" width="36px" src="data:{{{o.image_type}}};base64,{{{o.image}}}"/>
{[ } ]}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment