xmpp.chapril.org-conversejs/src/converse-uniview.js
JC Brand 1fa203c990 Support for IndexedDB. updates #1105
Depend on latest backbone.browserStorage which has support for IndexedDB
via localforage.

Storage operations are now asynchronous and transactional.

Bugs fixed (mostly by waiting for operations to complete):

* Rooms are now fetched asynchronously, so wait before triggering `show`
  or when closing.
* Make sure chat create/update transactions complete before firing events
* Make sure chats and messages have been fetched before creating new ones.
* When doing a `fetch` with `wait: false` on a collection and then
  creating a model in that collection, then once the read
  operation finishes (after creating the model), the collection is emptied again.
* Patch and wait when saving.
  Otherwise we have previously set attributes overriding later ones.
* Make sure api.roomviews.close returns a promise

Test fixes:

* Chats are now asynchronously returned, so we need to use `await`
* Wait for the storage transaction to complete when creating and updating messages
* Wait for all chatboxes to close
    Otherwise we get sessionStorage inconsistencies due to the async nature of localforage.
* Wait for room views to close in spec/chatroom.js

In the process, remove the `closeAllChatBoxes` override in
converse-controlbox by letting the `close` method decide whether it
should be closed or not.
2019-10-30 13:02:23 +01:00

114 lines
3.9 KiB
JavaScript

// Converse.js
// http://conversejs.org
//
// Copyright (c) 2013-2018, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
/**
* @module converse-uniview
* @description
* A plugin which ensures that only one chat (private or groupchat) is
* visible at any one time. All other ongoing chats are hidden and kept in the
* background.
*
* This plugin makes sense in mobile, embedded or fullscreen chat environments
* (as configured by the `view_mode` setting).
*/
import "converse-chatview";
import converse from "@converse/headless/converse-core";
const u = converse.env.utils;
function hideChat (view) {
if (view.model.get('id') === 'controlbox') { return; }
u.safeSave(view.model, {'hidden': true});
view.hide();
}
function visibleChats (_converse) {
return _converse.chatboxes
.filter(cb => (cb.get('id') !== 'controlbox' && !cb.get('hidden'))).length > 0;
}
converse.plugins.add('converse-uniview', {
// It's possible however to make optional dependencies non-optional.
// If the setting "strict_plugin_dependencies" is set to true,
// an error will be raised if the plugin is not found.
dependencies: ['converse-chatboxes', 'converse-muc-views', 'converse-controlbox', 'converse-rosterview'],
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.
ChatBoxes: {
createChatBox (jid, attrs) {
/* Make sure new chat boxes are hidden by default. */
const { _converse } = this.__super__;
if (_converse.isUniView()) {
attrs = attrs || {};
attrs.hidden = true;
}
return this.__super__.createChatBox.call(this, jid, attrs);
}
},
ChatBox: {
maybeShow () {
const { _converse } = this.__super__;
if (_converse.isUniView() && (!this.get('hidden') || !visibleChats(_converse))) {
return this.trigger("show");
} else {
return this.__super__.maybeShow.apply(this, arguments);
}
}
},
ChatBoxView: {
shouldShowOnTextMessage () {
const { _converse } = this.__super__;
if (_converse.isUniView()) {
return false;
} else {
return this.__super__.shouldShowOnTextMessage.apply(this, arguments);
}
}
}
},
initialize () {
/* The initialize function gets called as soon as the plugin is
* loaded by converse.js's plugin machinery.
*/
const { _converse } = this;
/************************ BEGIN Event Handlers ************************/
_converse.api.listen.on('beforeShowingChatView', (view) => {
/* We only have one chat visible at any one
* time. So before opening a chat, we make sure all other
* chats are hidden.
*/
if (_converse.isUniView()) {
Object.values(_converse.chatboxviews.xget(view.model.get('id')))
.filter(v => !v.model.get('hidden'))
.forEach(hideChat);
if (view.model.get('hidden')) {
return new Promise(resolve => {
u.safeSave(
view.model,
{'hidden': false}, {
'success': resolve,
'failure': resolve
}
);
});
}
}
});
/************************ END Event Handlers ************************/
}
});