Commit 133df99a authored by JC Brand's avatar JC Brand

Honor the filesize restrictions of the XMPP server

updates #161
parent 95e648e7
...@@ -1929,6 +1929,12 @@ ...@@ -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",
......
...@@ -765,7 +765,7 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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();
})); }));
}); });
......
This diff is collapsed.
...@@ -29,6 +29,7 @@ require.config({ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 () {
......
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