Commit 8db1f3e3 authored by JC Brand's avatar JC Brand

MAM: refactor to functions instead of extending chats with methods

parent 4349b016
......@@ -17,109 +17,101 @@ const { NS } = Strophe;
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 {
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
});
Object.assign(_converse.ChatBox.prototype, MAMEnabledChat);
_converse.onMAMError = function (iq) {
if (iq?.querySelectorAll('feature-not-implemented').length) {
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') ||
!room.features.get('mam_enabled') ||
room.get('prejoin_mam_fetched')) {
!muc.features.get('mam_enabled') ||
muc.get('prejoin_mam_fetched')) {
return;
}
room.fetchNewestMessages();
room.save({'prejoin_mam_fetched': true});
fetchNewestMessages(muc);
muc.save({'prejoin_mam_fetched': true});
}
/************************ BEGIN Event Handlers ************************/
......@@ -216,13 +205,13 @@ converse.plugins.add('converse-mam', {
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 => {
// XXX: For MUCs, we listen to enteredNewRoom instead
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).
// With MUCs we can listen for `enteredNewRoom`.
if (chat.get('type') === _converse.PRIVATE_CHAT_TYPE && !_converse.connection.restored) {
chat.fetchNewestMessages();
fetchNewestMessages(chat);
}
});
/************************ END Event Handlers **************************/
......
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