|
@@ -17,109 +17,101 @@ const { NS } = Strophe;
|
|
const u = converse.env.utils;
|
|
const u = converse.env.utils;
|
|
|
|
|
|
/**
|
|
/**
|
|
- * The MUC utils object. Contains utility functions related to multi-user chat.
|
|
|
|
- * @mixin MAMEnabledChat
|
|
|
|
|
|
+ * Fetches messages that might have been archived *after*
|
|
|
|
+ * the last archived message in our local cache.
|
|
*/
|
|
*/
|
|
-const MAMEnabledChat = {
|
|
|
|
- /**
|
|
|
|
- * Fetches messages that might have been archived *after*
|
|
|
|
- * the last archived message in our local cache.
|
|
|
|
- * @private
|
|
|
|
- */
|
|
|
|
- fetchNewestMessages () {
|
|
|
|
- if (this.disable_mam) {
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- const most_recent_msg = this.getMostRecentMessage();
|
|
|
|
- // if clear_messages_on_reconnection is true, than any recent messages
|
|
|
|
- // must have been received *after* connection and we instead must query
|
|
|
|
- // for earlier messages
|
|
|
|
- if (most_recent_msg && !api.settings.get('clear_messages_on_reconnection')) {
|
|
|
|
- const stanza_id = most_recent_msg.get(`stanza_id ${this.get('jid')}`);
|
|
|
|
- if (stanza_id) {
|
|
|
|
- this.fetchArchivedMessages({'after': stanza_id}, 'forwards');
|
|
|
|
- } else {
|
|
|
|
- this.fetchArchivedMessages({'start': most_recent_msg.get('time')}, 'forwards');
|
|
|
|
- }
|
|
|
|
|
|
+function fetchNewestMessages (model) {
|
|
|
|
+ if (model.disable_mam) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ const most_recent_msg = model.getMostRecentMessage();
|
|
|
|
+ // if clear_messages_on_reconnection is true, than any recent messages
|
|
|
|
+ // must have been received *after* connection and we instead must query
|
|
|
|
+ // for earlier messages
|
|
|
|
+ if (most_recent_msg && !api.settings.get('clear_messages_on_reconnection')) {
|
|
|
|
+ const stanza_id = most_recent_msg.get(`stanza_id ${model.get('jid')}`);
|
|
|
|
+ if (stanza_id) {
|
|
|
|
+ fetchArchivedMessages(model, {'after': stanza_id}, 'forwards');
|
|
} else {
|
|
} else {
|
|
- this.fetchArchivedMessages({'before': ''});
|
|
|
|
|
|
+ fetchArchivedMessages(model, {'start': most_recent_msg.get('time')}, 'forwards');
|
|
}
|
|
}
|
|
- },
|
|
|
|
-
|
|
|
|
- async handleMAMResult (result, query, options, page_direction) {
|
|
|
|
- await api.emojis.initialize();
|
|
|
|
- const is_muc = this.get('type') === _converse.CHATROOMS_TYPE;
|
|
|
|
- result.messages = result.messages.map(
|
|
|
|
- s => (is_muc ? parseMUCMessage(s, this, _converse) : parseMessage(s, _converse))
|
|
|
|
- );
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Synchronous event which allows listeners to first do some
|
|
|
|
- * work based on the MAM result before calling the handlers here.
|
|
|
|
- * @event _converse#MAMResult
|
|
|
|
- */
|
|
|
|
- const data = { query, 'chatbox': this, 'messages': result.messages };
|
|
|
|
- await api.trigger('MAMResult', data, {'synchronous': true});
|
|
|
|
-
|
|
|
|
- result.messages.forEach(m => this.queueMessage(m));
|
|
|
|
- if (result.error) {
|
|
|
|
- const event_id = result.error.retry_event_id = u.getUniqueId();
|
|
|
|
- api.listen.once(event_id, () => this.fetchArchivedMessages(options, page_direction));
|
|
|
|
- this.createMessageFromError(result.error);
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
|
|
+ } else {
|
|
|
|
+ fetchArchivedMessages(model, {'before': ''});
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+async function handleMAMResult (model, result, query, options, page_direction) {
|
|
|
|
+ await api.emojis.initialize();
|
|
|
|
+ const is_muc = model.get('type') === _converse.CHATROOMS_TYPE;
|
|
|
|
+ result.messages = result.messages.map(
|
|
|
|
+ s => (is_muc ? parseMUCMessage(s, model, _converse) : parseMessage(s, _converse))
|
|
|
|
+ );
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Fetch XEP-0313 archived messages based on the passed in criteria.
|
|
|
|
- * @private
|
|
|
|
- * @param { Object } options
|
|
|
|
- * @param { integer } [options.max] - The maximum number of items to return.
|
|
|
|
- * Defaults to "archived_messages_page_size"
|
|
|
|
- * @param { string } [options.after] - The XEP-0359 stanza ID of a message
|
|
|
|
- * after which messages should be returned. Implies forward paging.
|
|
|
|
- * @param { string } [options.before] - The XEP-0359 stanza ID of a message
|
|
|
|
- * before which messages should be returned. Implies backward paging.
|
|
|
|
- * @param { string } [options.end] - A date string in ISO-8601 format,
|
|
|
|
- * before which messages should be returned. Implies backward paging.
|
|
|
|
- * @param { string } [options.start] - A date string in ISO-8601 format,
|
|
|
|
- * after which messages should be returned. Implies forward paging.
|
|
|
|
- * @param { string } [options.with] - The JID of the entity with
|
|
|
|
- * which messages were exchanged.
|
|
|
|
- * @param { boolean } [options.groupchat] - True if archive in groupchat.
|
|
|
|
- * @param { ('forwards'|'backwards')} [page_direction] - Determines whether this function should
|
|
|
|
- * recursively page through the entire result set if a limited number of results were returned.
|
|
|
|
|
|
+ * Synchronous event which allows listeners to first do some
|
|
|
|
+ * work based on the MAM result before calling the handlers here.
|
|
|
|
+ * @event _converse#MAMResult
|
|
*/
|
|
*/
|
|
- async fetchArchivedMessages (options={}, page_direction) {
|
|
|
|
- if (this.disable_mam) {
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- const is_muc = this.get('type') === _converse.CHATROOMS_TYPE;
|
|
|
|
- const mam_jid = is_muc ? this.get('jid') : _converse.bare_jid;
|
|
|
|
- if (!(await api.disco.supports(NS.MAM, mam_jid))) {
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- const max = api.settings.get('archived_messages_page_size')
|
|
|
|
- const query = Object.assign({
|
|
|
|
- 'groupchat': is_muc,
|
|
|
|
- 'max': max,
|
|
|
|
- 'with': this.get('jid'),
|
|
|
|
- }, options);
|
|
|
|
-
|
|
|
|
- const result = await api.archive.query(query);
|
|
|
|
- await this.handleMAMResult(result, query, options, page_direction);
|
|
|
|
-
|
|
|
|
- if (page_direction && result.rsm && !result.complete) {
|
|
|
|
- if (page_direction === 'forwards') {
|
|
|
|
- options = result.rsm.next(max, options.before).query;
|
|
|
|
- } else if (page_direction === 'backwards') {
|
|
|
|
- options = result.rsm.previous(max, options.after).query;
|
|
|
|
- }
|
|
|
|
- return this.fetchArchivedMessages(options, page_direction);
|
|
|
|
- } else {
|
|
|
|
- // TODO: Add a special kind of message which will
|
|
|
|
- // render as a link to fetch further messages, either
|
|
|
|
- // to fetch older messages or to fill in a gap.
|
|
|
|
|
|
+ const data = { query, 'chatbox': model, 'messages': result.messages };
|
|
|
|
+ await api.trigger('MAMResult', data, {'synchronous': true});
|
|
|
|
+
|
|
|
|
+ result.messages.forEach(m => model.queueMessage(m));
|
|
|
|
+ if (result.error) {
|
|
|
|
+ const event_id = result.error.retry_event_id = u.getUniqueId();
|
|
|
|
+ api.listen.once(event_id, () => fetchArchivedMessages(model, options, page_direction));
|
|
|
|
+ model.createMessageFromError(result.error);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Fetch XEP-0313 archived messages based on the passed in criteria.
|
|
|
|
+ * @param { Object } options
|
|
|
|
+ * @param { integer } [options.max] - The maximum number of items to return.
|
|
|
|
+ * Defaults to "archived_messages_page_size"
|
|
|
|
+ * @param { string } [options.after] - The XEP-0359 stanza ID of a message
|
|
|
|
+ * after which messages should be returned. Implies forward paging.
|
|
|
|
+ * @param { string } [options.before] - The XEP-0359 stanza ID of a message
|
|
|
|
+ * before which messages should be returned. Implies backward paging.
|
|
|
|
+ * @param { string } [options.end] - A date string in ISO-8601 format,
|
|
|
|
+ * before which messages should be returned. Implies backward paging.
|
|
|
|
+ * @param { string } [options.start] - A date string in ISO-8601 format,
|
|
|
|
+ * after which messages should be returned. Implies forward paging.
|
|
|
|
+ * @param { string } [options.with] - The JID of the entity with
|
|
|
|
+ * which messages were exchanged.
|
|
|
|
+ * @param { boolean } [options.groupchat] - True if archive in groupchat.
|
|
|
|
+ * @param { ('forwards'|'backwards')} [page_direction] - Determines whether this function should
|
|
|
|
+ * recursively page through the entire result set if a limited number of results were returned.
|
|
|
|
+ */
|
|
|
|
+async function fetchArchivedMessages (model, options={}, page_direction) {
|
|
|
|
+ if (model.disable_mam) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ const is_muc = model.get('type') === _converse.CHATROOMS_TYPE;
|
|
|
|
+ const mam_jid = is_muc ? model.get('jid') : _converse.bare_jid;
|
|
|
|
+ if (!(await api.disco.supports(NS.MAM, mam_jid))) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ const max = api.settings.get('archived_messages_page_size')
|
|
|
|
+ const query = Object.assign({
|
|
|
|
+ 'groupchat': is_muc,
|
|
|
|
+ 'max': max,
|
|
|
|
+ 'with': model.get('jid'),
|
|
|
|
+ }, options);
|
|
|
|
+
|
|
|
|
+ const result = await api.archive.query(query);
|
|
|
|
+ await handleMAMResult(model, result, query, options, page_direction);
|
|
|
|
+
|
|
|
|
+ if (page_direction && result.rsm && !result.complete) {
|
|
|
|
+ if (page_direction === 'forwards') {
|
|
|
|
+ options = result.rsm.next(max, options.before).query;
|
|
|
|
+ } else if (page_direction === 'backwards') {
|
|
|
|
+ options = result.rsm.previous(max, options.after).query;
|
|
}
|
|
}
|
|
|
|
+ return fetchArchivedMessages(model, options, page_direction);
|
|
|
|
+ } else {
|
|
|
|
+ // TODO: Add a special kind of message which will
|
|
|
|
+ // render as a link to fetch further messages, either
|
|
|
|
+ // to fetch older messages or to fill in a gap.
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -139,9 +131,6 @@ converse.plugins.add('converse-mam', {
|
|
message_archiving_timeout: 20000, // Time (in milliseconds) to wait before aborting MAM request
|
|
message_archiving_timeout: 20000, // Time (in milliseconds) to wait before aborting MAM request
|
|
});
|
|
});
|
|
|
|
|
|
- Object.assign(_converse.ChatBox.prototype, MAMEnabledChat);
|
|
|
|
-
|
|
|
|
-
|
|
|
|
_converse.onMAMError = function (iq) {
|
|
_converse.onMAMError = function (iq) {
|
|
if (iq?.querySelectorAll('feature-not-implemented').length) {
|
|
if (iq?.querySelectorAll('feature-not-implemented').length) {
|
|
log.warn(`Message Archive Management (XEP-0313) not supported by ${iq.getAttribute('from')}`);
|
|
log.warn(`Message Archive Management (XEP-0313) not supported by ${iq.getAttribute('from')}`);
|
|
@@ -195,14 +184,14 @@ converse.plugins.add('converse-mam', {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- function preMUCJoinMAMFetch (room) {
|
|
|
|
|
|
+ function preMUCJoinMAMFetch (muc) {
|
|
if (!api.settings.get('muc_show_logs_before_join') ||
|
|
if (!api.settings.get('muc_show_logs_before_join') ||
|
|
- !room.features.get('mam_enabled') ||
|
|
|
|
- room.get('prejoin_mam_fetched')) {
|
|
|
|
|
|
+ !muc.features.get('mam_enabled') ||
|
|
|
|
+ muc.get('prejoin_mam_fetched')) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- room.fetchNewestMessages();
|
|
|
|
- room.save({'prejoin_mam_fetched': true});
|
|
|
|
|
|
+ fetchNewestMessages(muc);
|
|
|
|
+ muc.save({'prejoin_mam_fetched': true});
|
|
}
|
|
}
|
|
|
|
|
|
/************************ BEGIN Event Handlers ************************/
|
|
/************************ BEGIN Event Handlers ************************/
|
|
@@ -216,13 +205,13 @@ converse.plugins.add('converse-mam', {
|
|
view.model.features.on('change:mam_enabled', () => preMUCJoinMAMFetch(view.model));
|
|
view.model.features.on('change:mam_enabled', () => preMUCJoinMAMFetch(view.model));
|
|
}
|
|
}
|
|
});
|
|
});
|
|
- api.listen.on('enteredNewRoom', room => room.features.get('mam_enabled') && room.fetchNewestMessages());
|
|
|
|
|
|
+ api.listen.on('enteredNewRoom', muc => muc.features.get('mam_enabled') && fetchNewestMessages(muc));
|
|
|
|
|
|
|
|
|
|
api.listen.on('chatReconnected', chat => {
|
|
api.listen.on('chatReconnected', chat => {
|
|
// XXX: For MUCs, we listen to enteredNewRoom instead
|
|
// XXX: For MUCs, we listen to enteredNewRoom instead
|
|
if (chat.get('type') === _converse.PRIVATE_CHAT_TYPE) {
|
|
if (chat.get('type') === _converse.PRIVATE_CHAT_TYPE) {
|
|
- chat.fetchNewestMessages();
|
|
|
|
|
|
+ fetchNewestMessages(chat);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
|
|
@@ -233,7 +222,7 @@ converse.plugins.add('converse-mam', {
|
|
// sent during the reload).
|
|
// sent during the reload).
|
|
// With MUCs we can listen for `enteredNewRoom`.
|
|
// With MUCs we can listen for `enteredNewRoom`.
|
|
if (chat.get('type') === _converse.PRIVATE_CHAT_TYPE && !_converse.connection.restored) {
|
|
if (chat.get('type') === _converse.PRIVATE_CHAT_TYPE && !_converse.connection.restored) {
|
|
- chat.fetchNewestMessages();
|
|
|
|
|
|
+ fetchNewestMessages(chat);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
/************************ END Event Handlers **************************/
|
|
/************************ END Event Handlers **************************/
|