Commit 2db3db9b authored by JC Brand's avatar JC Brand

Add support for editing messages containing mentions

parent d9c5867f
...@@ -2091,7 +2091,7 @@ ...@@ -2091,7 +2091,7 @@
describe("when received", function () { describe("when received", function () {
it("highlights all users mentioned via XEP-0372 references", it("highlights all users mentioned via XEP-0372 references",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched'], {},
function (done, _converse) { function (done, _converse) {
...@@ -2137,7 +2137,7 @@ ...@@ -2137,7 +2137,7 @@
describe("in which someone is mentioned", function () { describe("in which someone is mentioned", function () {
it("gets parsed for mentions which get turned into references", it("gets parsed for mentions which get turned into references",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched'], {},
function (done, _converse) { function (done, _converse) {
...@@ -2190,12 +2190,85 @@ ...@@ -2190,12 +2190,85 @@
expect(references.length).toBe(1); expect(references.length).toBe(1);
expect(JSON.stringify(references)) expect(JSON.stringify(references))
.toBe('[{"begin":0,"end":6,"value":"gibson","type":"mention","uri":"xmpp:gibson@localhost"}]'); .toBe('[{"begin":0,"end":6,"value":"gibson","type":"mention","uri":"xmpp:gibson@localhost"}]');
done(); done();
return; return;
}); });
})); }));
it("can get corrected and given new references",
mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {},
function (done, _converse) {
test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'tom')
.then(() => {
const view = _converse.chatboxviews.get('lounge@localhost');
['z3r0', 'mr.robot', 'gibson', 'sw0rdf1sh'].forEach((nick) => {
_converse.connection._dataRecv(test_utils.createRequest(
$pres({
'to': 'tom@localhost/resource',
'from': `lounge@localhost/${nick}`
})
.c('x', {xmlns: Strophe.NS.MUC_USER})
.c('item', {
'affiliation': 'none',
'jid': `${nick}@localhost/resource`,
'role': 'participant'
})));
});
const textarea = view.el.querySelector('textarea.chat-textarea');
textarea.value = 'hello @z3r0 @gibson @mr.robot, how are you?'
const enter_event = {
'target': textarea,
'preventDefault': _.noop,
'stopPropagation': _.noop,
'keyCode': 13 // Enter
}
spyOn(_converse.connection, 'send');
view.keyPressed(enter_event);
const msg = _converse.connection.send.calls.all()[0].args[0];
expect(msg.toLocaleString())
.toBe(`<message from='dummy@localhost/resource' `+
`to='lounge@localhost' type='groupchat' id='${msg.nodeTree.getAttribute('id')}' `+
`xmlns='jabber:client'>`+
`<body>hello z3r0 gibson mr.robot, how are you?</body>`+
`<active xmlns='http://jabber.org/protocol/chatstates'/>`+
`<reference xmlns='urn:xmpp:reference:0' begin='18' end='26' type='mention' uri='xmpp:mr.robot@localhost'/>`+
`<reference xmlns='urn:xmpp:reference:0' begin='11' end='17' type='mention' uri='xmpp:gibson@localhost'/>`+
`<reference xmlns='urn:xmpp:reference:0' begin='6' end='10' type='mention' uri='xmpp:z3r0@localhost'/>`+
`</message>`);
const first_msg = view.model.messages.findWhere({'message': 'hello z3r0 gibson mr.robot, how are you?'});
const action = view.el.querySelector('.chat-msg .chat-msg__action');
action.style.opacity = 1;
action.click();
expect(textarea.value).toBe('hello @z3r0 @gibson @mr.robot, how are you?');
expect(view.model.messages.at(0).get('correcting')).toBe(true);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(u.hasClass('correcting', view.el.querySelector('.chat-msg'))).toBe(true);
textarea.value = 'hello @z3r0 @gibson @sw0rdf1sh, how are you?';
view.keyPressed(enter_event);
const correction = _converse.connection.send.calls.all()[1].args[0];
expect(correction.toLocaleString())
.toBe(`<message from='dummy@localhost/resource' `+
`to='lounge@localhost' type='groupchat' id='${correction.nodeTree.getAttribute('id')}' `+
`xmlns='jabber:client'>`+
`<body>hello z3r0 gibson sw0rdf1sh, how are you?</body>`+
`<active xmlns='http://jabber.org/protocol/chatstates'/>`+
`<reference xmlns='urn:xmpp:reference:0' begin='18' end='27' type='mention' uri='xmpp:sw0rdf1sh@localhost'/>`+
`<reference xmlns='urn:xmpp:reference:0' begin='11' end='17' type='mention' uri='xmpp:gibson@localhost'/>`+
`<reference xmlns='urn:xmpp:reference:0' begin='6' end='10' type='mention' uri='xmpp:z3r0@localhost'/>`+
`<replace xmlns='urn:xmpp:message-correct:0' id='${msg.nodeTree.getAttribute('id')}'/>`+
`</message>`);
done();
}).catch(_.partial(console.error, _));
}));
it("includes XEP-0372 references to that person", it("includes XEP-0372 references to that person",
mock.initConverseWithPromises( mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {}, null, ['rosterGroupsFetched'], {},
......
...@@ -400,10 +400,11 @@ ...@@ -400,10 +400,11 @@
const older_versions = message.get('older_versions') || []; const older_versions = message.get('older_versions') || [];
older_versions.push(message.get('message')); older_versions.push(message.get('message'));
message.save({ message.save({
'correcting': false,
'edited': true,
'message': attrs.message, 'message': attrs.message,
'older_versions': older_versions, 'older_versions': older_versions,
'edited': true, 'references': attrs.references
'correcting': false
}); });
return this.sendMessageStanza(message); return this.sendMessageStanza(message);
} }
......
...@@ -970,7 +970,7 @@ ...@@ -970,7 +970,7 @@
currently_correcting.save('correcting', false); currently_correcting.save('correcting', false);
} }
message.save('correcting', true); message.save('correcting', true);
this.insertIntoTextArea(message.get('message'), true, true); this.insertIntoTextArea(u.prefixMentions(message), true, true);
} else { } else {
message.save('correcting', false); message.save('correcting', false);
this.insertIntoTextArea('', true, false); this.insertIntoTextArea('', true, false);
......
...@@ -167,7 +167,7 @@ ...@@ -167,7 +167,7 @@
text = xss.filterXSS(text, {'whiteList': {}}); text = xss.filterXSS(text, {'whiteList': {}});
msg_content.innerHTML = _.flow( msg_content.innerHTML = _.flow(
_.partial(u.geoUriToHttp, _, _converse.geouri_replacement), _.partial(u.geoUriToHttp, _, _converse.geouri_replacement),
_.partial(u.addMentions, _, this.model.get('references'), this.model.collection.chatbox), _.partial(u.addMentionsMarkup, _, this.model.get('references'), this.model.collection.chatbox),
u.addHyperlinks, u.addHyperlinks,
u.renderNewLines, u.renderNewLines,
_.partial(u.addEmoji, _converse, emojione, _) _.partial(u.addEmoji, _converse, emojione, _)
......
...@@ -518,6 +518,7 @@ ...@@ -518,6 +518,7 @@
is_chatroom: true, is_chatroom: true,
events: { events: {
'change input.fileupload': 'onFileSelection', 'change input.fileupload': 'onFileSelection',
'click .chat-msg__action-edit': 'onMessageEditButtonClicked',
'click .chatbox-navback': 'showControlBox', 'click .chatbox-navback': 'showControlBox',
'click .close-chatbox-button': 'close', 'click .close-chatbox-button': 'close',
'click .configure-chatroom-button': 'getAndRenderConfigurationForm', 'click .configure-chatroom-button': 'getAndRenderConfigurationForm',
......
...@@ -229,7 +229,20 @@ ...@@ -229,7 +229,20 @@
return encodeURI(decodeURI(url)).replace(/[!'()]/g, escape).replace(/\*/g, "%2A"); return encodeURI(decodeURI(url)).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
}; };
u.addMentions = function (text, references, chatbox) { u.prefixMentions = function (message) {
/* Given a message object, return its text with @ chars
* inserted before the mentioned nicknames.
*/
let text = message.get('message');
(message.get('references') || [])
.sort((a, b) => b.begin - a.begin)
.forEach(ref => {
text = `${text.slice(0, ref.begin)}@${text.slice(ref.begin)}`
});
return text;
};
u.addMentionsMarkup = function (text, references, chatbox) {
if (chatbox.get('message_type') !== 'groupchat') { if (chatbox.get('message_type') !== 'groupchat') {
return text; return text;
} }
......
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