Commit 6ac1df43 authored by JC Brand's avatar JC Brand

Render chat state notifications on the message view

and not via the chatbox view (fixes some failing tests also).
parent 99915a26
...@@ -718,25 +718,30 @@ ...@@ -718,25 +718,30 @@
}).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object)); expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
var chatboxview = _converse.chatboxviews.get(sender_jid); var view = _converse.chatboxviews.get(sender_jid);
expect(chatboxview).toBeDefined(); expect(view).toBeDefined();
// Check that the notification appears inside the chatbox in the DOM
var events = chatboxview.el.querySelectorAll('.chat-state-notification'); test_utils.waitUntil(() => view.model.vcard.get('fullname') === mock.cur_names[1])
expect(events.length).toBe(1); .then(function () {
expect(events[0].textContent).toEqual(mock.cur_names[1] + ' is typing'); var view = _converse.chatboxviews.get(sender_jid);
// Check that the notification appears inside the chatbox in the DOM
// Check that it doesn't appear twice var events = view.el.querySelectorAll('.chat-state-notification');
msg = $msg({ expect(events.length).toBe(1);
from: sender_jid, expect(events[0].textContent).toEqual(mock.cur_names[1] + ' is typing');
to: _converse.connection.jid,
type: 'chat', // Check that it doesn't appear twice
id: (new Date()).getTime() msg = $msg({
}).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree(); from: sender_jid,
_converse.chatboxes.onMessage(msg); to: _converse.connection.jid,
events = chatboxview.el.querySelectorAll('.chat-state-notification'); type: 'chat',
expect(events.length).toBe(1); id: (new Date()).getTime()
expect(events[0].textContent).toEqual(mock.cur_names[1] + ' is typing'); }).c('body').c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
done(); _converse.chatboxes.onMessage(msg);
events = view.el.querySelectorAll('.chat-state-notification');
expect(events.length).toBe(1);
expect(events[0].textContent).toEqual(mock.cur_names[1] + ' is typing');
done();
})
})); }));
it("can be a composing carbon message that this user sent from a different client", it("can be a composing carbon message that this user sent from a different client",
...@@ -877,10 +882,14 @@ ...@@ -877,10 +882,14 @@
}).c('body').c('paused', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('body').c('paused', {'xmlns': Strophe.NS.CHATSTATES}).tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object)); expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
var chatboxview = _converse.chatboxviews.get(sender_jid); var view = _converse.chatboxviews.get(sender_jid);
var $events = $(chatboxview.el).find('.chat-info.chat-state-notification'); test_utils.waitUntil(() => view.model.vcard.get('fullname') === mock.cur_names[1])
expect($events.text()).toEqual(mock.cur_names[1] + ' has stopped typing'); .then(function () {
done(); var view = _converse.chatboxviews.get(sender_jid);
var event = view.el.querySelector('.chat-info.chat-state-notification');
expect(event.textContent).toEqual(mock.cur_names[1] + ' has stopped typing');
done();
});
}); });
})); }));
...@@ -1113,10 +1122,14 @@ ...@@ -1113,10 +1122,14 @@
}).c('body').c('gone', {'xmlns': Strophe.NS.CHATSTATES}).tree(); }).c('body').c('gone', {'xmlns': Strophe.NS.CHATSTATES}).tree();
_converse.chatboxes.onMessage(msg); _converse.chatboxes.onMessage(msg);
expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object)); expect(_converse.emit).toHaveBeenCalledWith('message', jasmine.any(Object));
var chatboxview = _converse.chatboxviews.get(sender_jid); var view = _converse.chatboxviews.get(sender_jid);
var $events = $(chatboxview.el).find('.chat-state-notification'); test_utils.waitUntil(() => view.model.vcard.get('fullname') === mock.cur_names[1])
expect($events.text()).toEqual(mock.cur_names[1] + ' has gone away'); .then(function () {
done(); var view = _converse.chatboxviews.get(sender_jid);
var event = view.el.querySelector('.chat-state-notification');
expect(event.textContent).toEqual(mock.cur_names[1] + ' has gone away');
done();
});
})); }));
}); });
}); });
......
...@@ -109,6 +109,16 @@ ...@@ -109,6 +109,16 @@
this.getRequestSlotURL(); this.getRequestSlotURL();
} }
} }
if (this.isOnlyChatStateNotification()) {
window.setTimeout(this.destroy.bind(this), 20000);
}
},
isOnlyChatStateNotification () {
return this.get('chat_state') &&
!this.get('oob_url') &&
!this.get('file') &&
!this.get('message');
}, },
getDisplayName () { getDisplayName () {
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
"tpl!chatbox", "tpl!chatbox",
"tpl!chatbox_head", "tpl!chatbox_head",
"tpl!chatbox_message_form", "tpl!chatbox_message_form",
"tpl!csn",
"tpl!emojis", "tpl!emojis",
"tpl!error_message", "tpl!error_message",
"tpl!help_message", "tpl!help_message",
...@@ -37,7 +36,6 @@ ...@@ -37,7 +36,6 @@
tpl_chatbox, tpl_chatbox,
tpl_chatbox_head, tpl_chatbox_head,
tpl_chatbox_message_form, tpl_chatbox_message_form,
tpl_csn,
tpl_emojis, tpl_emojis,
tpl_error_message, tpl_error_message,
tpl_help_message, tpl_help_message,
...@@ -589,48 +587,6 @@ ...@@ -589,48 +587,6 @@
} }
}, },
showChatStateNotification (message) {
/* Support for XEP-0085, Chat State Notifications */
let text;
const from = message.get('from'),
name = message.getDisplayName();
this.clearChatStateNotification(message);
if (message.get('chat_state') === _converse.COMPOSING) {
if (message.get('sender') === 'me') {
text = __('Typing from another device');
} else {
text = name +' '+__('is typing');
}
} else if (message.get('chat_state') === _converse.PAUSED) {
if (message.get('sender') === 'me') {
text = __('Stopped typing on the other device');
} else {
text = name +' '+__('has stopped typing');
}
} else if (message.get('chat_state') === _converse.GONE) {
text = name +' '+__('has gone away');
} else {
return;
}
const isodate = moment().format();
this.content.insertAdjacentHTML(
'beforeend',
tpl_csn({
'message': text,
'from': from,
'isodate': isodate
}));
this.scrollDown();
this.clear_status_timeout = window.setTimeout(
this.clearChatStateNotification.bind(this, message, isodate),
30000
);
return message;
},
shouldShowOnTextMessage () { shouldShowOnTextMessage () {
return !u.isVisible(this.el); return !u.isVisible(this.el);
}, },
...@@ -711,9 +667,9 @@ ...@@ -711,9 +667,9 @@
* (Backbone.Model) message: The message object * (Backbone.Model) message: The message object
*/ */
const view = new _converse.MessageView({'model': message}); const view = new _converse.MessageView({'model': message});
this.clearChatStateNotification(message);
this.insertMessage(view); this.insertMessage(view);
this.insertDayIndicator(view.el); this.insertDayIndicator(view.el);
this.clearChatStateNotification(message);
this.setScrollPosition(view.el); this.setScrollPosition(view.el);
if (u.isNewMessage(message)) { if (u.isNewMessage(message)) {
...@@ -740,20 +696,8 @@ ...@@ -740,20 +696,8 @@
* Parameters: * Parameters:
* (Object) message - The message Backbone object that was added. * (Object) message - The message Backbone object that was added.
*/ */
if (!_.isUndefined(this.clear_status_timeout)) { this.showMessage(message);
window.clearTimeout(this.clear_status_timeout);
delete this.clear_status_timeout;
}
if (message.get('type') === 'error') {
this.showMessage(message);
} else {
if (message.get('chat_state') && !message.get('delayed')) {
this.showChatStateNotification(message);
}
if (message.get('file') || message.get('message')) {
this.showMessage(message);
}
}
_converse.emit('messageAdded', { _converse.emit('messageAdded', {
'message': message, 'message': message,
'chatbox': this.model 'chatbox': this.model
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
"emojione", "emojione",
"filesize", "filesize",
"tpl!action", "tpl!action",
"tpl!csn",
"tpl!file_progress", "tpl!file_progress",
"tpl!info", "tpl!info",
"tpl!message", "tpl!message",
...@@ -22,6 +23,7 @@ ...@@ -22,6 +23,7 @@
emojione, emojione,
filesize, filesize,
tpl_action, tpl_action,
tpl_csn,
tpl_file_progress, tpl_file_progress,
tpl_info, tpl_info,
tpl_message, tpl_message,
...@@ -74,15 +76,31 @@ ...@@ -74,15 +76,31 @@
this.model.on('change:progress', this.renderFileUploadProgresBar, this); this.model.on('change:progress', this.renderFileUploadProgresBar, this);
this.model.on('change:type', this.render, this); this.model.on('change:type', this.render, this);
this.model.on('change:upload', this.render, this); this.model.on('change:upload', this.render, this);
this.model.on('destroy', this.remove, this);
this.render(); this.render();
}, },
render () { render () {
if (this.model.get('file') && !this.model.get('oob_url')) { if (this.model.isOnlyChatStateNotification()) {
return this.renderChatStateNotification()
} else if (this.model.get('file') && !this.model.get('oob_url')) {
return this.renderFileUploadProgresBar(); return this.renderFileUploadProgresBar();
} else if (this.model.get('type') === 'error') { } else if (this.model.get('type') === 'error') {
return this.renderErrorMessage(); return this.renderErrorMessage();
} else {
return this.renderChatMessage();
}
},
replaceElement (msg) {
if (!_.isNil(this.el.parentElement)) {
this.el.parentElement.replaceChild(msg, this.el);
} }
this.setElement(msg);
return this.el;
},
renderChatMessage () {
let template, text = this.model.get('message'); let template, text = this.model.get('message');
if (this.isMeCommand()) { if (this.isMeCommand()) {
template = tpl_action; template = tpl_action;
...@@ -104,13 +122,11 @@ ...@@ -104,13 +122,11 @@
var url = this.model.get('oob_url'); var url = this.model.get('oob_url');
if (url) { if (url) {
const msg_media = msg.querySelector('.chat-msg-media'); msg.querySelector('.chat-msg-media').innerHTML = _.flow(
msg_media.innerHTML = _.flow(
_.partial(u.renderFileURL, _converse), _.partial(u.renderFileURL, _converse),
_.partial(u.renderMovieURL, _converse), _.partial(u.renderMovieURL, _converse),
_.partial(u.renderAudioURL, _converse), _.partial(u.renderAudioURL, _converse),
_.partial(u.renderImageURL, _converse) _.partial(u.renderImageURL, _converse))(url);
)(url);
} }
const msg_content = msg.querySelector('.chat-msg-text'); const msg_content = msg.querySelector('.chat-msg-text');
...@@ -126,19 +142,12 @@ ...@@ -126,19 +142,12 @@
this.model.collection.trigger('rendered'); this.model.collection.trigger('rendered');
}); });
this.replaceElement(msg); this.replaceElement(msg);
if (this.model.get('type') !== 'headline') { if (this.model.get('type') !== 'headline') {
this.renderAvatar(); this.renderAvatar();
} }
}, },
replaceElement (msg) {
if (!_.isNil(this.el.parentElement)) {
this.el.parentElement.replaceChild(msg, this.el);
}
this.setElement(msg);
return this.el;
},
renderErrorMessage () { renderErrorMessage () {
const moment_time = moment(this.model.get('time')), const moment_time = moment(this.model.get('time')),
msg = u.stringToElement( msg = u.stringToElement(
...@@ -150,6 +159,41 @@ ...@@ -150,6 +159,41 @@
return this.replaceElement(msg); return this.replaceElement(msg);
}, },
renderChatStateNotification () {
if (this.model.get('delayed')) {
return this.model.destroy();
}
let text;
const from = this.model.get('from'),
name = this.model.getDisplayName();
if (this.model.get('chat_state') === _converse.COMPOSING) {
if (this.model.get('sender') === 'me') {
text = __('Typing from another device');
} else {
text = name +' '+__('is typing');
}
} else if (this.model.get('chat_state') === _converse.PAUSED) {
if (this.model.get('sender') === 'me') {
text = __('Stopped typing on the other device');
} else {
text = name +' '+__('has stopped typing');
}
} else if (this.model.get('chat_state') === _converse.GONE) {
text = name +' '+__('has gone away');
} else {
return;
}
const isodate = moment().format();
this.replaceElement(
u.stringToElement(
tpl_csn({
'message': text,
'from': from,
'isodate': isodate
})));
},
renderFileUploadProgresBar () { renderFileUploadProgresBar () {
const msg = u.stringToElement(tpl_file_progress( const msg = u.stringToElement(tpl_file_progress(
_.extend(this.model.toJSON(), { _.extend(this.model.toJSON(), {
......
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