Avoid race-condition that destroys vcards
VCards were being created before `fetch` was completed, so once fetch was done those VCards were unset from their collection. Add a new event and promise `VCardsInitialized` that triggers after successful fetching and wait for it before creating VCards.
This commit is contained in:
parent
1fa203c990
commit
17dfa3d7ba
@ -722,10 +722,8 @@
|
|||||||
var view = _converse.chatboxviews.get(sender_jid);
|
var view = _converse.chatboxviews.get(sender_jid);
|
||||||
expect(view).toBeDefined();
|
expect(view).toBeDefined();
|
||||||
|
|
||||||
await u.waitUntil(() => view.model.vcard.get('fullname') === mock.cur_names[1])
|
const event = await u.waitUntil(() => view.el.querySelector('.chat-state-notification'));
|
||||||
// Check that the notification appears inside the chatbox in the DOM
|
expect(event.textContent).toEqual(mock.cur_names[1] + ' is typing');
|
||||||
let events = view.el.querySelectorAll('.chat-state-notification');
|
|
||||||
expect(events[0].textContent).toEqual(mock.cur_names[1] + ' is typing');
|
|
||||||
|
|
||||||
// Check that it doesn't appear twice
|
// Check that it doesn't appear twice
|
||||||
msg = $msg({
|
msg = $msg({
|
||||||
@ -735,7 +733,7 @@
|
|||||||
id: (new Date()).getTime()
|
id: (new Date()).getTime()
|
||||||
}).c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
|
}).c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree();
|
||||||
await _converse.chatboxes.onMessage(msg);
|
await _converse.chatboxes.onMessage(msg);
|
||||||
events = view.el.querySelectorAll('.chat-state-notification');
|
const events = view.el.querySelectorAll('.chat-state-notification');
|
||||||
expect(events.length).toBe(1);
|
expect(events.length).toBe(1);
|
||||||
expect(events[0].textContent).toEqual(mock.cur_names[1] + ' is typing');
|
expect(events[0].textContent).toEqual(mock.cur_names[1] + ' is typing');
|
||||||
done();
|
done();
|
||||||
@ -778,7 +776,8 @@
|
|||||||
expect(msg_obj.get('sender')).toEqual('me');
|
expect(msg_obj.get('sender')).toEqual('me');
|
||||||
expect(msg_obj.get('is_delayed')).toEqual(false);
|
expect(msg_obj.get('is_delayed')).toEqual(false);
|
||||||
const chat_content = chatboxview.el.querySelector('.chat-content');
|
const chat_content = chatboxview.el.querySelector('.chat-content');
|
||||||
const status_text = chat_content.querySelector('.chat-info.chat-state-notification').textContent;
|
const el = await u.waitUntil(() => chat_content.querySelector('.chat-info.chat-state-notification'));
|
||||||
|
const status_text = el.textContent;
|
||||||
expect(status_text).toBe('Typing from another device');
|
expect(status_text).toBe('Typing from another device');
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
@ -863,7 +862,7 @@
|
|||||||
await _converse.chatboxes.onMessage(msg);
|
await _converse.chatboxes.onMessage(msg);
|
||||||
expect(_converse.api.trigger).toHaveBeenCalledWith('message', jasmine.any(Object));
|
expect(_converse.api.trigger).toHaveBeenCalledWith('message', jasmine.any(Object));
|
||||||
await u.waitUntil(() => view.model.vcard.get('fullname') === mock.cur_names[1])
|
await u.waitUntil(() => view.model.vcard.get('fullname') === mock.cur_names[1])
|
||||||
var event = view.el.querySelector('.chat-info.chat-state-notification');
|
const event = await u.waitUntil(() => view.el.querySelector('.chat-state-notification'));
|
||||||
expect(event.textContent).toEqual(mock.cur_names[1] + ' has stopped typing');
|
expect(event.textContent).toEqual(mock.cur_names[1] + ' has stopped typing');
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
@ -904,9 +903,8 @@
|
|||||||
const msg_obj = chatbox.messages.models[0];
|
const msg_obj = chatbox.messages.models[0];
|
||||||
expect(msg_obj.get('sender')).toEqual('me');
|
expect(msg_obj.get('sender')).toEqual('me');
|
||||||
expect(msg_obj.get('is_delayed')).toEqual(false);
|
expect(msg_obj.get('is_delayed')).toEqual(false);
|
||||||
const chat_content = chatboxview.el.querySelector('.chat-content');
|
const el = await u.waitUntil(() => chatboxview.el.querySelector('.chat-info.chat-state-notification'));
|
||||||
const status_text = chat_content.querySelector('.chat-info.chat-state-notification').textContent;
|
expect(el.textContent).toBe('Stopped typing on the other device');
|
||||||
expect(status_text).toBe('Stopped typing on the other device');
|
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
@ -1045,7 +1043,7 @@
|
|||||||
.c('composing', {'xmlns': Strophe.NS.CHATSTATES}).up()
|
.c('composing', {'xmlns': Strophe.NS.CHATSTATES}).up()
|
||||||
.tree();
|
.tree();
|
||||||
await _converse.chatboxes.onMessage(msg);
|
await _converse.chatboxes.onMessage(msg);
|
||||||
await u.waitUntil(() => view.model.messages.length);
|
await u.waitUntil(() => view.el.querySelector('.chat-state-notification'));
|
||||||
expect(view.el.querySelectorAll('.chat-state-notification').length).toBe(1);
|
expect(view.el.querySelectorAll('.chat-state-notification').length).toBe(1);
|
||||||
msg = $msg({
|
msg = $msg({
|
||||||
from: sender_jid,
|
from: sender_jid,
|
||||||
@ -1056,7 +1054,7 @@
|
|||||||
await _converse.chatboxes.onMessage(msg);
|
await _converse.chatboxes.onMessage(msg);
|
||||||
await u.waitUntil(() => (view.model.messages.length > 1));
|
await u.waitUntil(() => (view.model.messages.length > 1));
|
||||||
expect(_converse.api.trigger).toHaveBeenCalledWith('message', jasmine.any(Object));
|
expect(_converse.api.trigger).toHaveBeenCalledWith('message', jasmine.any(Object));
|
||||||
expect(view.el.querySelectorAll('.chat-state-notification').length).toBe(0);
|
await u.waitUntil(() => view.el.querySelectorAll('.chat-state-notification').length === 0);
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
@ -1084,7 +1082,7 @@
|
|||||||
expect(_converse.api.trigger).toHaveBeenCalledWith('message', jasmine.any(Object));
|
expect(_converse.api.trigger).toHaveBeenCalledWith('message', jasmine.any(Object));
|
||||||
const view = _converse.chatboxviews.get(sender_jid);
|
const view = _converse.chatboxviews.get(sender_jid);
|
||||||
await u.waitUntil(() => view.model.vcard.get('fullname') === mock.cur_names[1]);
|
await u.waitUntil(() => view.model.vcard.get('fullname') === mock.cur_names[1]);
|
||||||
const event = view.el.querySelector('.chat-state-notification');
|
const event = await u.waitUntil(() => view.el.querySelector('.chat-state-notification'));
|
||||||
expect(event.textContent).toEqual(mock.cur_names[1] + ' has gone away');
|
expect(event.textContent).toEqual(mock.cur_names[1] + ' has gone away');
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
|
@ -165,7 +165,7 @@
|
|||||||
// A contact should now have been created
|
// A contact should now have been created
|
||||||
expect(_converse.roster.get('contact@example.org') instanceof _converse.RosterContact).toBeTruthy();
|
expect(_converse.roster.get('contact@example.org') instanceof _converse.RosterContact).toBeTruthy();
|
||||||
expect(contact.get('jid')).toBe('contact@example.org');
|
expect(contact.get('jid')).toBe('contact@example.org');
|
||||||
expect(_converse.api.vcard.get).toHaveBeenCalled();
|
await u.waitUntil(() => contact.initialized);
|
||||||
|
|
||||||
/* To subscribe to the contact's presence information,
|
/* To subscribe to the contact's presence information,
|
||||||
* the user's client MUST send a presence stanza of
|
* the user's client MUST send a presence stanza of
|
||||||
|
@ -601,7 +601,7 @@
|
|||||||
|
|
||||||
it("do not have a header if there aren't any",
|
it("do not have a header if there aren't any",
|
||||||
mock.initConverse(
|
mock.initConverse(
|
||||||
['rosterGroupsFetched'], {},
|
['rosterGroupsFetched', 'VCardsInitialized'], {},
|
||||||
async function (done, _converse) {
|
async function (done, _converse) {
|
||||||
|
|
||||||
await test_utils.openControlBox(_converse);
|
await test_utils.openControlBox(_converse);
|
||||||
@ -613,16 +613,15 @@
|
|||||||
ask: 'subscribe',
|
ask: 'subscribe',
|
||||||
fullname: name
|
fullname: name
|
||||||
});
|
});
|
||||||
spyOn(window, 'confirm').and.returnValue(true);
|
|
||||||
await u.waitUntil(() => {
|
await u.waitUntil(() => {
|
||||||
const el = _converse.rosterview.get('Pending contacts').el;
|
const el = _converse.rosterview.get('Pending contacts').el;
|
||||||
return u.isVisible(el) && _.filter(el.querySelectorAll('li'), li => u.isVisible(li)).length;
|
return u.isVisible(el) && _.filter(el.querySelectorAll('li'), li => u.isVisible(li)).length;
|
||||||
}, 700)
|
}, 700)
|
||||||
|
|
||||||
spyOn(_converse.connection, 'sendIQ').and.callThrough();
|
const remove_el = await u.waitUntil(() => sizzle(`.remove-xmpp-contact[title="Click to remove ${name} as a contact"]`, _converse.rosterview.el).pop());
|
||||||
sizzle(`.remove-xmpp-contact[title="Click to remove ${name} as a contact"]`, _converse.rosterview.el).pop().click();
|
spyOn(window, 'confirm').and.returnValue(true);
|
||||||
|
remove_el.click();
|
||||||
expect(window.confirm).toHaveBeenCalled();
|
expect(window.confirm).toHaveBeenCalled();
|
||||||
expect(_converse.connection.sendIQ).toHaveBeenCalled();
|
|
||||||
|
|
||||||
const iq = _converse.connection.IQ_stanzas.pop();
|
const iq = _converse.connection.IQ_stanzas.pop();
|
||||||
expect(Strophe.serialize(iq)).toBe(
|
expect(Strophe.serialize(iq)).toBe(
|
||||||
@ -739,7 +738,7 @@
|
|||||||
ask: null,
|
ask: null,
|
||||||
fullname: name
|
fullname: name
|
||||||
});
|
});
|
||||||
return u.waitUntil(() => contact.vcard.get('fullname'));
|
return u.waitUntil(() => contact.initialized);
|
||||||
}));
|
}));
|
||||||
await u.waitUntil(() => sizzle('li', _converse.rosterview.el).length, 600);
|
await u.waitUntil(() => sizzle('li', _converse.rosterview.el).length, 600);
|
||||||
// Check that they are sorted alphabetically
|
// Check that they are sorted alphabetically
|
||||||
@ -1041,7 +1040,7 @@
|
|||||||
requesting: true,
|
requesting: true,
|
||||||
nickname: name
|
nickname: name
|
||||||
});
|
});
|
||||||
return u.waitUntil(() => contact.vcard.get('fullname'));
|
return u.waitUntil(() => contact.initialized);
|
||||||
}));
|
}));
|
||||||
await u.waitUntil(() => _converse.rosterview.get('Contact requests').el.querySelectorAll('li').length, 700);
|
await u.waitUntil(() => _converse.rosterview.get('Contact requests').el.querySelectorAll('li').length, 700);
|
||||||
expect(_converse.rosterview.update).toHaveBeenCalled();
|
expect(_converse.rosterview.update).toHaveBeenCalled();
|
||||||
|
@ -701,6 +701,7 @@ converse.plugins.add('converse-chatview', {
|
|||||||
* @param { _converse.Message } message - The message object
|
* @param { _converse.Message } message - The message object
|
||||||
*/
|
*/
|
||||||
async showMessage (message) {
|
async showMessage (message) {
|
||||||
|
await message.initialized;
|
||||||
const view = this.add(message.get('id'), new _converse.MessageView({'model': message}));
|
const view = this.add(message.get('id'), new _converse.MessageView({'model': message}));
|
||||||
await view.render();
|
await view.render();
|
||||||
// Clear chat state notifications
|
// Clear chat state notifications
|
||||||
|
@ -310,7 +310,7 @@ converse.plugins.add('converse-profile', {
|
|||||||
/******************** Event Handlers ********************/
|
/******************** Event Handlers ********************/
|
||||||
|
|
||||||
_converse.api.listen.on('controlBoxPaneInitialized', async view => {
|
_converse.api.listen.on('controlBoxPaneInitialized', async view => {
|
||||||
await _converse.api.waitUntil('statusInitialized');
|
await _converse.api.waitUntil('VCardsInitialized');
|
||||||
_converse.xmppstatusview = new _converse.XMPPStatusView({'model': _converse.xmppstatus});
|
_converse.xmppstatusview = new _converse.XMPPStatusView({'model': _converse.xmppstatus});
|
||||||
view.el.insertAdjacentElement('afterBegin', _converse.xmppstatusview.render().el);
|
view.el.insertAdjacentElement('afterBegin', _converse.xmppstatusview.render().el);
|
||||||
});
|
});
|
||||||
|
@ -336,7 +336,8 @@ converse.plugins.add('converse-rosterview', {
|
|||||||
"click .remove-xmpp-contact": "removeContact"
|
"click .remove-xmpp-contact": "removeContact"
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize () {
|
async initialize () {
|
||||||
|
await this.model.initialized;
|
||||||
this.listenTo(this.model, "change", this.render);
|
this.listenTo(this.model, "change", this.render);
|
||||||
this.listenTo(this.model, "highlight", this.highlight);
|
this.listenTo(this.model, "highlight", this.highlight);
|
||||||
this.listenTo(this.model, "destroy", this.remove);
|
this.listenTo(this.model, "destroy", this.remove);
|
||||||
@ -345,6 +346,7 @@ converse.plugins.add('converse-rosterview', {
|
|||||||
|
|
||||||
this.listenTo(this.model.presence, "change:show", this.render);
|
this.listenTo(this.model.presence, "change:show", this.render);
|
||||||
this.listenTo(this.model.vcard, 'change:fullname', this.render);
|
this.listenTo(this.model.vcard, 'change:fullname', this.render);
|
||||||
|
this.render();
|
||||||
},
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
@ -978,7 +980,7 @@ converse.plugins.add('converse-rosterview', {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function initRoster () {
|
function initRosterView () {
|
||||||
/* Create an instance of RosterView once the RosterGroups
|
/* Create an instance of RosterView once the RosterGroups
|
||||||
* collection has been created (in @converse/headless/converse-core.js)
|
* collection has been created (in @converse/headless/converse-core.js)
|
||||||
*/
|
*/
|
||||||
@ -996,8 +998,8 @@ converse.plugins.add('converse-rosterview', {
|
|||||||
*/
|
*/
|
||||||
_converse.api.trigger('rosterViewInitialized');
|
_converse.api.trigger('rosterViewInitialized');
|
||||||
}
|
}
|
||||||
_converse.api.listen.on('rosterInitialized', initRoster);
|
_converse.api.listen.on('rosterInitialized', initRosterView);
|
||||||
_converse.api.listen.on('rosterReadyAfterReconnection', initRoster);
|
_converse.api.listen.on('rosterReadyAfterReconnection', initRosterView);
|
||||||
|
|
||||||
_converse.api.listen.on('afterTearDown', () => {
|
_converse.api.listen.on('afterTearDown', () => {
|
||||||
if (converse.rosterview) {
|
if (converse.rosterview) {
|
||||||
|
@ -123,11 +123,11 @@ converse.plugins.add('converse-chatboxes', {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize () {
|
async initialize () {
|
||||||
|
this.initialized = u.getResolveablePromise();
|
||||||
ModelWithContact.prototype.initialize.apply(this, arguments);
|
ModelWithContact.prototype.initialize.apply(this, arguments);
|
||||||
|
|
||||||
if (this.get('type') === 'chat') {
|
if (this.get('type') === 'chat') {
|
||||||
this.setVCard();
|
|
||||||
this.setRosterContact(Strophe.getBareJidFromJid(this.get('from')));
|
this.setRosterContact(Strophe.getBareJidFromJid(this.get('from')));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,6 +137,8 @@ converse.plugins.add('converse-chatboxes', {
|
|||||||
if (this.isEphemeral()) {
|
if (this.isEphemeral()) {
|
||||||
window.setTimeout(this.safeDestroy.bind(this), 10000);
|
window.setTimeout(this.safeDestroy.bind(this), 10000);
|
||||||
}
|
}
|
||||||
|
await _converse.api.trigger('messageInitialized', this, {'Synchronous': true});
|
||||||
|
this.initialized.resolve();
|
||||||
},
|
},
|
||||||
|
|
||||||
safeDestroy () {
|
safeDestroy () {
|
||||||
@ -147,19 +149,6 @@ converse.plugins.add('converse-chatboxes', {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setVCard () {
|
|
||||||
if (!_converse.vcards) {
|
|
||||||
// VCards aren't supported
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.get('type') === 'error') {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
const jid = Strophe.getBareJidFromJid(this.get('from'));
|
|
||||||
this.vcard = _converse.vcards.findWhere({'jid': jid}) || _converse.vcards.create({'jid': jid});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
isOnlyChatStateNotification () {
|
isOnlyChatStateNotification () {
|
||||||
return u.isOnlyChatStateNotification(this);
|
return u.isOnlyChatStateNotification(this);
|
||||||
},
|
},
|
||||||
|
@ -340,10 +340,10 @@ converse.plugins.add('converse-muc', {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setVCard () {
|
async setVCard () {
|
||||||
|
await _converse.api.waitUntil('VCardsInitialized');
|
||||||
if (!_converse.vcards) {
|
if (!_converse.vcards) {
|
||||||
// VCards aren't supported
|
return; // VCards aren't supported
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (['error', 'info'].includes(this.get('type'))) {
|
if (['error', 'info'].includes(this.get('type'))) {
|
||||||
return;
|
return;
|
||||||
@ -403,10 +403,7 @@ converse.plugins.add('converse-muc', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
async initialize() {
|
async initialize() {
|
||||||
if (_converse.vcards) {
|
this.setVCard();
|
||||||
this.vcard = _converse.vcards.findWhere({'jid': this.get('jid')}) ||
|
|
||||||
_converse.vcards.create({'jid': this.get('jid')});
|
|
||||||
}
|
|
||||||
this.set('box_id', `box-${btoa(this.get('jid'))}`);
|
this.set('box_id', `box-${btoa(this.get('jid'))}`);
|
||||||
|
|
||||||
this.initFeatures(); // sendChatState depends on this.features
|
this.initFeatures(); // sendChatState depends on this.features
|
||||||
@ -421,6 +418,14 @@ converse.plugins.add('converse-muc', {
|
|||||||
this.enterRoom();
|
this.enterRoom();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async setVCard () {
|
||||||
|
await _converse.api.waitUntil('VCardsInitialized');
|
||||||
|
if (_converse.vcards) {
|
||||||
|
this.vcard = _converse.vcards.findWhere({'jid': this.get('jid')}) ||
|
||||||
|
_converse.vcards.create({'jid': this.get('jid')});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
async enterRoom () {
|
async enterRoom () {
|
||||||
const conn_status = this.get('connection_status');
|
const conn_status = this.get('connection_status');
|
||||||
_converse.log(
|
_converse.log(
|
||||||
|
@ -74,39 +74,6 @@ converse.plugins.add('converse-roster', {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the Bakcbone collections that represent the contats
|
|
||||||
* roster and the roster groups.
|
|
||||||
* @private
|
|
||||||
* @method _converse.initRoster
|
|
||||||
*/
|
|
||||||
_converse.initRoster = function () {
|
|
||||||
const storage = _converse.config.get('storage');
|
|
||||||
_converse.roster = new _converse.RosterContacts();
|
|
||||||
let id = `converse.contacts-${_converse.bare_jid}`;
|
|
||||||
_converse.roster.browserStorage = _converse.createStore(id, storage);
|
|
||||||
|
|
||||||
_converse.roster.data = new Backbone.Model();
|
|
||||||
id = `converse-roster-model-${_converse.bare_jid}`;
|
|
||||||
_converse.roster.data.id = id;
|
|
||||||
_converse.roster.data.browserStorage = _converse.createStore(id, storage);
|
|
||||||
_converse.roster.data.fetch();
|
|
||||||
|
|
||||||
id = `converse.roster.groups${_converse.bare_jid}`;
|
|
||||||
_converse.rostergroups = new _converse.RosterGroups();
|
|
||||||
_converse.rostergroups.browserStorage = _converse.createStore(id, storage);
|
|
||||||
/**
|
|
||||||
* Triggered once the `_converse.RosterContacts` and `_converse.RosterGroups` have
|
|
||||||
* been created, but not yet populated with data.
|
|
||||||
* This event is useful when you want to create views for these collections.
|
|
||||||
* @event _converse#chatBoxMaximized
|
|
||||||
* @example _converse.api.listen.on('rosterInitialized', () => { ... });
|
|
||||||
* @example _converse.api.waitUntil('rosterInitialized').then(() => { ... });
|
|
||||||
*/
|
|
||||||
_converse.api.trigger('rosterInitialized');
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
_converse.sendInitialPresence = function () {
|
_converse.sendInitialPresence = function () {
|
||||||
if (_converse.send_initial_presence) {
|
if (_converse.send_initial_presence) {
|
||||||
_converse.xmppstatus.sendPresence();
|
_converse.xmppstatus.sendPresence();
|
||||||
@ -243,6 +210,7 @@ converse.plugins.add('converse-roster', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
async initialize (attributes) {
|
async initialize (attributes) {
|
||||||
|
this.initialized = u.getResolveablePromise();
|
||||||
this.setPresence();
|
this.setPresence();
|
||||||
const { jid } = attributes;
|
const { jid } = attributes;
|
||||||
const bare_jid = Strophe.getBareJidFromJid(jid).toLowerCase();
|
const bare_jid = Strophe.getBareJidFromJid(jid).toLowerCase();
|
||||||
@ -268,6 +236,7 @@ converse.plugins.add('converse-roster', {
|
|||||||
* @param { _converse.RosterContact } contact
|
* @param { _converse.RosterContact } contact
|
||||||
*/
|
*/
|
||||||
await _converse.api.trigger('rosterContactInitialized', this, {'Synchronous': true});
|
await _converse.api.trigger('rosterContactInitialized', this, {'Synchronous': true});
|
||||||
|
this.initialized.resolve();
|
||||||
},
|
},
|
||||||
|
|
||||||
setPresence () {
|
setPresence () {
|
||||||
@ -995,7 +964,36 @@ converse.plugins.add('converse-roster', {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
_converse.api.listen.on('presencesInitialized', (reconnecting) => {
|
async function initRoster () {
|
||||||
|
// Initialize the Bakcbone collections that represent the contats
|
||||||
|
// roster and the roster groups.
|
||||||
|
await _converse.api.waitUntil('VCardsInitialized');
|
||||||
|
const storage = _converse.config.get('storage');
|
||||||
|
_converse.roster = new _converse.RosterContacts();
|
||||||
|
let id = `converse.contacts-${_converse.bare_jid}`;
|
||||||
|
_converse.roster.browserStorage = _converse.createStore(id, storage);
|
||||||
|
|
||||||
|
_converse.roster.data = new Backbone.Model();
|
||||||
|
id = `converse-roster-model-${_converse.bare_jid}`;
|
||||||
|
_converse.roster.data.id = id;
|
||||||
|
_converse.roster.data.browserStorage = _converse.createStore(id, storage);
|
||||||
|
_converse.roster.data.fetch();
|
||||||
|
|
||||||
|
id = `converse.roster.groups${_converse.bare_jid}`;
|
||||||
|
_converse.rostergroups = new _converse.RosterGroups();
|
||||||
|
_converse.rostergroups.browserStorage = _converse.createStore(id, storage);
|
||||||
|
/**
|
||||||
|
* Triggered once the `_converse.RosterContacts` and `_converse.RosterGroups` have
|
||||||
|
* been created, but not yet populated with data.
|
||||||
|
* This event is useful when you want to create views for these collections.
|
||||||
|
* @event _converse#chatBoxMaximized
|
||||||
|
* @example _converse.api.listen.on('rosterInitialized', () => { ... });
|
||||||
|
* @example _converse.api.waitUntil('rosterInitialized').then(() => { ... });
|
||||||
|
*/
|
||||||
|
_converse.api.trigger('rosterInitialized');
|
||||||
|
}
|
||||||
|
|
||||||
|
_converse.api.listen.on('presencesInitialized', async (reconnecting) => {
|
||||||
if (reconnecting) {
|
if (reconnecting) {
|
||||||
/**
|
/**
|
||||||
* Similar to `rosterInitialized`, but instead pertaining to reconnection.
|
* Similar to `rosterInitialized`, but instead pertaining to reconnection.
|
||||||
@ -1006,7 +1004,7 @@ converse.plugins.add('converse-roster', {
|
|||||||
*/
|
*/
|
||||||
_converse.api.trigger('rosterReadyAfterReconnection');
|
_converse.api.trigger('rosterReadyAfterReconnection');
|
||||||
} else {
|
} else {
|
||||||
_converse.initRoster();
|
await initRoster();
|
||||||
}
|
}
|
||||||
_converse.roster.onConnected();
|
_converse.roster.onConnected();
|
||||||
_converse.registerPresenceHandler();
|
_converse.registerPresenceHandler();
|
||||||
|
@ -65,6 +65,8 @@ converse.plugins.add('converse-vcard', {
|
|||||||
*/
|
*/
|
||||||
const { _converse } = this;
|
const { _converse } = this;
|
||||||
|
|
||||||
|
_converse.api.promises.add('VCardsInitialized');
|
||||||
|
|
||||||
|
|
||||||
_converse.VCard = Backbone.Model.extend({
|
_converse.VCard = Backbone.Model.extend({
|
||||||
defaults: {
|
defaults: {
|
||||||
@ -101,7 +103,9 @@ converse.plugins.add('converse-vcard', {
|
|||||||
model: _converse.VCard,
|
model: _converse.VCard,
|
||||||
|
|
||||||
initialize () {
|
initialize () {
|
||||||
this.on('add', vcard => _converse.api.vcard.update(vcard));
|
this.on('add', vcard => {
|
||||||
|
_converse.api.vcard.update(vcard);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -157,26 +161,36 @@ converse.plugins.add('converse-vcard', {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/************************ BEGIN Event Handlers ************************/
|
/************************ BEGIN Event Handlers ************************/
|
||||||
_converse.initVCardCollection = function () {
|
_converse.initVCardCollection = async function () {
|
||||||
_converse.vcards = new _converse.VCards();
|
_converse.vcards = new _converse.VCards();
|
||||||
const id = `${_converse.bare_jid}-converse.vcards`;
|
_converse.vcards.browserStorage = _converse.createStore(`${_converse.bare_jid}-converse.vcards`);
|
||||||
_converse.vcards.browserStorage = _converse.createStore(id, _converse.config.get('storage'));
|
await new Promise(resolve => {
|
||||||
_converse.vcards.fetch();
|
_converse.vcards.fetch({
|
||||||
}
|
'success': resolve,
|
||||||
|
'error': resolve
|
||||||
_converse.api.listen.on('statusInitialized', () => {
|
}, {'silent': true});
|
||||||
_converse.initVCardCollection();
|
});
|
||||||
const vcards = _converse.vcards;
|
const vcards = _converse.vcards;
|
||||||
if (_converse.session) {
|
if (_converse.session) {
|
||||||
const jid = _converse.session.get('bare_jid');
|
const jid = _converse.session.get('bare_jid');
|
||||||
_converse.xmppstatus.vcard = vcards.findWhere({'jid': jid}) || vcards.create({'jid': jid});
|
_converse.xmppstatus.vcard = vcards.findWhere({'jid': jid}) || vcards.create({'jid': jid});
|
||||||
}
|
}
|
||||||
});
|
/**
|
||||||
|
* Triggered as soon as the `_converse.vcards` collection has been initialized and populated from cache.
|
||||||
|
* @event _converse#VCardsInitialized
|
||||||
|
*/
|
||||||
|
_converse.api.trigger('VCardsInitialized');
|
||||||
|
}
|
||||||
|
|
||||||
|
_converse.api.listen.on('statusInitialized', _converse.initVCardCollection);
|
||||||
|
|
||||||
_converse.api.listen.on('clearSession', () => {
|
_converse.api.listen.on('clearSession', () => {
|
||||||
if (_converse.shouldClearCache() && _converse.vcards) {
|
if (_converse.shouldClearCache()) {
|
||||||
_converse.vcards.clearSession();
|
_converse.api.promises.add('VCardsInitialized');
|
||||||
delete _converse.vcards;
|
if (_converse.vcards) {
|
||||||
|
_converse.vcards.clearSession();
|
||||||
|
delete _converse.vcards;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -184,16 +198,24 @@ converse.plugins.add('converse-vcard', {
|
|||||||
_converse.api.listen.on('addClientFeatures', () => _converse.api.disco.own.features.add(Strophe.NS.VCARD));
|
_converse.api.listen.on('addClientFeatures', () => _converse.api.disco.own.features.add(Strophe.NS.VCARD));
|
||||||
|
|
||||||
|
|
||||||
function setVCardOnModel (model) {
|
async function setVCardOnModel (model) {
|
||||||
// TODO: if we can make this method async and wait for the VCard to
|
let jid;
|
||||||
// be updated, then we'll avoid unnecessary re-rendering of roster contacts.
|
if (model instanceof _converse.Message) {
|
||||||
const jid = model.get('jid');
|
if (model.get('type') === 'error') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
jid = model.get('from');
|
||||||
|
} else {
|
||||||
|
jid = model.get('jid');
|
||||||
|
}
|
||||||
|
await _converse.api.waitUntil('VCardsInitialized');
|
||||||
model.vcard = _converse.vcards.findWhere({'jid': jid});
|
model.vcard = _converse.vcards.findWhere({'jid': jid});
|
||||||
if (!model.vcard) {
|
if (!model.vcard) {
|
||||||
model.vcard = _converse.vcards.create({'jid': jid});
|
model.vcard = _converse.vcards.create({'jid': jid});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_converse.api.listen.on('rosterContactInitialized', contact => setVCardOnModel(contact));
|
_converse.api.listen.on('rosterContactInitialized', m => setVCardOnModel(m));
|
||||||
|
_converse.api.listen.on('messageInitialized', m => setVCardOnModel(m));
|
||||||
|
|
||||||
|
|
||||||
/************************ BEGIN API ************************/
|
/************************ BEGIN API ************************/
|
||||||
@ -286,9 +308,9 @@ converse.plugins.add('converse-vcard', {
|
|||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
async update (model, force) {
|
async update (model, force) {
|
||||||
const vcard = await this.get(model, force);
|
const data = await this.get(model, force);
|
||||||
delete vcard['stanza']
|
delete data['stanza']
|
||||||
model.save(vcard);
|
model.save(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user