Commit 6717315d authored by JC Brand's avatar JC Brand

Add support for message corrections in MUC.

parent 16faf62d
...@@ -68341,19 +68341,6 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -68341,19 +68341,6 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
_converse.api.promises.add(['chatBoxesFetched', 'chatBoxesInitialized', 'privateChatsAutoJoined']); _converse.api.promises.add(['chatBoxesFetched', 'chatBoxesInitialized', 'privateChatsAutoJoined']);
function getMessageBody(stanza) {
/* Given a message stanza, return the text contained in its body.
*/
const type = stanza.getAttribute('type');
if (type === 'error') {
const error = stanza.querySelector('error');
return _.propertyOf(error.querySelector('text'))('textContent') || __('Sorry, an error occurred:') + ' ' + error.innerHTML;
} else {
return _.propertyOf(stanza.querySelector('body'))('textContent');
}
}
function openChat(jid) { function openChat(jid) {
if (!utils.isValidJID(jid)) { if (!utils.isValidJID(jid)) {
return _converse.log(`Invalid JID "${jid}" provided in URL fragment`, Strophe.LogLevel.WARN); return _converse.log(`Invalid JID "${jid}" provided in URL fragment`, Strophe.LogLevel.WARN);
...@@ -68605,6 +68592,27 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -68605,6 +68592,27 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
return this.vcard.get('fullname') || this.get('jid'); return this.vcard.get('fullname') || this.get('jid');
}, },
handleMessageCorrection(stanza) {
const replace = sizzle(`replace[xmlns="${Strophe.NS.MESSAGE_CORRECT}"]`, stanza).pop();
if (replace) {
const msgid = replace && replace.getAttribute('id') || stanza.getAttribute('id'),
message = msgid && this.messages.findWhere({
msgid
}),
older_versions = message.get('older_versions') || [];
older_versions.push(message.get('message'));
message.save({
'message': _converse.chatboxes.getMessageBody(stanza),
'older_versions': older_versions,
'edited': true
});
return true;
}
return false;
},
createMessageStanza(message) { createMessageStanza(message) {
/* Given a _converse.Message Backbone.Model, return the XML /* Given a _converse.Message Backbone.Model, return the XML
* stanza that represents it. * stanza that represents it.
...@@ -68786,7 +68794,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -68786,7 +68794,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
'is_archived': !_.isNil(archive), 'is_archived': !_.isNil(archive),
'is_delayed': !_.isNil(delay), 'is_delayed': !_.isNil(delay),
'is_spoiler': !_.isNil(spoiler), 'is_spoiler': !_.isNil(spoiler),
'message': getMessageBody(stanza) || undefined, 'message': _converse.chatboxes.getMessageBody(stanza) || undefined,
'msgid': stanza.getAttribute('id'), 'msgid': stanza.getAttribute('id'),
'time': delay ? delay.getAttribute('stamp') : moment().format(), 'time': delay ? delay.getAttribute('stamp') : moment().format(),
'type': stanza.getAttribute('type') 'type': stanza.getAttribute('type')
...@@ -68941,6 +68949,19 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -68941,6 +68949,19 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
return true; return true;
}, },
getMessageBody(stanza) {
/* Given a message stanza, return the text contained in its body.
*/
const type = stanza.getAttribute('type');
if (type === 'error') {
const error = stanza.querySelector('error');
return _.propertyOf(error.querySelector('text'))('textContent') || __('Sorry, an error occurred:') + ' ' + error.innerHTML;
} else {
return _.propertyOf(stanza.querySelector('body'))('textContent');
}
},
onMessage(stanza) { onMessage(stanza) {
/* Handler method for all incoming single-user chat "message" /* Handler method for all incoming single-user chat "message"
* stanzas. * stanzas.
...@@ -69002,22 +69023,13 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -69002,22 +69023,13 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
}; };
const chatbox = this.getChatBox(contact_jid, attrs, !_.isNull(stanza.querySelector('body'))); const chatbox = this.getChatBox(contact_jid, attrs, !_.isNull(stanza.querySelector('body')));
if (chatbox) { if (chatbox && !chatbox.handleMessageCorrection(stanza)) {
const replace = sizzle(`replace[xmlns="${Strophe.NS.MESSAGE_CORRECT}"]`, stanza).pop(), const msgid = stanza.getAttribute('id'),
msgid = replace && replace.getAttribute('id') || stanza.getAttribute('id'),
message = msgid && chatbox.messages.findWhere({ message = msgid && chatbox.messages.findWhere({
msgid msgid
}); });
if (replace) { if (!message) {
const older_versions = message.get('older_versions') || [];
older_versions.push(message.get('message'));
message.save({
'message': getMessageBody(stanza),
'older_versions': older_versions,
'edited': true
});
} else if (!message) {
// Only create the message when we're sure it's not a duplicate // Only create the message when we're sure it's not a duplicate
chatbox.incrementUnreadMsgCounter(original_stanza); chatbox.incrementUnreadMsgCounter(original_stanza);
chatbox.createMessage(stanza, original_stanza); chatbox.createMessage(stanza, original_stanza);
...@@ -78483,30 +78495,33 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ ...@@ -78483,30 +78495,33 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
stanza = forwarded.querySelector('message'); stanza = forwarded.querySelector('message');
} }
const jid = stanza.getAttribute('from'),
resource = Strophe.getResourceFromJid(jid),
sender = resource && Strophe.unescapeNode(resource) || '',
subject = _.propertyOf(stanza.querySelector('subject'))('textContent');
if (this.isDuplicate(stanza, original_stanza)) { if (this.isDuplicate(stanza, original_stanza)) {
return; return;
} }
if (subject) { const jid = stanza.getAttribute('from'),
u.safeSave(this, { resource = Strophe.getResourceFromJid(jid),
'subject': { sender = resource && Strophe.unescapeNode(resource) || '';
'author': sender,
'text': subject
}
});
}
if (sender === '') { if (!this.handleMessageCorrection(stanza)) {
return; const subject = _.propertyOf(stanza.querySelector('subject'))('textContent');
}
this.incrementUnreadMsgCounter(original_stanza); if (subject) {
this.createMessage(stanza, original_stanza); u.safeSave(this, {
'subject': {
'author': sender,
'text': subject
}
});
}
if (sender === '') {
return;
}
this.incrementUnreadMsgCounter(original_stanza);
this.createMessage(stanza, original_stanza);
}
if (sender !== this.get('nick')) { if (sender !== this.get('nick')) {
// We only emit an event if it's not our own message // We only emit an event if it's not our own message
This diff is collapsed.
...@@ -1328,8 +1328,7 @@ ...@@ -1328,8 +1328,7 @@
spyOn(view.model, 'sendMessage').and.callThrough(); spyOn(view.model, 'sendMessage').and.callThrough();
test_utils.sendMessage(view, message); test_utils.sendMessage(view, message);
test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-image').length) test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-image').length, 1000).then(() => {
.then(() => {
expect(view.model.sendMessage).toHaveBeenCalled(); expect(view.model.sendMessage).toHaveBeenCalled();
var msg = $(view.el).find('.chat-content .chat-msg').last().find('.chat-msg-text'); var msg = $(view.el).find('.chat-content .chat-msg').last().find('.chat-msg-text');
expect(msg.html().trim()).toEqual( expect(msg.html().trim()).toEqual(
...@@ -1338,9 +1337,7 @@ ...@@ -1338,9 +1337,7 @@
' src="' + message + '"></a>'); ' src="' + message + '"></a>');
message += "?param1=val1&param2=val2"; message += "?param1=val1&param2=val2";
test_utils.sendMessage(view, message); test_utils.sendMessage(view, message);
return test_utils.waitUntil(function () { return test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-image').length === 2, 1000);
return view.el.querySelectorAll('.chat-content .chat-image').length === 2;
}, 1000);
}).then(() => { }).then(() => {
expect(view.model.sendMessage).toHaveBeenCalled(); 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');
...@@ -1352,9 +1349,7 @@ ...@@ -1352,9 +1349,7 @@
// Test now with two images in one message // Test now with two images in one message
message += ' hello world '+base_url+"/logo/conversejs-filled.svg"; message += ' hello world '+base_url+"/logo/conversejs-filled.svg";
test_utils.sendMessage(view, message); test_utils.sendMessage(view, message);
return test_utils.waitUntil(function () { return test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-image').length === 4, 1000);
return view.el.querySelectorAll('.chat-content .chat-image').length === 4;
}, 1000);
}).then(function () { }).then(function () {
expect(view.model.sendMessage).toHaveBeenCalled(); 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');
...@@ -1765,7 +1760,7 @@ ...@@ -1765,7 +1760,7 @@
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
msg_id = u.getUniqueId(); msg_id = u.getUniqueId();
_converse.chatboxes.onMessage($msg({ view.model.onMessage($msg({
'from': 'lounge@localhost/newguy', 'from': 'lounge@localhost/newguy',
'to': _converse.connection.jid, 'to': _converse.connection.jid,
'type': 'groupchat', 'type': 'groupchat',
...@@ -1776,7 +1771,7 @@ ...@@ -1776,7 +1771,7 @@
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?'); .toBe('But soft, what light through yonder airlock breaks?');
_converse.chatboxes.onMessage($msg({ view.model.onMessage($msg({
'from': 'lounge@localhost/newguy', 'from': 'lounge@localhost/newguy',
'to': _converse.connection.jid, 'to': _converse.connection.jid,
'type': 'chat', 'type': 'chat',
...@@ -1790,7 +1785,7 @@ ...@@ -1790,7 +1785,7 @@
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1); 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);
_converse.chatboxes.onMessage($msg({ view.model.onMessage($msg({
'from': 'lounge@localhost/newguy', 'from': 'lounge@localhost/newguy',
'to': _converse.connection.jid, 'to': _converse.connection.jid,
'type': 'chat', 'type': 'chat',
......
...@@ -62,19 +62,6 @@ ...@@ -62,19 +62,6 @@
'privateChatsAutoJoined' 'privateChatsAutoJoined'
]); ]);
function getMessageBody (stanza) {
/* Given a message stanza, return the text contained in its body.
*/
const type = stanza.getAttribute('type');
if (type === 'error') {
const error = stanza.querySelector('error');
return _.propertyOf(error.querySelector('text'))('textContent') ||
__('Sorry, an error occurred:') + ' ' + error.innerHTML;
} else {
return _.propertyOf(stanza.querySelector('body'))('textContent');
}
}
function openChat (jid) { function openChat (jid) {
if (!utils.isValidJID(jid)) { if (!utils.isValidJID(jid)) {
return _converse.log( return _converse.log(
...@@ -305,6 +292,23 @@ ...@@ -305,6 +292,23 @@
return this.vcard.get('fullname') || this.get('jid'); return this.vcard.get('fullname') || this.get('jid');
}, },
handleMessageCorrection (stanza) {
const replace = sizzle(`replace[xmlns="${Strophe.NS.MESSAGE_CORRECT}"]`, stanza).pop();
if (replace) {
const msgid = replace && replace.getAttribute('id') || stanza.getAttribute('id'),
message = msgid && this.messages.findWhere({msgid}),
older_versions = message.get('older_versions') || [];
older_versions.push(message.get('message'));
message.save({
'message': _converse.chatboxes.getMessageBody(stanza),
'older_versions': older_versions,
'edited': true
});
return true;
}
return false;
},
createMessageStanza (message) { createMessageStanza (message) {
/* Given a _converse.Message Backbone.Model, return the XML /* Given a _converse.Message Backbone.Model, return the XML
* stanza that represents it. * stanza that represents it.
...@@ -473,7 +477,7 @@ ...@@ -473,7 +477,7 @@
'is_archived': !_.isNil(archive), 'is_archived': !_.isNil(archive),
'is_delayed': !_.isNil(delay), 'is_delayed': !_.isNil(delay),
'is_spoiler': !_.isNil(spoiler), 'is_spoiler': !_.isNil(spoiler),
'message': getMessageBody(stanza) || undefined, 'message': _converse.chatboxes.getMessageBody(stanza) || undefined,
'msgid': stanza.getAttribute('id'), 'msgid': stanza.getAttribute('id'),
'time': delay ? delay.getAttribute('stamp') : moment().format(), 'time': delay ? delay.getAttribute('stamp') : moment().format(),
'type': stanza.getAttribute('type') 'type': stanza.getAttribute('type')
...@@ -614,6 +618,19 @@ ...@@ -614,6 +618,19 @@
return true; return true;
}, },
getMessageBody (stanza) {
/* Given a message stanza, return the text contained in its body.
*/
const type = stanza.getAttribute('type');
if (type === 'error') {
const error = stanza.querySelector('error');
return _.propertyOf(error.querySelector('text'))('textContent') ||
__('Sorry, an error occurred:') + ' ' + error.innerHTML;
} else {
return _.propertyOf(stanza.querySelector('body'))('textContent');
}
},
onMessage (stanza) { onMessage (stanza) {
/* Handler method for all incoming single-user chat "message" /* Handler method for all incoming single-user chat "message"
* stanzas. * stanzas.
...@@ -676,20 +693,10 @@ ...@@ -676,20 +693,10 @@
'fullname': _.get(_converse.api.contacts.get(contact_jid), 'attributes.fullname') 'fullname': _.get(_converse.api.contacts.get(contact_jid), 'attributes.fullname')
} }
const chatbox = this.getChatBox(contact_jid, attrs, !_.isNull(stanza.querySelector('body'))); const chatbox = this.getChatBox(contact_jid, attrs, !_.isNull(stanza.querySelector('body')));
if (chatbox) { if (chatbox && !chatbox.handleMessageCorrection(stanza)) {
const replace = sizzle(`replace[xmlns="${Strophe.NS.MESSAGE_CORRECT}"]`, stanza).pop(), const msgid = stanza.getAttribute('id'),
msgid = replace && replace.getAttribute('id') || stanza.getAttribute('id'),
message = msgid && chatbox.messages.findWhere({msgid}); message = msgid && chatbox.messages.findWhere({msgid});
if (!message) {
if (replace) {
const older_versions = message.get('older_versions') || [];
older_versions.push(message.get('message'));
message.save({
'message': getMessageBody(stanza),
'older_versions': older_versions,
'edited': true
});
} else if (!message) {
// Only create the message when we're sure it's not a duplicate // Only create the message when we're sure it's not a duplicate
chatbox.incrementUnreadMsgCounter(original_stanza); chatbox.incrementUnreadMsgCounter(original_stanza);
chatbox.createMessage(stanza, original_stanza); chatbox.createMessage(stanza, original_stanza);
......
...@@ -849,22 +849,24 @@ ...@@ -849,22 +849,24 @@
if (!_.isNull(forwarded)) { if (!_.isNull(forwarded)) {
stanza = forwarded.querySelector('message'); stanza = forwarded.querySelector('message');
} }
const jid = stanza.getAttribute('from'),
resource = Strophe.getResourceFromJid(jid),
sender = resource && Strophe.unescapeNode(resource) || '',
subject = _.propertyOf(stanza.querySelector('subject'))('textContent');
if (this.isDuplicate(stanza, original_stanza)) { if (this.isDuplicate(stanza, original_stanza)) {
return; return;
} }
if (subject) { const jid = stanza.getAttribute('from'),
u.safeSave(this, {'subject': {'author': sender, 'text': subject}}); resource = Strophe.getResourceFromJid(jid),
} sender = resource && Strophe.unescapeNode(resource) || '';
if (sender === '') {
return; if (!this.handleMessageCorrection(stanza)) {
const subject = _.propertyOf(stanza.querySelector('subject'))('textContent');
if (subject) {
u.safeSave(this, {'subject': {'author': sender, 'text': subject}});
}
if (sender === '') {
return;
}
this.incrementUnreadMsgCounter(original_stanza);
this.createMessage(stanza, original_stanza);
} }
this.incrementUnreadMsgCounter(original_stanza);
this.createMessage(stanza, original_stanza);
if (sender !== this.get('nick')) { if (sender !== this.get('nick')) {
// We only emit an event if it's not our own message // We only emit an event if it's not our own message
_converse.emit('message', {'stanza': original_stanza, 'chatbox': this}); _converse.emit('message', {'stanza': original_stanza, 'chatbox': this});
......
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