Cancel message correction by pressing the down arrow

Also, add a class `correcting` to the message being corrected, to
provide a visual cue.

updates #421
This commit is contained in:
JC Brand 2018-07-08 10:13:15 +02:00
parent 39c85db181
commit 84a10d77d9
10 changed files with 294 additions and 128 deletions

View File

@ -34,7 +34,7 @@
"array-bracket-spacing": "off",
"array-callback-return": "error",
"arrow-body-style": "off",
"arrow-parens": "error",
"arrow-parens": "off",
"arrow-spacing": "error",
"block-scoped-var": "off",
"block-spacing": "off",

View File

@ -8859,6 +8859,10 @@ body.reset {
-webkit-animation: colorchange-chatmessage 1s; }
#conversejs .message.chat-msg:hover {
background-color: rgba(0, 0, 0, 0.035); }
#conversejs .message.chat-msg.correcting.groupchat {
background-color: #fdf1ee; }
#conversejs .message.chat-msg.correcting:not(.groupchat) {
background-color: #e7f7ee; }
#conversejs .message.chat-msg .spoiler {
margin-top: 0.5em; }
#conversejs .message.chat-msg .spoiler-hint {

84
dist/converse.js vendored
View File

@ -68675,7 +68675,6 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
return {
'fullname': fullname,
'replace': this.correction,
'from': _converse.bare_jid,
'sender': 'me',
'time': moment().format(),
@ -68691,21 +68690,18 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
* Parameters:
* (Message) message - The chat message
*/
if (attrs.replace) {
const message = this.messages.findWhere({
'id': attrs.replace
});
const message = this.messages.findWhere('correcting');
if (message) {
const older_versions = message.get('older_versions') || [];
older_versions.push(message.get('message'));
message.save({
'message': attrs.message,
'older_versions': older_versions,
'edited': true
});
return this.sendMessageStanza(message);
}
if (message) {
const older_versions = message.get('older_versions') || [];
older_versions.push(message.get('message'));
message.save({
'message': attrs.message,
'older_versions': older_versions,
'edited': true,
'correcting': false
});
return this.sendMessageStanza(message);
}
return this.sendMessageStanza(this.messages.create(attrs));
@ -69344,6 +69340,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
const KEY = {
ENTER: 13,
UP_ARROW: 38,
DOWN_ARROW: 40,
FORWARD_SLASH: 47
};
converse.plugins.add('converse-chatview', {
@ -69621,7 +69618,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
'click .toggle-smiley ul.emoji-picker li': 'insertEmoji',
'click .toggle-smiley': 'toggleEmojiMenu',
'click .upload-file': 'toggleFileUpload',
'keyup .chat-textarea': 'keyPressed',
'keydown .chat-textarea': 'keyPressed',
'input .chat-textarea': 'inputChanged'
},
@ -70103,6 +70100,10 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
*/
this.showMessage(message);
if (message.get('correcting')) {
this.insertIntoTextArea(message.get('message'), true);
}
_converse.emit('messageAdded', {
'message': message,
'chatbox': this.model
@ -70142,7 +70143,6 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
}
const attrs = this.model.getOutgoingMessageAttributes(text, spoiler_hint);
delete this.model.correction;
this.model.sendMessage(attrs);
},
@ -70203,10 +70203,16 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
keyPressed(ev) {
/* Event handler for when a key is pressed in a chat box textarea.
*/
if (ev.keyCode === KEY.ENTER && !ev.shiftKey) {
if (ev.shiftKey) {
return;
}
if (ev.keyCode === KEY.ENTER) {
this.onFormSubmitted(ev);
} else if (ev.keyCode === KEY.UP_ARROW && !ev.shiftKey) {
} else if (ev.keyCode === KEY.UP_ARROW && !ev.target.selectionEnd) {
this.editPreviousMessage();
} else if (ev.keyCode === KEY.DOWN_ARROW && ev.target.selectionEnd === ev.target.value.length) {
this.cancelMessageCorrection();
} else if (ev.keyCode !== KEY.FORWARD_SLASH && this.model.get('chat_state') !== _converse.COMPOSING) {
// Set chat state to composing if keyCode is not a forward-slash
// (which would imply an internal command and not a message).
@ -70214,16 +70220,19 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
}
},
cancelMessageCorrection() {
this.insertIntoTextArea('', true);
this.model.messages.where('correcting').forEach(msg => msg.save('correcting', false));
},
editPreviousMessage() {
const msg = _.findLast(this.model.messages.models, msg => msg.get('message'));
if (msg) {
const textbox_el = this.el.querySelector('.chat-textarea');
textbox_el.value = msg.get('message');
textbox_el.focus(); // We don't set "correcting" the Backbone-way, because
this.insertIntoTextArea(msg.get('message'), true); // We don't set "correcting" the Backbone-way, because
// we don't want it to persist to storage.
this.model.correction = msg.get('id');
msg.save('correcting', true);
}
},
@ -70250,15 +70259,21 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
return this;
},
insertIntoTextArea(value) {
insertIntoTextArea(value, replace = false) {
const textbox_el = this.el.querySelector('.chat-textarea');
let existing = textbox_el.value;
if (existing && existing[existing.length - 1] !== ' ') {
existing = existing + ' ';
if (replace) {
textbox_el.value = value;
} else {
let existing = textbox_el.value;
if (existing && existing[existing.length - 1] !== ' ') {
existing = existing + ' ';
}
textbox_el.value = existing + value + ' ';
}
textbox_el.value = existing + value + ' ';
textbox_el.focus();
},
@ -74572,10 +74587,11 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
initialize() {
this.model.vcard.on('change', this.render, this);
this.model.on('change:correcting', this.render, this);
this.model.on('change:message', this.render, this);
this.model.on('change:progress', this.renderFileUploadProgresBar, this);
this.model.on('change:type', this.render, this);
this.model.on('change:upload', this.render, this);
this.model.on('change:message', this.render, this);
this.model.on('destroy', this.remove, this);
this.render();
},
@ -74746,6 +74762,10 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
}
}
if (this.model.get('correcting')) {
extra_classes += ' correcting';
}
return extra_classes;
}
@ -75997,7 +76017,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
'click .toggle-smiley ul.emoji-picker li': 'insertEmoji',
'click .toggle-smiley': 'toggleEmojiMenu',
'click .upload-file': 'toggleFileUpload',
'keypress .chat-textarea': 'keyPressed',
'keydown .chat-textarea': 'keyPressed',
'input .chat-textarea': 'inputChanged'
},
@ -85632,13 +85652,13 @@ __p += '\n </span>\n <time timestamp="' +
__e(o.isodate) +
'" class="chat-msg-time">' +
__e(o.pretty_time) +
'</time>\n </span>\n <span class="chat-msg-text"></span>\n <div class="chat-msg-media"></div>\n ';
'</time>\n </span>\n ';
if (o.edited) { ;
__p += ' <i title="' +
__e(o.__('This message has been edited')) +
'" class="fa fa-edit chat-msg-edited"></i> ';
} ;
__p += '\n </div>\n</div>\n';
__p += '\n <span class="chat-msg-text"></span>\n <div class="chat-msg-media"></div>\n </div>\n</div>\n';
return __p
};

