parent
95e648e79f
commit
133df99aec
6
package-lock.json
generated
6
package-lock.json
generated
|
@ -1929,6 +1929,12 @@
|
||||||
"integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
|
"integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"filesize": {
|
||||||
|
"version": "3.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz",
|
||||||
|
"integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"fill-range": {
|
"fill-range": {
|
||||||
"version": "2.2.3",
|
"version": "2.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
|
||||||
|
|
|
@ -37,16 +37,17 @@
|
||||||
"backbone": "1.3.3",
|
"backbone": "1.3.3",
|
||||||
"backbone.browserStorage": "0.0.3",
|
"backbone.browserStorage": "0.0.3",
|
||||||
"backbone.nativeview": "^0.3.3",
|
"backbone.nativeview": "^0.3.3",
|
||||||
"bootstrap": "^4.0.0",
|
|
||||||
"bootstrap.native": "^2.0.21",
|
|
||||||
"backbone.overview": "1.0.2",
|
"backbone.overview": "1.0.2",
|
||||||
"backbone.vdomview": "1.0.1",
|
"backbone.vdomview": "1.0.1",
|
||||||
|
"bootstrap": "^4.0.0",
|
||||||
|
"bootstrap.native": "^2.0.21",
|
||||||
"bourbon": "^4.3.2",
|
"bourbon": "^4.3.2",
|
||||||
"clean-css-cli": "^4.0.10",
|
"clean-css-cli": "^4.0.10",
|
||||||
"emojione": "^3.0.3",
|
"emojione": "^3.0.3",
|
||||||
"es6-promise": "^4.1.0",
|
"es6-promise": "^4.1.0",
|
||||||
"eslint": "4.19.0",
|
"eslint": "4.19.0",
|
||||||
"eslint-plugin-lodash": "^2.3.3",
|
"eslint-plugin-lodash": "^2.3.3",
|
||||||
|
"filesize": "^3.6.1",
|
||||||
"font-awesome": "^4.7.0",
|
"font-awesome": "^4.7.0",
|
||||||
"http-server": "^0.10.0",
|
"http-server": "^0.10.0",
|
||||||
"install": "^0.9.5",
|
"install": "^0.9.5",
|
||||||
|
|
|
@ -765,7 +765,7 @@
|
||||||
// We send another message, for which an error will
|
// We send another message, for which an error will
|
||||||
// not be received, to test that errors appear
|
// not be received, to test that errors appear
|
||||||
// after the relevant message.
|
// after the relevant message.
|
||||||
msg_text = 'This message will be sent, and not receive an error';
|
msg_text = 'This message will be sent, and also receive an error';
|
||||||
message = view.model.messages.create({
|
message = view.model.messages.create({
|
||||||
'msgid': '6fcdeee3-000f-4ce8-a17e-9ce28f0ae104',
|
'msgid': '6fcdeee3-000f-4ce8-a17e-9ce28f0ae104',
|
||||||
'fullname': fullname,
|
'fullname': fullname,
|
||||||
|
@ -802,12 +802,6 @@
|
||||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
expect($chat_content.find('.chat-error').text()).toEqual(error_txt);
|
expect($chat_content.find('.chat-error').text()).toEqual(error_txt);
|
||||||
|
|
||||||
/* Incoming error messages that are not tied to a
|
|
||||||
* certain show message (via the msgid attribute),
|
|
||||||
* are not shown at all. The reason for this is
|
|
||||||
* that we may get error messages for chat state
|
|
||||||
* notifications as well.
|
|
||||||
*/
|
|
||||||
stanza = $msg({
|
stanza = $msg({
|
||||||
'to': _converse.connection.jid,
|
'to': _converse.connection.jid,
|
||||||
'type':'error',
|
'type':'error',
|
||||||
|
@ -819,7 +813,36 @@
|
||||||
.c('text', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" })
|
.c('text', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" })
|
||||||
.t('Server-to-server connection failed: Connecting failed: connection timeout');
|
.t('Server-to-server connection failed: Connecting failed: connection timeout');
|
||||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
expect($chat_content.find('.chat-error').length).toEqual(1);
|
expect($chat_content.find('.chat-error').length).toEqual(2);
|
||||||
|
|
||||||
|
// If the last message is already an error message,
|
||||||
|
// then we don't render it another time.
|
||||||
|
stanza = $msg({
|
||||||
|
'to': _converse.connection.jid,
|
||||||
|
'type':'error',
|
||||||
|
'id':'another-unused-id',
|
||||||
|
'from': sender_jid
|
||||||
|
})
|
||||||
|
.c('error', {'type': 'cancel'})
|
||||||
|
.c('remote-server-not-found', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" }).up()
|
||||||
|
.c('text', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" })
|
||||||
|
.t('Server-to-server connection failed: Connecting failed: connection timeout');
|
||||||
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
|
expect($chat_content.find('.chat-error').length).toEqual(2);
|
||||||
|
|
||||||
|
// A different error message will however render
|
||||||
|
stanza = $msg({
|
||||||
|
'to': _converse.connection.jid,
|
||||||
|
'type':'error',
|
||||||
|
'id':'another-id',
|
||||||
|
'from': sender_jid
|
||||||
|
})
|
||||||
|
.c('error', {'type': 'cancel'})
|
||||||
|
.c('remote-server-not-found', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" }).up()
|
||||||
|
.c('text', { 'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas" })
|
||||||
|
.t('Something else went wrong as well');
|
||||||
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
|
expect($chat_content.find('.chat-error').length).toEqual(3);
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
|
@ -204,9 +204,9 @@
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe("when clicked", function () {
|
describe("when clicked and a file chosen", function () {
|
||||||
|
|
||||||
it("a file upload slot is requested", mock.initConverseWithAsync(function (done, _converse) {
|
it("is uploaded and sent out", mock.initConverseWithAsync(function (done, _converse) {
|
||||||
test_utils.waitUntilDiscoConfirmed(
|
test_utils.waitUntilDiscoConfirmed(
|
||||||
_converse, _converse.domain,
|
_converse, _converse.domain,
|
||||||
[{'category': 'server', 'type':'IM'}],
|
[{'category': 'server', 'type':'IM'}],
|
||||||
|
@ -311,6 +311,135 @@
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it("shows and error message if the file is too large", mock.initConverseWithAsync(function (done, _converse) {
|
||||||
|
var IQ_stanzas = _converse.connection.IQ_stanzas;
|
||||||
|
var IQ_ids = _converse.connection.IQ_ids;
|
||||||
|
var send_backup = XMLHttpRequest.prototype.send;
|
||||||
|
|
||||||
|
test_utils.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, [], []).then(function () {
|
||||||
|
test_utils.waitUntil(function () {
|
||||||
|
return _.filter(IQ_stanzas, function (iq) {
|
||||||
|
return iq.nodeTree.querySelector(
|
||||||
|
'iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]');
|
||||||
|
}).length > 0;
|
||||||
|
}, 300).then(function () {
|
||||||
|
var stanza = _.filter(IQ_stanzas, function (iq) {
|
||||||
|
return iq.nodeTree.querySelector(
|
||||||
|
'iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]');
|
||||||
|
})[0];
|
||||||
|
var info_IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
|
||||||
|
|
||||||
|
stanza = $iq({
|
||||||
|
'type': 'result',
|
||||||
|
'from': 'localhost',
|
||||||
|
'to': 'dummy@localhost/resource',
|
||||||
|
'id': info_IQ_id
|
||||||
|
}).c('query', {'xmlns': 'http://jabber.org/protocol/disco#info'})
|
||||||
|
.c('identity', {
|
||||||
|
'category': 'server',
|
||||||
|
'type': 'im'}).up()
|
||||||
|
.c('feature', {
|
||||||
|
'var': 'http://jabber.org/protocol/disco#info'}).up()
|
||||||
|
.c('feature', {
|
||||||
|
'var': 'http://jabber.org/protocol/disco#items'});
|
||||||
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
|
|
||||||
|
_converse.api.disco.entities.get().then(function(entities) {
|
||||||
|
expect(entities.length).toBe(2);
|
||||||
|
expect(_.includes(entities.pluck('jid'), 'localhost')).toBe(true);
|
||||||
|
expect(_.includes(entities.pluck('jid'), 'dummy@localhost')).toBe(true);
|
||||||
|
|
||||||
|
expect(entities.get(_converse.domain).features.length).toBe(2);
|
||||||
|
expect(entities.get(_converse.domain).identities.length).toBe(1);
|
||||||
|
|
||||||
|
return test_utils.waitUntil(function () {
|
||||||
|
// Converse.js sees that the entity has a disco#items feature,
|
||||||
|
// so it will make a query for it.
|
||||||
|
return _.filter(IQ_stanzas, function (iq) {
|
||||||
|
return iq.nodeTree.querySelector('iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#items"]');
|
||||||
|
}).length > 0;
|
||||||
|
}, 300);
|
||||||
|
});
|
||||||
|
}).then(function () {
|
||||||
|
var stanza = _.filter(IQ_stanzas, function (iq) {
|
||||||
|
return iq.nodeTree.querySelector('iq[to="localhost"] query[xmlns="http://jabber.org/protocol/disco#items"]');
|
||||||
|
})[0];
|
||||||
|
var items_IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
|
||||||
|
stanza = $iq({
|
||||||
|
'type': 'result',
|
||||||
|
'from': 'localhost',
|
||||||
|
'to': 'dummy@localhost/resource',
|
||||||
|
'id': items_IQ_id
|
||||||
|
}).c('query', {'xmlns': 'http://jabber.org/protocol/disco#items'})
|
||||||
|
.c('item', {
|
||||||
|
'jid': 'upload.localhost',
|
||||||
|
'name': 'HTTP File Upload'});
|
||||||
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
|
|
||||||
|
_converse.api.disco.entities.get().then(function (entities) {
|
||||||
|
expect(entities.length).toBe(2);
|
||||||
|
expect(entities.get('localhost').items.length).toBe(1);
|
||||||
|
return test_utils.waitUntil(function () {
|
||||||
|
// Converse.js sees that the entity has a disco#info feature,
|
||||||
|
// so it will make a query for it.
|
||||||
|
return _.filter(IQ_stanzas, function (iq) {
|
||||||
|
return iq.nodeTree.querySelector('iq[to="upload.localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]');
|
||||||
|
}).length > 0;
|
||||||
|
}, 300);
|
||||||
|
});
|
||||||
|
}).then(function () {
|
||||||
|
var stanza = _.filter(IQ_stanzas, function (iq) {
|
||||||
|
return iq.nodeTree.querySelector('iq[to="upload.localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]');
|
||||||
|
})[0];
|
||||||
|
var IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
|
||||||
|
expect(stanza.toLocaleString()).toBe(
|
||||||
|
"<iq from='dummy@localhost/resource' to='upload.localhost' type='get' xmlns='jabber:client' id='"+IQ_id+"'>"+
|
||||||
|
"<query xmlns='http://jabber.org/protocol/disco#info'/>"+
|
||||||
|
"</iq>");
|
||||||
|
|
||||||
|
// Upload service responds and reports a maximum file size of 5MiB
|
||||||
|
stanza = $iq({'type': 'result', 'to': 'dummy@localhost/resource', 'id': IQ_id, 'from': 'upload.localhost'})
|
||||||
|
.c('query', {'xmlns': 'http://jabber.org/protocol/disco#info'})
|
||||||
|
.c('identity', {'category':'store', 'type':'file', 'name':'HTTP File Upload'}).up()
|
||||||
|
.c('feature', {'var':'urn:xmpp:http:upload:0'}).up()
|
||||||
|
.c('x', {'type':'result', 'xmlns':'jabber:x:data'})
|
||||||
|
.c('field', {'var':'FORM_TYPE', 'type':'hidden'})
|
||||||
|
.c('value').t('urn:xmpp:http:upload:0').up().up()
|
||||||
|
.c('field', {'var':'max-file-size'})
|
||||||
|
.c('value').t('5242880');
|
||||||
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
|
|
||||||
|
_converse.api.disco.entities.get().then(function (entities) {
|
||||||
|
expect(entities.get('localhost').items.get('upload.localhost').identities.where({'category': 'store'}).length).toBe(1);
|
||||||
|
_converse.api.disco.supports(Strophe.NS.HTTPUPLOAD, _converse.domain).then(
|
||||||
|
function (result) {
|
||||||
|
test_utils.createContacts(_converse, 'current');
|
||||||
|
var contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||||
|
test_utils.openChatBoxFor(_converse, contact_jid);
|
||||||
|
var view = _converse.chatboxviews.get(contact_jid);
|
||||||
|
var file = {
|
||||||
|
'type': 'image/jpeg',
|
||||||
|
'size': '5242881',
|
||||||
|
'lastModifiedDate': "",
|
||||||
|
'name': "my-juliet.jpg"
|
||||||
|
};
|
||||||
|
view.model.sendFiles([file]);
|
||||||
|
return test_utils.waitUntil(function () {
|
||||||
|
return view.el.querySelectorAll('.message').length;
|
||||||
|
}).then(function () {
|
||||||
|
const messages = view.el.querySelectorAll('.message.chat-error');
|
||||||
|
expect(messages.length).toBe(1);
|
||||||
|
expect(messages[0].textContent).toBe(
|
||||||
|
'The size of your file, my-juliet.jpg, exceeds the maximum allowed by your server, which is 5 MB.');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -29,6 +29,7 @@ require.config({
|
||||||
"emojione": "node_modules/emojione/lib/js/emojione",
|
"emojione": "node_modules/emojione/lib/js/emojione",
|
||||||
"es6-promise": "node_modules/es6-promise/dist/es6-promise.auto",
|
"es6-promise": "node_modules/es6-promise/dist/es6-promise.auto",
|
||||||
"eventemitter": "node_modules/otr/build/dep/eventemitter",
|
"eventemitter": "node_modules/otr/build/dep/eventemitter",
|
||||||
|
"filesize": "node_modules/filesize/lib/filesize",
|
||||||
"form-utils": "src/utils/form",
|
"form-utils": "src/utils/form",
|
||||||
"i18n": "src/i18n",
|
"i18n": "src/i18n",
|
||||||
"jed": "node_modules/jed/jed",
|
"jed": "node_modules/jed/jed",
|
||||||
|
|
|
@ -8,10 +8,11 @@
|
||||||
define([
|
define([
|
||||||
"converse-core",
|
"converse-core",
|
||||||
"emojione",
|
"emojione",
|
||||||
|
"filesize",
|
||||||
"tpl!chatboxes",
|
"tpl!chatboxes",
|
||||||
"backbone.overview"
|
"backbone.overview"
|
||||||
], factory);
|
], factory);
|
||||||
}(this, function (converse, emojione, tpl_chatboxes) {
|
}(this, function (converse, emojione, filesize, tpl_chatboxes) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const { $msg, Backbone, Promise, Strophe, b64_sha1, moment, utils, _ } = converse.env;
|
const { $msg, Backbone, Promise, Strophe, b64_sha1, moment, utils, _ } = converse.env;
|
||||||
|
@ -289,21 +290,36 @@
|
||||||
|
|
||||||
sendFiles (files) {
|
sendFiles (files) {
|
||||||
_converse.api.disco.supports(Strophe.NS.HTTPUPLOAD, _converse.domain).then((result) => {
|
_converse.api.disco.supports(Strophe.NS.HTTPUPLOAD, _converse.domain).then((result) => {
|
||||||
const slot_request_url = _.get(result.pop(), 'id');
|
const item = result.pop(),
|
||||||
|
data = item.dataforms.where({'FORM_TYPE': {'value': Strophe.NS.HTTPUPLOAD, 'type': "hidden"}}).pop(),
|
||||||
|
max_file_size = window.parseInt(_.get(data, 'attributes.max-file-size.value')),
|
||||||
|
slot_request_url = _.get(item, 'id');
|
||||||
|
|
||||||
if (!slot_request_url) {
|
if (!slot_request_url) {
|
||||||
const err_msg = __("Sorry, looks like file upload is not supported by your server.");
|
this.messages.create({
|
||||||
return this.trigger('showHelpMessages', [err_msg], 'error');
|
'message': __("Sorry, looks like file upload is not supported by your server."),
|
||||||
|
'type': 'error',
|
||||||
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
_.each(files, (file) => {
|
_.each(files, (file) => {
|
||||||
this.messages.create(
|
if (!window.isNaN(max_file_size) && window.parseInt(file.size) > max_file_size) {
|
||||||
_.extend(
|
return this.messages.create({
|
||||||
this.getOutgoingMessageAttributes(), {
|
'message': __('The size of your file, %1$s, exceeds the maximum allowed by your server, which is %2$s.',
|
||||||
'file': file,
|
file.name, filesize(max_file_size)),
|
||||||
'progress': 0,
|
'type': 'error',
|
||||||
'slot_request_url': slot_request_url,
|
});
|
||||||
'type': this.get('message_type'),
|
} else {
|
||||||
})
|
this.messages.create(
|
||||||
);
|
_.extend(
|
||||||
|
this.getOutgoingMessageAttributes(), {
|
||||||
|
'file': file,
|
||||||
|
'progress': 0,
|
||||||
|
'slot_request_url': slot_request_url,
|
||||||
|
'type': this.get('message_type'),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
|
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
|
||||||
},
|
},
|
||||||
|
|
|
@ -529,33 +529,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
showMessage (message) {
|
|
||||||
/* Inserts a chat message into the content area of the chat box.
|
|
||||||
* Will also insert a new day indicator if the message is on a
|
|
||||||
* different day.
|
|
||||||
*
|
|
||||||
* The message to show may either be newer than the newest
|
|
||||||
* message, or older than the oldest message.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* (Backbone.Model) message: The message object
|
|
||||||
*/
|
|
||||||
const view = new _converse.MessageView({'model': message}),
|
|
||||||
current_msg_date = moment(message.get('time')) || moment,
|
|
||||||
previous_msg_date = this.getLastMessageDate(current_msg_date),
|
|
||||||
message_el = view.el;
|
|
||||||
|
|
||||||
if (_.isNull(previous_msg_date)) {
|
|
||||||
this.content.insertAdjacentElement('afterbegin', message_el);
|
|
||||||
} else {
|
|
||||||
const previous_msg_el = sizzle(`[data-isodate="${previous_msg_date}"]:last`, this.content).pop();
|
|
||||||
previous_msg_el.insertAdjacentElement('afterend', message_el);
|
|
||||||
}
|
|
||||||
this.insertDayIndicator(message_el);
|
|
||||||
this.clearChatStateNotification(message.get('from'));
|
|
||||||
this.setScrollPosition(message_el);
|
|
||||||
},
|
|
||||||
|
|
||||||
setScrollPosition (message_el) {
|
setScrollPosition (message_el) {
|
||||||
/* Given a newly inserted message, determine whether we
|
/* Given a newly inserted message, determine whether we
|
||||||
* should keep the scrollbar in place (so as to not scroll
|
* should keep the scrollbar in place (so as to not scroll
|
||||||
|
@ -655,8 +628,50 @@
|
||||||
return !u.isVisible(this.el);
|
return !u.isVisible(this.el);
|
||||||
},
|
},
|
||||||
|
|
||||||
handleTextMessage (message) {
|
insertMessage (view) {
|
||||||
this.showMessage(message);
|
/* Given a view representing a message, insert it inot the
|
||||||
|
* content area of the chat box.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* (Backbone.View) message: The message Backbone.View
|
||||||
|
*/
|
||||||
|
if (view.model.get('type') === 'error') {
|
||||||
|
const previous_msg_el = this.content.querySelector(`[data-msgid="${view.model.get('msgid')}"]`);
|
||||||
|
if (previous_msg_el) {
|
||||||
|
return previous_msg_el.insertAdjacentElement('afterend', view.el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const current_msg_date = moment(view.model.get('time')) || moment,
|
||||||
|
previous_msg_date = this.getLastMessageDate(current_msg_date);
|
||||||
|
|
||||||
|
if (_.isNull(previous_msg_date)) {
|
||||||
|
this.content.insertAdjacentElement('afterbegin', view.el);
|
||||||
|
} else {
|
||||||
|
const previous_msg_el = sizzle(`[data-isodate="${previous_msg_date}"]:last`, this.content).pop();
|
||||||
|
if (view.model.get('type') === 'error' &&
|
||||||
|
u.hasClass('chat-error', previous_msg_el) &&
|
||||||
|
previous_msg_el.textContent === view.model.get('message')) {
|
||||||
|
// We don't show a duplicate error message
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
previous_msg_el.insertAdjacentElement('afterend', view.el);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
showMessage (message) {
|
||||||
|
/* Inserts a chat message into the content area of the chat box.
|
||||||
|
*
|
||||||
|
* Will also insert a new day indicator if the message is on a
|
||||||
|
* different day.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* (Backbone.Model) message: The message object
|
||||||
|
*/
|
||||||
|
const view = new _converse.MessageView({'model': message});
|
||||||
|
this.insertMessage(view);
|
||||||
|
this.insertDayIndicator(view.el);
|
||||||
|
this.clearChatStateNotification(message.get('from'));
|
||||||
|
this.setScrollPosition(view.el);
|
||||||
|
|
||||||
if (u.isNewMessage(message)) {
|
if (u.isNewMessage(message)) {
|
||||||
if (message.get('sender') === 'me') {
|
if (message.get('sender') === 'me') {
|
||||||
|
@ -676,21 +691,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
handleErrorMessage (message) {
|
|
||||||
const message_el = this.content.querySelector(`[data-msgid="${message.get('msgid')}"]`);
|
|
||||||
if (!_.isNull(message_el)) {
|
|
||||||
message_el.insertAdjacentHTML(
|
|
||||||
'afterend',
|
|
||||||
tpl_info({
|
|
||||||
'extra_classes': 'chat-error',
|
|
||||||
'message': message.get('message'),
|
|
||||||
'isodate': moment().format(),
|
|
||||||
'data': ''
|
|
||||||
}));
|
|
||||||
this.scrollDown();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onMessageAdded (message) {
|
onMessageAdded (message) {
|
||||||
/* Handler that gets called when a new message object is created.
|
/* Handler that gets called when a new message object is created.
|
||||||
*
|
*
|
||||||
|
@ -702,13 +702,13 @@
|
||||||
delete this.clear_status_timeout;
|
delete this.clear_status_timeout;
|
||||||
}
|
}
|
||||||
if (message.get('type') === 'error') {
|
if (message.get('type') === 'error') {
|
||||||
this.handleErrorMessage(message);
|
this.showMessage(message);
|
||||||
} else {
|
} else {
|
||||||
if (message.get('chat_state')) {
|
if (message.get('chat_state')) {
|
||||||
this.showChatStateNotification(message);
|
this.showChatStateNotification(message);
|
||||||
}
|
}
|
||||||
if (message.get('file') || message.get('message')) {
|
if (message.get('file') || message.get('message')) {
|
||||||
this.handleTextMessage(message);
|
this.showMessage(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_converse.emit('messageAdded', {
|
_converse.emit('messageAdded', {
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"emojione",
|
"emojione",
|
||||||
"tpl!action",
|
"tpl!action",
|
||||||
"tpl!file",
|
"tpl!file",
|
||||||
|
"tpl!info",
|
||||||
"tpl!message",
|
"tpl!message",
|
||||||
"tpl!spoiler_message"
|
"tpl!spoiler_message"
|
||||||
], factory);
|
], factory);
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
emojione,
|
emojione,
|
||||||
tpl_action,
|
tpl_action,
|
||||||
tpl_file,
|
tpl_file,
|
||||||
|
tpl_info,
|
||||||
tpl_message,
|
tpl_message,
|
||||||
tpl_spoiler_message
|
tpl_spoiler_message
|
||||||
) {
|
) {
|
||||||
|
@ -53,7 +55,10 @@
|
||||||
render () {
|
render () {
|
||||||
if (this.model.get('file') && !this.model.get('message')) {
|
if (this.model.get('file') && !this.model.get('message')) {
|
||||||
return this.renderFileUploadProgresBar();
|
return this.renderFileUploadProgresBar();
|
||||||
|
} else if (this.model.get('type') === 'error') {
|
||||||
|
return this.renderErrorMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
let template, username,
|
let template, username,
|
||||||
text = this.model.get('message');
|
text = this.model.get('message');
|
||||||
|
|
||||||
|
@ -91,6 +96,10 @@
|
||||||
u.renderImageURLs(msg_content).then(() => {
|
u.renderImageURLs(msg_content).then(() => {
|
||||||
this.model.collection.trigger('rendered');
|
this.model.collection.trigger('rendered');
|
||||||
});
|
});
|
||||||
|
return this.replaceElement(msg);
|
||||||
|
},
|
||||||
|
|
||||||
|
replaceElement (msg) {
|
||||||
if (!_.isNil(this.el.parentElement)) {
|
if (!_.isNil(this.el.parentElement)) {
|
||||||
this.el.parentElement.replaceChild(msg, this.el);
|
this.el.parentElement.replaceChild(msg, this.el);
|
||||||
}
|
}
|
||||||
|
@ -98,13 +107,20 @@
|
||||||
return this.el;
|
return this.el;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
renderErrorMessage () {
|
||||||
|
const moment_time = moment(this.model.get('time')),
|
||||||
|
msg = u.stringToElement(
|
||||||
|
tpl_info(_.extend(this.model.toJSON(), {
|
||||||
|
'extra_classes': 'chat-error',
|
||||||
|
'isodate': moment_time.format(),
|
||||||
|
'data': ''
|
||||||
|
})));
|
||||||
|
return this.replaceElement(msg);
|
||||||
|
},
|
||||||
|
|
||||||
renderFileUploadProgresBar () {
|
renderFileUploadProgresBar () {
|
||||||
const msg = u.stringToElement(tpl_file(this.model.toJSON()));
|
const msg = u.stringToElement(tpl_file(this.model.toJSON()));
|
||||||
if (!_.isNil(this.el.parentElement)) {
|
return this.replaceElement(msg);
|
||||||
this.el.parentElement.replaceChild(msg, this.el);
|
|
||||||
}
|
|
||||||
this.setElement(msg);
|
|
||||||
return this.el;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
isMeCommand () {
|
isMeCommand () {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user