Show error message with option to retry when MAM query times out
This commit is contained in:
parent
6307fa698d
commit
89ac4a6969
@ -5,6 +5,7 @@
|
|||||||
- Add a new GUI for moderator actions. You can trigger it by entering `/modtools` in a MUC.
|
- Add a new GUI for moderator actions. You can trigger it by entering `/modtools` in a MUC.
|
||||||
- Reconnect if the server doesn't respond to a `ping` within 10 seconds.
|
- Reconnect if the server doesn't respond to a `ping` within 10 seconds.
|
||||||
- Don't query for MAM MUC messages before the cached messages have been restored (another cause of duplicate messages).
|
- Don't query for MAM MUC messages before the cached messages have been restored (another cause of duplicate messages).
|
||||||
|
- Show an error message and option to retry when fetching of the MAM archive times out
|
||||||
|
|
||||||
## 5.0.0 (2019-08-08)
|
## 5.0.0 (2019-08-08)
|
||||||
|
|
||||||
|
@ -450,7 +450,7 @@ body.converse-fullscreen {
|
|||||||
width: 1em;
|
width: 1em;
|
||||||
display: block;
|
display: block;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 2em;
|
padding: 0.5em 0;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
.left {
|
.left {
|
||||||
|
@ -573,7 +573,7 @@
|
|||||||
await u.waitUntil(() => view.el.querySelectorAll('.message').length)
|
await u.waitUntil(() => view.el.querySelectorAll('.message').length)
|
||||||
const messages = view.el.querySelectorAll('.message.chat-error');
|
const messages = view.el.querySelectorAll('.message.chat-error');
|
||||||
expect(messages.length).toBe(1);
|
expect(messages.length).toBe(1);
|
||||||
expect(messages[0].textContent).toBe(
|
expect(messages[0].textContent.trim()).toBe(
|
||||||
'The size of your file, my-juliet.jpg, exceeds the maximum allowed by your server, which is 5 MB.');
|
'The size of your file, my-juliet.jpg, exceeds the maximum allowed by your server, which is 5 MB.');
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
|
108
spec/mam.js
108
spec/mam.js
@ -772,7 +772,7 @@
|
|||||||
* </result>
|
* </result>
|
||||||
* </message>
|
* </message>
|
||||||
*/
|
*/
|
||||||
const msg1 = $msg({'id':'aeb213', 'to':'juliet@capulet.lit/chamber'})
|
const msg1 = $msg({'id':'aeb212', 'to':'juliet@capulet.lit/chamber'})
|
||||||
.c('result', {'xmlns': 'urn:xmpp:mam:2', 'queryid':queryid, 'id':'28482-98726-73623'})
|
.c('result', {'xmlns': 'urn:xmpp:mam:2', 'queryid':queryid, 'id':'28482-98726-73623'})
|
||||||
.c('forwarded', {'xmlns':'urn:xmpp:forward:0'})
|
.c('forwarded', {'xmlns':'urn:xmpp:forward:0'})
|
||||||
.c('delay', {'xmlns':'urn:xmpp:delay', 'stamp':'2010-07-10T23:08:25Z'}).up()
|
.c('delay', {'xmlns':'urn:xmpp:delay', 'stamp':'2010-07-10T23:08:25Z'}).up()
|
||||||
@ -943,7 +943,7 @@
|
|||||||
`</query>`+
|
`</query>`+
|
||||||
`</iq>`
|
`</iq>`
|
||||||
);
|
);
|
||||||
const msg1 = $msg({'id':'aeb213', 'to': contact_jid})
|
const msg1 = $msg({'id':'aeb212', 'to': contact_jid})
|
||||||
.c('result', {'xmlns': 'urn:xmpp:mam:2', 'queryid':queryid, 'id':'28482-98726-73623'})
|
.c('result', {'xmlns': 'urn:xmpp:mam:2', 'queryid':queryid, 'id':'28482-98726-73623'})
|
||||||
.c('forwarded', {'xmlns':'urn:xmpp:forward:0'})
|
.c('forwarded', {'xmlns':'urn:xmpp:forward:0'})
|
||||||
.c('delay', {'xmlns':'urn:xmpp:delay', 'stamp':'2010-07-10T23:08:25Z'}).up()
|
.c('delay', {'xmlns':'urn:xmpp:delay', 'stamp':'2010-07-10T23:08:25Z'}).up()
|
||||||
@ -974,6 +974,110 @@
|
|||||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it("will show an error message if the MAM query times out",
|
||||||
|
mock.initConverse(
|
||||||
|
null, ['discoInitialized'], {},
|
||||||
|
async function (done, _converse) {
|
||||||
|
|
||||||
|
const sendIQ = _converse.connection.sendIQ;
|
||||||
|
|
||||||
|
let timeout_happened = false;
|
||||||
|
spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) {
|
||||||
|
sendIQ.bind(this)(iq, callback, errback);
|
||||||
|
if (!timeout_happened) {
|
||||||
|
if (typeof(iq.tree) === "function") {
|
||||||
|
iq = iq.tree();
|
||||||
|
}
|
||||||
|
if (sizzle('query[xmlns="urn:xmpp:mam:2"]', iq).length) {
|
||||||
|
// We emulate a timeout event
|
||||||
|
callback(null);
|
||||||
|
timeout_happened = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await test_utils.waitForRoster(_converse, 'current', 1);
|
||||||
|
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
|
||||||
|
await test_utils.openChatBoxFor(_converse, contact_jid);
|
||||||
|
await test_utils.waitUntilDiscoConfirmed(_converse, _converse.bare_jid, null, [Strophe.NS.MAM]);
|
||||||
|
|
||||||
|
const IQ_stanzas = _converse.connection.IQ_stanzas;
|
||||||
|
let sent_stanza = await u.waitUntil(() => IQ_stanzas.filter(iq => sizzle('query[xmlns="urn:xmpp:mam:2"]', iq).length).pop());
|
||||||
|
let queryid = sent_stanza.querySelector('query').getAttribute('queryid');
|
||||||
|
|
||||||
|
expect(Strophe.serialize(sent_stanza)).toBe(
|
||||||
|
`<iq id="${sent_stanza.getAttribute('id')}" type="set" xmlns="jabber:client">`+
|
||||||
|
`<query queryid="${queryid}" xmlns="urn:xmpp:mam:2">`+
|
||||||
|
`<x type="submit" xmlns="jabber:x:data">`+
|
||||||
|
`<field type="hidden" var="FORM_TYPE"><value>urn:xmpp:mam:2</value></field>`+
|
||||||
|
`<field var="with"><value>mercutio@montague.lit</value></field>`+
|
||||||
|
`</x>`+
|
||||||
|
`<set xmlns="http://jabber.org/protocol/rsm"><max>50</max><before></before></set>`+
|
||||||
|
`</query>`+
|
||||||
|
`</iq>`);
|
||||||
|
|
||||||
|
const view = _converse.chatboxviews.get(contact_jid);
|
||||||
|
expect(view.model.messages.length).toBe(1);
|
||||||
|
expect(view.model.messages.at(0).get('ephemeral')).toBe(false);
|
||||||
|
expect(view.model.messages.at(0).get('type')).toBe('error');
|
||||||
|
expect(view.model.messages.at(0).get('message')).toBe('Timeout while trying to fetch archived messages.');
|
||||||
|
|
||||||
|
let err_message = view.el.querySelector('.message.chat-error');
|
||||||
|
err_message.querySelector('.retry').click();
|
||||||
|
expect(err_message.querySelector('.spinner')).not.toBe(null);
|
||||||
|
|
||||||
|
while (_converse.connection.IQ_stanzas.length) {
|
||||||
|
_converse.connection.IQ_stanzas.pop();
|
||||||
|
}
|
||||||
|
sent_stanza = await u.waitUntil(() => IQ_stanzas.filter(iq => sizzle('query[xmlns="urn:xmpp:mam:2"]', iq).length).pop());
|
||||||
|
queryid = sent_stanza.querySelector('query').getAttribute('queryid');
|
||||||
|
expect(Strophe.serialize(sent_stanza)).toBe(
|
||||||
|
`<iq id="${sent_stanza.getAttribute('id')}" type="set" xmlns="jabber:client">`+
|
||||||
|
`<query queryid="${queryid}" xmlns="urn:xmpp:mam:2">`+
|
||||||
|
`<x type="submit" xmlns="jabber:x:data">`+
|
||||||
|
`<field type="hidden" var="FORM_TYPE"><value>urn:xmpp:mam:2</value></field>`+
|
||||||
|
`<field var="with"><value>mercutio@montague.lit</value></field>`+
|
||||||
|
`</x>`+
|
||||||
|
`<set xmlns="http://jabber.org/protocol/rsm"><max>50</max><before></before></set>`+
|
||||||
|
`</query>`+
|
||||||
|
`</iq>`);
|
||||||
|
|
||||||
|
const msg1 = $msg({'id':'aeb212', 'to': contact_jid})
|
||||||
|
.c('result', {'xmlns': 'urn:xmpp:mam:2', 'queryid': queryid, 'id':'28482-98726-73623'})
|
||||||
|
.c('forwarded', {'xmlns':'urn:xmpp:forward:0'})
|
||||||
|
.c('delay', {'xmlns':'urn:xmpp:delay', 'stamp':'2010-07-10T23:08:25Z'}).up()
|
||||||
|
.c('message', {
|
||||||
|
'xmlns':'jabber:client',
|
||||||
|
'to': contact_jid,
|
||||||
|
'from': _converse.bare_jid,
|
||||||
|
'type':'chat' })
|
||||||
|
.c('body').t("Call me but love, and I'll be new baptized;");
|
||||||
|
_converse.connection._dataRecv(test_utils.createRequest(msg1));
|
||||||
|
|
||||||
|
const msg2 = $msg({'id':'aeb213', 'to': contact_jid})
|
||||||
|
.c('result', {'xmlns': 'urn:xmpp:mam:2', 'queryid': queryid, 'id':'28482-98726-73624'})
|
||||||
|
.c('forwarded', {'xmlns':'urn:xmpp:forward:0'})
|
||||||
|
.c('delay', {'xmlns':'urn:xmpp:delay', 'stamp':'2010-07-10T23:18:25Z'}).up()
|
||||||
|
.c('message', {
|
||||||
|
'xmlns':'jabber:client',
|
||||||
|
'to': contact_jid,
|
||||||
|
'from': _converse.bare_jid,
|
||||||
|
'type':'chat' })
|
||||||
|
.c('body').t("Henceforth I never will be Romeo.");
|
||||||
|
_converse.connection._dataRecv(test_utils.createRequest(msg2));
|
||||||
|
|
||||||
|
const stanza = $iq({'type': 'result', 'id': sent_stanza.getAttribute('id')})
|
||||||
|
.c('fin', {'xmlns': 'urn:xmpp:mam:2', 'complete': true})
|
||||||
|
.c('set', {'xmlns': 'http://jabber.org/protocol/rsm'})
|
||||||
|
.c('first', {'index': '0'}).t('28482-98726-73623').up()
|
||||||
|
.c('last').t('28482-98726-73624').up()
|
||||||
|
.c('count').t('2');
|
||||||
|
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||||
|
await u.waitUntil(() => view.model.messages.length === 2, 500);
|
||||||
|
err_message = view.el.querySelector('.message.chat-error');
|
||||||
|
expect(err_message).toBe(null);
|
||||||
|
done();
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
@ -1761,7 +1761,7 @@
|
|||||||
.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));
|
||||||
await new Promise((resolve, reject) => view.once('messageInserted', resolve));
|
await new Promise((resolve, reject) => view.once('messageInserted', resolve));
|
||||||
expect(chat_content.querySelector('.chat-error').textContent).toEqual(error_txt);
|
expect(chat_content.querySelector('.chat-error').textContent.trim()).toEqual(error_txt);
|
||||||
stanza = $msg({
|
stanza = $msg({
|
||||||
'to': _converse.connection.jid,
|
'to': _converse.connection.jid,
|
||||||
'type': 'error',
|
'type': 'error',
|
||||||
|
424
spec/muc.js
424
spec/muc.js
File diff suppressed because it is too large
Load Diff
@ -1430,7 +1430,7 @@
|
|||||||
|
|
||||||
await u.waitUntil(() => !view.model.get('omemo_supported'));
|
await u.waitUntil(() => !view.model.get('omemo_supported'));
|
||||||
|
|
||||||
expect(view.el.querySelector('.chat-error').textContent).toBe(
|
expect(view.el.querySelector('.chat-error').textContent.trim()).toBe(
|
||||||
"oldguy doesn't appear to have a client that supports OMEMO. "+
|
"oldguy doesn't appear to have a client that supports OMEMO. "+
|
||||||
"Encrypted chat will no longer be possible in this grouchat."
|
"Encrypted chat will no longer be possible in this grouchat."
|
||||||
);
|
);
|
||||||
|
@ -15,6 +15,7 @@ import tpl_file_progress from "templates/file_progress.html";
|
|||||||
import tpl_info from "templates/info.html";
|
import tpl_info from "templates/info.html";
|
||||||
import tpl_message from "templates/message.html";
|
import tpl_message from "templates/message.html";
|
||||||
import tpl_message_versions_modal from "templates/message_versions_modal.html";
|
import tpl_message_versions_modal from "templates/message_versions_modal.html";
|
||||||
|
import tpl_spinner from "templates/spinner.html";
|
||||||
import u from "@converse/headless/utils/emoji";
|
import u from "@converse/headless/utils/emoji";
|
||||||
import xss from "xss/dist/xss";
|
import xss from "xss/dist/xss";
|
||||||
|
|
||||||
@ -80,7 +81,8 @@ converse.plugins.add('converse-message-view', {
|
|||||||
|
|
||||||
_converse.MessageView = _converse.ViewWithAvatar.extend({
|
_converse.MessageView = _converse.ViewWithAvatar.extend({
|
||||||
events: {
|
events: {
|
||||||
'click .chat-msg__edit-modal': 'showMessageVersionsModal'
|
'click .chat-msg__edit-modal': 'showMessageVersionsModal',
|
||||||
|
'click .retry': 'onRetryClicked'
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize () {
|
initialize () {
|
||||||
@ -164,6 +166,16 @@ converse.plugins.add('converse-message-view', {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async onRetryClicked () {
|
||||||
|
this.showSpinner();
|
||||||
|
await this.model.error.retry();
|
||||||
|
this.model.destroy();
|
||||||
|
},
|
||||||
|
|
||||||
|
showSpinner () {
|
||||||
|
this.el.innerHTML = tpl_spinner();
|
||||||
|
},
|
||||||
|
|
||||||
onMessageEdited () {
|
onMessageEdited () {
|
||||||
if (this.model.get('is_archived')) {
|
if (this.model.get('is_archived')) {
|
||||||
return;
|
return;
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
* --------------------
|
* --------------------
|
||||||
* Any of the following components may be removed if they're not needed.
|
* Any of the following components may be removed if they're not needed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import "@converse/headless/headless";
|
import "@converse/headless/headless";
|
||||||
import "converse-autocomplete";
|
import "converse-autocomplete";
|
||||||
import "converse-bookmark-views"; // Views for XEP-0048 Bookmarks
|
import "converse-bookmark-views"; // Views for XEP-0048 Bookmarks
|
||||||
|
@ -90,7 +90,8 @@ converse.plugins.add('converse-chatboxes', {
|
|||||||
defaults () {
|
defaults () {
|
||||||
return {
|
return {
|
||||||
'msgid': _converse.connection.getUniqueId(),
|
'msgid': _converse.connection.getUniqueId(),
|
||||||
'time': (new Date()).toISOString()
|
'time': (new Date()).toISOString(),
|
||||||
|
'ephemeral': false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -134,7 +135,7 @@ converse.plugins.add('converse-chatboxes', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
isEphemeral () {
|
isEphemeral () {
|
||||||
return this.isOnlyChatStateNotification() || this.get('type') === 'error';
|
return this.isOnlyChatStateNotification() || this.get('ephemeral');
|
||||||
},
|
},
|
||||||
|
|
||||||
getDisplayName () {
|
getDisplayName () {
|
||||||
@ -178,7 +179,8 @@ converse.plugins.add('converse-chatboxes', {
|
|||||||
_converse.log(e, Strophe.LogLevel.ERROR);
|
_converse.log(e, Strophe.LogLevel.ERROR);
|
||||||
return this.save({
|
return this.save({
|
||||||
'type': 'error',
|
'type': 'error',
|
||||||
'message': __("Sorry, could not determine upload URL.")
|
'message': __("Sorry, could not determine upload URL."),
|
||||||
|
'ephemeral': true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const slot = stanza.querySelector('slot');
|
const slot = stanza.querySelector('slot');
|
||||||
@ -190,7 +192,8 @@ converse.plugins.add('converse-chatboxes', {
|
|||||||
} else {
|
} else {
|
||||||
return this.save({
|
return this.save({
|
||||||
'type': 'error',
|
'type': 'error',
|
||||||
'message': __("Sorry, could not determine file upload URL.")
|
'message': __("Sorry, could not determine file upload URL."),
|
||||||
|
'ephemeral': true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -228,7 +231,8 @@ converse.plugins.add('converse-chatboxes', {
|
|||||||
this.save({
|
this.save({
|
||||||
'type': 'error',
|
'type': 'error',
|
||||||
'upload': _converse.FAILURE,
|
'upload': _converse.FAILURE,
|
||||||
'message': message
|
'message': message,
|
||||||
|
'ephemeral': true
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
xhr.open('PUT', this.get('put'), true);
|
xhr.open('PUT', this.get('put'), true);
|
||||||
@ -401,6 +405,13 @@ converse.plugins.add('converse-chatboxes', {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
createMessageFromError (error) {
|
||||||
|
if (error instanceof _converse.TimeoutError) {
|
||||||
|
const msg = this.messages.create({'type': 'error', 'message': error.message, 'retry': true});
|
||||||
|
msg.error = error;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
getOldestMessage () {
|
getOldestMessage () {
|
||||||
for (let i=0; i<this.messages.length; i++) {
|
for (let i=0; i<this.messages.length; i++) {
|
||||||
const message = this.messages.at(i);
|
const message = this.messages.at(i);
|
||||||
@ -798,7 +809,8 @@ converse.plugins.add('converse-chatboxes', {
|
|||||||
if (!item) {
|
if (!item) {
|
||||||
this.messages.create({
|
this.messages.create({
|
||||||
'message': __("Sorry, looks like file upload is not supported by your server."),
|
'message': __("Sorry, looks like file upload is not supported by your server."),
|
||||||
'type': 'error'
|
'type': 'error',
|
||||||
|
'ephemeral': true
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -809,7 +821,8 @@ converse.plugins.add('converse-chatboxes', {
|
|||||||
if (!slot_request_url) {
|
if (!slot_request_url) {
|
||||||
this.messages.create({
|
this.messages.create({
|
||||||
'message': __("Sorry, looks like file upload is not supported by your server."),
|
'message': __("Sorry, looks like file upload is not supported by your server."),
|
||||||
'type': 'error'
|
'type': 'error',
|
||||||
|
'ephemeral': true
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -818,7 +831,8 @@ converse.plugins.add('converse-chatboxes', {
|
|||||||
return this.messages.create({
|
return this.messages.create({
|
||||||
'message': __('The size of your file, %1$s, exceeds the maximum allowed by your server, which is %2$s.',
|
'message': __('The size of your file, %1$s, exceeds the maximum allowed by your server, which is %2$s.',
|
||||||
file.name, filesize(max_file_size)),
|
file.name, filesize(max_file_size)),
|
||||||
'type': 'error'
|
'type': 'error',
|
||||||
|
'ephemeral': true
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const message = this.messages.create(
|
const message = this.messages.create(
|
||||||
@ -887,9 +901,12 @@ converse.plugins.add('converse-chatboxes', {
|
|||||||
__('Sorry, an error occurred:') + ' ' + error.innerHTML;
|
__('Sorry, an error occurred:') + ' ' + error.innerHTML;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a message stanza, return the text contained in its body.
|
||||||
|
* @private
|
||||||
|
* @param { XMLElement } stanza
|
||||||
|
*/
|
||||||
getMessageBody (stanza) {
|
getMessageBody (stanza) {
|
||||||
/* Given a message stanza, return the text contained in its body.
|
|
||||||
*/
|
|
||||||
const type = stanza.getAttribute('type');
|
const type = stanza.getAttribute('type');
|
||||||
if (type === 'error') {
|
if (type === 'error') {
|
||||||
return this.getErrorMessage(stanza);
|
return this.getErrorMessage(stanza);
|
||||||
|
@ -117,6 +117,14 @@ _converse.Collection = Backbone.Collection.extend({
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom error for indicating timeouts
|
||||||
|
* @namespace _converse
|
||||||
|
*/
|
||||||
|
class TimeoutError extends Error {}
|
||||||
|
_converse.TimeoutError = TimeoutError;
|
||||||
|
|
||||||
|
|
||||||
// Make converse pluggable
|
// Make converse pluggable
|
||||||
pluggable.enable(_converse, '_converse', 'pluggable');
|
pluggable.enable(_converse, '_converse', 'pluggable');
|
||||||
|
|
||||||
|
@ -128,6 +128,11 @@ converse.plugins.add('converse-mam', {
|
|||||||
const result = await _converse.api.archive.query(query);
|
const result = await _converse.api.archive.query(query);
|
||||||
result.messages.forEach(message_handler);
|
result.messages.forEach(message_handler);
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
result.error.retry = () => this.fetchArchivedMessages(options, page);
|
||||||
|
this.createMessageFromError(result.error);
|
||||||
|
}
|
||||||
|
|
||||||
if (page && result.rsm) {
|
if (page && result.rsm) {
|
||||||
if (page === 'forwards') {
|
if (page === 'forwards') {
|
||||||
options = result.rsm.next(_converse.archived_messages_page_size, options.before);
|
options = result.rsm.next(_converse.archived_messages_page_size, options.before);
|
||||||
@ -298,9 +303,9 @@ converse.plugins.add('converse-mam', {
|
|||||||
* * `index`
|
* * `index`
|
||||||
* * `count`
|
* * `count`
|
||||||
* @throws {Error} An error is thrown if the XMPP server responds with an error.
|
* @throws {Error} An error is thrown if the XMPP server responds with an error.
|
||||||
* @returns {Promise<Object>} A promise which resolves to an object which
|
* @returns { (Promise<Object> | _converse.TimeoutError) } A promise which resolves
|
||||||
* will have keys `messages` and `rsm` which contains a _converse.RSM object
|
* to an object which will have keys `messages` and `rsm` which contains a _converse.RSM
|
||||||
* on which "next" or "previous" can be called before passing it in again
|
* object on which "next" or "previous" can be called before passing it in again
|
||||||
* to this method, to get the next or previous page in the result set.
|
* to this method, to get the next or previous page in the result set.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
@ -506,17 +511,22 @@ converse.plugins.add('converse-mam', {
|
|||||||
return true;
|
return true;
|
||||||
}, Strophe.NS.MAM);
|
}, Strophe.NS.MAM);
|
||||||
|
|
||||||
let iq_result, rsm;
|
let error;
|
||||||
try {
|
const iq_result = await _converse.api.sendIQ(stanza, _converse.message_archiving_timeout, false)
|
||||||
iq_result = await _converse.api.sendIQ(stanza, _converse.message_archiving_timeout)
|
if (iq_result === null) {
|
||||||
} catch (e) {
|
const err_msg = "Timeout while trying to fetch archived messages.";
|
||||||
_converse.log(
|
_converse.log(err_msg, Strophe.LogLevel.ERROR);
|
||||||
"Error or timeout while trying to fetch "+
|
error = new _converse.TimeoutError(err_msg);
|
||||||
"archived messages", Strophe.LogLevel.ERROR);
|
return { messages, error };
|
||||||
_converse.log(e, Strophe.LogLevel.ERROR);
|
|
||||||
|
} else if (u.isErrorStanza(iq_result)) {
|
||||||
|
_converse.log("Error stanza received while trying to fetch archived messages", Strophe.LogLevel.ERROR);
|
||||||
|
_converse.log(iq_result, Strophe.LogLevel.ERROR);
|
||||||
|
return { messages };
|
||||||
}
|
}
|
||||||
_converse.connection.deleteHandler(message_handler);
|
_converse.connection.deleteHandler(message_handler);
|
||||||
|
|
||||||
|
let rsm;
|
||||||
const fin = iq_result && sizzle(`fin[xmlns="${Strophe.NS.MAM}"]`, iq_result).pop();
|
const fin = iq_result && sizzle(`fin[xmlns="${Strophe.NS.MAM}"]`, iq_result).pop();
|
||||||
if (fin && [null, 'false'].includes(fin.getAttribute('complete'))) {
|
if (fin && [null, 'false'].includes(fin.getAttribute('complete'))) {
|
||||||
const set = sizzle(`set[xmlns="${Strophe.NS.RSM}"]`, fin).pop();
|
const set = sizzle(`set[xmlns="${Strophe.NS.RSM}"]`, fin).pop();
|
||||||
@ -525,7 +535,7 @@ converse.plugins.add('converse-mam', {
|
|||||||
Object.assign(rsm, Object.assign(pick(options, [...MAM_ATTRIBUTES, ..._converse.RSM_ATTRIBUTES]), rsm));
|
Object.assign(rsm, Object.assign(pick(options, [...MAM_ATTRIBUTES, ..._converse.RSM_ATTRIBUTES]), rsm));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { messages, rsm }
|
return { messages, rsm, error };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1550,7 +1550,8 @@ converse.plugins.add('converse-muc', {
|
|||||||
} else {
|
} else {
|
||||||
const attrs = {
|
const attrs = {
|
||||||
'type': 'error',
|
'type': 'error',
|
||||||
'message': text
|
'message': text,
|
||||||
|
'ephemeral': true
|
||||||
}
|
}
|
||||||
this.messages.create(attrs);
|
this.messages.create(attrs);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
{[ if (o.render_message) { ]}
|
<div class="message chat-info {{{o.extra_classes}}}" data-isodate="{{{o.isodate}}}" {[ if (o.data_name) { ]} data-{{{o.data_name}}}="{{{o.data_value}}}"{[ } ]}>
|
||||||
<!-- XXX: Should only ever be rendered if the message text has been sanitized already -->
|
{[ if (o.render_message) {
|
||||||
<div class="message chat-info {{{o.extra_classes}}}"
|
// XXX: Should only ever be rendered if the message text has been sanitized already
|
||||||
data-isodate="{{{o.isodate}}}" {[ if (o.data_name) { ]} data-{{{o.data_name}}}="{{{o.data_value}}}"{[ } ]}>{{o.message}}</div>
|
]}
|
||||||
|
{{o.message}}
|
||||||
{[ } else { ]}
|
{[ } else { ]}
|
||||||
<div class="message chat-info {{{o.extra_classes}}}"
|
{{{o.message}}}
|
||||||
data-isodate="{{{o.isodate}}}" {[ if (o.data_name) { ]} data-{{{o.data_name}}}="{{{o.data_value}}}"{[ } ]}>{{{o.message}}}</div>
|
|
||||||
{[ } ]}
|
{[ } ]}
|
||||||
|
{[ if (o.retry) { ]}
|
||||||
|
<a class="retry">Retry</a>
|
||||||
|
{[ } ]}
|
||||||
|
</div>
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
<meta name="description" content="Converse XMPP Chat" />
|
<meta name="description" content="Converse XMPP Chat" />
|
||||||
<link rel="shortcut icon" type="image/png" href="../node_modules/jasmine-core/images/jasmine_favicon.png">
|
<link rel="shortcut icon" type="image/png" href="../node_modules/jasmine-core/images/jasmine_favicon.png">
|
||||||
<link rel="stylesheet" type="text/css" media="screen" href="../node_modules/jasmine-core/lib/jasmine-core/jasmine.css">
|
<link rel="stylesheet" type="text/css" media="screen" href="../node_modules/jasmine-core/lib/jasmine-core/jasmine.css">
|
||||||
<link type="text/css" rel="stylesheet" media="screen" href="../dist/website.css" />
|
|
||||||
<link type="text/css" rel="stylesheet" media="screen" href="../dist/converse.css" />
|
<link type="text/css" rel="stylesheet" media="screen" href="../dist/converse.css" />
|
||||||
<script src="../dist/converse.js"></script>
|
<script src="../dist/converse.js"></script>
|
||||||
<script data-main="runner" src="../node_modules/requirejs/require.js"></script>
|
<script data-main="runner" src="../node_modules/requirejs/require.js"></script>
|
||||||
|
Loading…
Reference in New Issue
Block a user