View File

@ -73,6 +73,14 @@
&:hover {
background-color: rgba(0, 0, 0, 0.035);
}
&.correcting {
&.groupchat {
background-color: lighten($chatroom-head-color, 35%);
}
&:not(.groupchat) {
background-color: lighten($chat-head-color, 50%);
}
}
.spoiler {
margin-top: 0.5em;

View File

@ -19,6 +19,97 @@
describe("A Chat Message", function () {
it("can be sent as a correction",
mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {},
function (done, _converse) {
test_utils.createContacts(_converse, 'current', 1);
test_utils.openControlBox();
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid);
const view = _converse.chatboxviews.get(contact_jid);
const textarea = view.el.querySelector('textarea.chat-textarea');
expect(textarea.value).toBe('');
view.keyPressed({
target: textarea,
keyCode: 38 // Up arrow
});
expect(textarea.value).toBe('');
textarea.value = 'But soft, what light through yonder airlock breaks?';
view.keyPressed({
target: textarea,
preventDefault: _.noop,
keyCode: 13 // Enter
});
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
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?'});
expect(textarea.value).toBe('');
view.keyPressed({
target: textarea,
keyCode: 38 // Up arrow
});
expect(textarea.value).toBe('But soft, what light through yonder airlock breaks?');
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);
spyOn(_converse.connection, 'send');
textarea.value = 'But soft, what light through yonder window breaks?';
view.keyPressed({
target: textarea,
preventDefault: _.noop,
keyCode: 13 // Enter
});
expect(_converse.connection.send).toHaveBeenCalled();
const msg = _converse.connection.send.calls.all()[0].args[0];
expect(msg.toLocaleString())
.toBe(`<message from='dummy@localhost/resource' `+
`to='max.frankfurter@localhost' type='chat' id='${msg.nodeTree.getAttribute('id')}' `+
`xmlns='jabber:client'>`+
`<body>But soft, what light through yonder window breaks?</body>`+
`<active xmlns='http://jabber.org/protocol/chatstates'/>`+
`<replace xmlns='urn:xmpp:message-correct:0' id='${first_msg.get('msgid')}'/>`+
`</message>`);
expect(view.model.messages.models.length).toBe(1);
const corrected_message = view.model.messages.at(0);
expect(corrected_message.get('msgid')).toBe(first_msg.get('msgid'));
expect(corrected_message.get('correcting')).toBe(false);
expect(corrected_message.get('older_versions').length).toBe(1);
expect(corrected_message.get('older_versions')[0]).toBe('But soft, what light through yonder airlock breaks?');
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(u.hasClass('correcting', view.el.querySelector('.chat-msg'))).toBe(false);
// Test that pressing the down arrow cancels message correction
expect(textarea.value).toBe('');
view.keyPressed({
target: textarea,
keyCode: 38 // Up arrow
});
expect(textarea.value).toBe('But soft, what light through yonder window breaks?');
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);
expect(textarea.value).toBe('But soft, what light through yonder window breaks?');
view.keyPressed({
target: textarea,
keyCode: 40 // Down arrow
});
expect(textarea.value).toBe('');
expect(view.model.messages.at(0).get('correcting')).toBe(false);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(u.hasClass('correcting', view.el.querySelector('.chat-msg'))).toBe(false);
done();
}));
describe("when received from someone else", function () {
it("will open a chatbox and be displayed inside it",
@ -136,70 +227,6 @@
});
}));
it("can be sent as a correction",
mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {},
function (done, _converse) {
test_utils.createContacts(_converse, 'current', 1);
test_utils.openControlBox();
const message = 'This is a received message';
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
test_utils.openChatBoxFor(_converse, contact_jid);
const view = _converse.chatboxviews.get(contact_jid);
const textarea = view.el.querySelector('textarea.chat-textarea');
expect(textarea.value).toBe('');
view.keyPressed({
target: textarea,
keyCode: 38
});
expect(textarea.value).toBe('');
textarea.value = 'But soft, what light through yonder airlock breaks?';
view.keyPressed({
target: textarea,
preventDefault: _.noop,
keyCode: 13
});
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
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?'});
expect(textarea.value).toBe('');
view.keyPressed({
target: textarea,
keyCode: 38
});
expect(textarea.value).toBe('But soft, what light through yonder airlock breaks?');
spyOn(_converse.connection, 'send');
textarea.value = 'But soft, what light through yonder window breaks?';
view.keyPressed({
target: textarea,
preventDefault: _.noop,
keyCode: 13
});
expect(_converse.connection.send).toHaveBeenCalled();
const msg = _converse.connection.send.calls.all()[0].args[0];
expect(msg.toLocaleString())
.toBe(`<message from='dummy@localhost/resource' `+
`to='max.frankfurter@localhost' type='chat' id='${msg.nodeTree.getAttribute('id')}' `+
`xmlns='jabber:client'>`+
`<body>But soft, what light through yonder window breaks?</body>`+
`<active xmlns='http://jabber.org/protocol/chatstates'/>`+
`<replace xmlns='urn:xmpp:message-correct:0' id='${first_msg.get('msgid')}'/>`+
`</message>`);
expect(view.model.messages.models.length).toBe(1);
const corrected_message = view.model.messages.at(0);
expect(corrected_message.get('msgid')).toBe(first_msg.get('msgid'));
expect(corrected_message.get('older_versions').length).toBe(1);
expect(corrected_message.get('older_versions')[0]).toBe('But soft, what light through yonder airlock breaks?');
done();
}));
describe("when a chatbox is opened for someone who is not in the roster", function () {
it("the VCard for that user is fetched and the chatbox updated with the results",
@ -1663,7 +1690,6 @@
function (done, _converse) {
let msg_id, view;
test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy')
.then(() => {
const jid = 'lounge@localhost';
@ -1733,5 +1759,98 @@
done();
});
}));
it("can be sent as a correction",
mock.initConverseWithPromises(
null, ['rosterGroupsFetched'], {},
function (done, _converse) {
let msg_id, view;
test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy')
.then(() => {
const jid = 'lounge@localhost';
const room = _converse.api.rooms.get(jid);
view = _converse.chatboxviews.get(jid);
const textarea = view.el.querySelector('textarea.chat-textarea');
expect(textarea.value).toBe('');
view.keyPressed({
target: textarea,
keyCode: 38 // Up arrow
});
expect(textarea.value).toBe('');
textarea.value = 'But soft, what light through yonder airlock breaks?';
view.keyPressed({
target: textarea,
preventDefault: _.noop,
keyCode: 13 // Enter
});
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
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?'});
expect(textarea.value).toBe('');
view.keyPressed({
target: textarea,
keyCode: 38 // Up arrow
});
expect(textarea.value).toBe('But soft, what light through yonder airlock breaks?');
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);
spyOn(_converse.connection, 'send');
textarea.value = 'But soft, what light through yonder window breaks?';
view.keyPressed({
target: textarea,
preventDefault: _.noop,
keyCode: 13 // Enter
});
expect(_converse.connection.send).toHaveBeenCalled();
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>But soft, what light through yonder window breaks?</body>`+
`<active xmlns='http://jabber.org/protocol/chatstates'/>`+
`<replace xmlns='urn:xmpp:message-correct:0' id='${first_msg.get('msgid')}'/>`+
`</message>`);
expect(view.model.messages.models.length).toBe(1);
const corrected_message = view.model.messages.at(0);
expect(corrected_message.get('msgid')).toBe(first_msg.get('msgid'));
expect(corrected_message.get('correcting')).toBe(false);
expect(corrected_message.get('older_versions').length).toBe(1);
expect(corrected_message.get('older_versions')[0]).toBe('But soft, what light through yonder airlock breaks?');
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(u.hasClass('correcting', view.el.querySelector('.chat-msg'))).toBe(false);
// Test that pressing the down arrow cancels message correction
expect(textarea.value).toBe('');
view.keyPressed({
target: textarea,
keyCode: 38 // Up arrow
});
expect(textarea.value).toBe('But soft, what light through yonder window breaks?');
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);
expect(textarea.value).toBe('But soft, what light through yonder window breaks?');
view.keyPressed({
target: textarea,
keyCode: 40 // Down arrow
});
expect(textarea.value).toBe('');
expect(view.model.messages.at(0).get('correcting')).toBe(false);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(u.hasClass('correcting', view.el.querySelector('.chat-msg'))).toBe(false);
done();
});
}));
});
}));

View File

@ -365,7 +365,6 @@
return {
'fullname': fullname,
'replace': this.correction,
'from': _converse.bare_jid,
'sender': 'me',
'time': moment().format(),
@ -381,18 +380,17 @@
* Parameters:
* (Message) message - The chat message
*/
if (attrs.replace) {
const message = this.messages.findWhere({'id': attrs.replace})
if (message) {
const older_versions = message.get('older_versions') || [];
older_versions.push(message.get('message'));
message.save({
'message': attrs.message,
'older_versions': older_versions,
'edited': true
});
return this.sendMessageStanza(message);
}
const message = this.messages.findWhere('correcting')
if (message) {
const older_versions = message.get('older_versions') || [];
older_versions.push(message.get('message'));
message.save({
'message': attrs.message,
'older_versions': older_versions,
'edited': true,
'correcting': false
});
return this.sendMessageStanza(message);
}
return this.sendMessageStanza(this.messages.create(attrs));
},

View File

@ -55,6 +55,7 @@
const KEY = {
ENTER: 13,
UP_ARROW: 38,
DOWN_ARROW: 40,
FORWARD_SLASH: 47
};
@ -334,7 +335,7 @@
'click .toggle-smiley ul.emoji-picker li': 'insertEmoji',
'click .toggle-smiley': 'toggleEmojiMenu',
'click .upload-file': 'toggleFileUpload',
'keyup .chat-textarea': 'keyPressed',
'keydown .chat-textarea': 'keyPressed',
'input .chat-textarea': 'inputChanged'
},
@ -802,7 +803,9 @@
* (Object) message - The message Backbone object that was added.
*/
this.showMessage(message);
if (message.get('correcting')) {
this.insertIntoTextArea(message.get('message'), true);
}
_converse.emit('messageAdded', {
'message': message,
'chatbox': this.model
@ -848,7 +851,6 @@
return;
}
const attrs = this.model.getOutgoingMessageAttributes(text, spoiler_hint);
delete this.model.correction;
this.model.sendMessage(attrs);
},
@ -912,10 +914,14 @@
keyPressed (ev) {
/* Event handler for when a key is pressed in a chat box textarea.
*/
if (ev.keyCode === KEY.ENTER && !ev.shiftKey) {
if (ev.shiftKey) { return; }
if (ev.keyCode === KEY.ENTER) {
this.onFormSubmitted(ev);
} else if (ev.keyCode === KEY.UP_ARROW && !ev.shiftKey) {
} else if (ev.keyCode === KEY.UP_ARROW && !ev.target.selectionEnd) {
this.editPreviousMessage();
} else if (ev.keyCode === KEY.DOWN_ARROW && ev.target.selectionEnd === ev.target.value.length) {
this.cancelMessageCorrection();
} else if (ev.keyCode !== KEY.FORWARD_SLASH && this.model.get('chat_state') !== _converse.COMPOSING) {
// Set chat state to composing if keyCode is not a forward-slash
// (which would imply an internal command and not a message).
@ -923,15 +929,18 @@
}
},
cancelMessageCorrection () {
this.insertIntoTextArea('', true);
this.model.messages.where('correcting').forEach(msg => msg.save('correcting', false));
},
editPreviousMessage () {
const msg = _.findLast(this.model.messages.models, (msg) => msg.get('message'));
if (msg) {
const textbox_el = this.el.querySelector('.chat-textarea');
textbox_el.value = msg.get('message');
textbox_el.focus()
this.insertIntoTextArea(msg.get('message'), true);
// We don't set "correcting" the Backbone-way, because
// we don't want it to persist to storage.
this.model.correction = msg.get('id');
msg.save('correcting', true);
}
},
@ -951,13 +960,17 @@
return this;
},
insertIntoTextArea (value) {
insertIntoTextArea (value, replace=false) {
const textbox_el = this.el.querySelector('.chat-textarea');
let existing = textbox_el.value;
if (existing && (existing[existing.length-1] !== ' ')) {
existing = existing + ' ';
if (replace) {
textbox_el.value = value;
} else {
let existing = textbox_el.value;
if (existing && (existing[existing.length-1] !== ' ')) {
existing = existing + ' ';
}
textbox_el.value = existing+value+' ';
}
textbox_el.value = existing+value+' ';
textbox_el.focus()
},

View File

@ -91,10 +91,11 @@
initialize () {
this.model.vcard.on('change', this.render, this);
this.model.on('change:correcting', this.render, this);
this.model.on('change:message', this.render, this);
this.model.on('change:progress', this.renderFileUploadProgresBar, this);
this.model.on('change:type', this.render, this);
this.model.on('change:upload', this.render, this);
this.model.on('change:message', this.render, this);
this.model.on('destroy', this.remove, this);
this.render();
},
@ -262,6 +263,9 @@
extra_classes += ' mentioned';
}
}
if (this.model.get('correcting')) {
extra_classes += ' correcting';
}
return extra_classes;
}
});

View File

@ -529,7 +529,7 @@
'click .toggle-smiley ul.emoji-picker li': 'insertEmoji',
'click .toggle-smiley': 'toggleEmojiMenu',
'click .upload-file': 'toggleFileUpload',
'keypress .chat-textarea': 'keyPressed',
'keydown .chat-textarea': 'keyPressed',
'input .chat-textarea': 'inputChanged'
},

View File

@ -9,8 +9,8 @@
</span>
<time timestamp="{{{o.isodate}}}" class="chat-msg-time">{{{o.pretty_time}}}</time>
</span>
{[ 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.edited) { ]} <i title="{{{o.__('This message has been edited')}}}" class="fa fa-edit chat-msg-edited"></i> {[ } ]}
</div>
</div>