189 lines
7.3 KiB
JavaScript
189 lines
7.3 KiB
JavaScript
// Converse.js (A browser based XMPP chat client)
|
|
// https://conversejs.org
|
|
//
|
|
// Copyright (c) 2012-2019, Jan-Carel Brand <jc@opkode.com>
|
|
// Licensed under the Mozilla Public License (MPLv2)
|
|
//
|
|
// Views for XEP-0313 Message Archive Management
|
|
|
|
import converse from "@converse/headless/converse-core";
|
|
|
|
|
|
const CHATROOMS_TYPE = 'chatroom';
|
|
const { Strophe, _ } = converse.env;
|
|
const u = converse.env.utils;
|
|
|
|
|
|
converse.plugins.add('converse-mam-views', {
|
|
|
|
dependencies: ['converse-disco', 'converse-mam', 'converse-chatview', 'converse-muc-views'],
|
|
|
|
overrides: {
|
|
// Overrides mentioned here will be picked up by converse.js's
|
|
// plugin architecture they will replace existing methods on the
|
|
// relevant objects or classes.
|
|
//
|
|
// New functions which don't exist yet can also be added.
|
|
|
|
ChatBoxView: {
|
|
|
|
render () {
|
|
const result = this.__super__.render.apply(this, arguments);
|
|
if (!this.disable_mam) {
|
|
this.content.addEventListener('scroll', _.debounce(this.onScroll.bind(this), 100));
|
|
}
|
|
return result;
|
|
},
|
|
|
|
fetchNewestMessages () {
|
|
/* Fetches messages that might have been archived *after*
|
|
* the last archived message in our local cache.
|
|
*/
|
|
if (this.disable_mam) { return; }
|
|
const { _converse } = this.__super__,
|
|
most_recent_msg = u.getMostRecentMessage(this.model);
|
|
|
|
if (_.isNil(most_recent_msg)) {
|
|
this.fetchArchivedMessages();
|
|
} else {
|
|
const stanza_id = most_recent_msg.get(`stanza_id ${this.model.get('jid')}`);
|
|
if (stanza_id) {
|
|
this.fetchArchivedMessages({'after': stanza_id});
|
|
} else {
|
|
this.fetchArchivedMessages({'start': most_recent_msg.get('time')});
|
|
}
|
|
}
|
|
},
|
|
|
|
fetchArchivedMessagesIfNecessary () {
|
|
/* Check if archived messages should be fetched, and if so, do so. */
|
|
if (this.disable_mam || this.model.get('mam_initialized')) {
|
|
return;
|
|
}
|
|
const { _converse } = this.__super__;
|
|
_converse.api.disco.supports(Strophe.NS.MAM, _converse.bare_jid).then(
|
|
(result) => { // Success
|
|
if (result.length) {
|
|
this.fetchArchivedMessages();
|
|
}
|
|
this.model.save({'mam_initialized': true});
|
|
},
|
|
() => { // Error
|
|
_converse.log(
|
|
"Error or timeout while checking for MAM support",
|
|
Strophe.LogLevel.ERROR
|
|
);
|
|
}
|
|
).catch((msg) => {
|
|
this.clearSpinner();
|
|
_converse.log(msg, Strophe.LogLevel.FATAL);
|
|
});
|
|
},
|
|
|
|
async fetchArchivedMessages (options) {
|
|
const { _converse } = this.__super__;
|
|
if (this.disable_mam) { return; }
|
|
|
|
const is_groupchat = this.model.get('type') === CHATROOMS_TYPE;
|
|
|
|
let mam_jid, message_handler;
|
|
if (is_groupchat) {
|
|
mam_jid = this.model.get('jid');
|
|
message_handler = this.model.onMessage.bind(this.model);
|
|
} else {
|
|
mam_jid = _converse.bare_jid;
|
|
message_handler = _converse.chatboxes.onMessage.bind(_converse.chatboxes)
|
|
}
|
|
|
|
const supported = await _converse.api.disco.supports(Strophe.NS.MAM, mam_jid);
|
|
if (!supported.length) {
|
|
return;
|
|
}
|
|
this.addSpinner();
|
|
_converse.api.archive.query(
|
|
_.extend({
|
|
'groupchat': is_groupchat,
|
|
'before': '', // Page backwards from the most recent message
|
|
'max': _converse.archived_messages_page_size,
|
|
'with': this.model.get('jid'),
|
|
}, options),
|
|
|
|
messages => { // Success
|
|
this.clearSpinner();
|
|
_.each(messages, message_handler);
|
|
},
|
|
e => { // Error
|
|
this.clearSpinner();
|
|
_converse.log(
|
|
"Error or timeout while trying to fetch "+
|
|
"archived messages", Strophe.LogLevel.ERROR);
|
|
_converse.log(e, Strophe.LogLevel.ERROR);
|
|
}
|
|
);
|
|
},
|
|
|
|
onScroll (ev) {
|
|
const { _converse } = this.__super__;
|
|
if (this.content.scrollTop === 0 && this.model.messages.length) {
|
|
const oldest_message = this.model.messages.at(0);
|
|
const by_jid = this.model.get('jid');
|
|
const stanza_id = oldest_message.get(`stanza_id ${by_jid}`);
|
|
if (stanza_id) {
|
|
this.fetchArchivedMessages({'before': stanza_id});
|
|
} else {
|
|
this.fetchArchivedMessages({
|
|
'end': oldest_message.get('time')
|
|
});
|
|
}
|
|
}
|
|
},
|
|
},
|
|
|
|
ChatRoomView: {
|
|
|
|
initialize () {
|
|
const { _converse } = this.__super__;
|
|
this.__super__.initialize.apply(this, arguments);
|
|
this.model.on('change:mam_enabled', this.fetchArchivedMessagesIfNecessary, this);
|
|
this.model.on('change:connection_status', this.fetchArchivedMessagesIfNecessary, this);
|
|
},
|
|
|
|
renderChatArea () {
|
|
const result = this.__super__.renderChatArea.apply(this, arguments);
|
|
if (!this.disable_mam) {
|
|
this.content.addEventListener('scroll', _.debounce(this.onScroll.bind(this), 100));
|
|
}
|
|
return result;
|
|
},
|
|
|
|
fetchArchivedMessagesIfNecessary () {
|
|
if (this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED ||
|
|
!this.model.get('mam_enabled') ||
|
|
this.model.get('mam_initialized')) {
|
|
|
|
return;
|
|
}
|
|
this.fetchArchivedMessages();
|
|
this.model.save({'mam_initialized': true});
|
|
}
|
|
}
|
|
},
|
|
|
|
initialize () {
|
|
/* The initialize function gets called as soon as the plugin is
|
|
* loaded by Converse.js's plugin machinery.
|
|
*/
|
|
const { _converse } = this;
|
|
|
|
/* Event handlers */
|
|
_converse.api.listen.on('afterMessagesFetched', view => view.fetchNewestMessages());
|
|
|
|
_converse.api.listen.on('reconnected', () => {
|
|
const private_chats = _converse.chatboxviews.filter(
|
|
view => _.at(view, 'model.attributes.type')[0] === 'chatbox'
|
|
);
|
|
_.each(private_chats, (view) => view.fetchNewestMessages())
|
|
});
|
|
}
|
|
});
|