Remove local contacts not returned from a full roster response
This commit is contained in:
parent
8e1c3e47df
commit
2d5b0753e2
@ -4,6 +4,7 @@
|
||||
|
||||
- GIFs don't render inside unfurls and cause a TypeError
|
||||
- Improve how the `muc_domain` setting is populated via service discovery
|
||||
- Remove local (non-requesting) contacts not returned from a full roster response
|
||||
- #2746: Always reply to all iqs, even those not understood
|
||||
- #2868: Selected emoji is inserted into all open chat boxes
|
||||
|
||||
|
@ -67,7 +67,7 @@ const RosterContacts = Collection.extend({
|
||||
'add': true,
|
||||
'silent': true,
|
||||
'success': resolve,
|
||||
'error': (c, e) => reject(e)
|
||||
'error': (_, e) => reject(e)
|
||||
});
|
||||
});
|
||||
if (u.isErrorObject(result)) {
|
||||
@ -262,11 +262,19 @@ const RosterContacts = Collection.extend({
|
||||
if (this.rosterVersioningSupported()) {
|
||||
stanza.attrs({'ver': this.data.get('version')});
|
||||
}
|
||||
|
||||
const iq = await api.sendIQ(stanza, null, false);
|
||||
if (iq.getAttribute('type') !== 'error') {
|
||||
|
||||
if (iq.getAttribute('type') === 'result') {
|
||||
const query = sizzle(`query[xmlns="${Strophe.NS.ROSTER}"]`, iq).pop();
|
||||
if (query) {
|
||||
const items = sizzle(`item`, query);
|
||||
if (!this.data.get('version')) {
|
||||
// We're getting the full roster, so remove all cached
|
||||
// contacts that aren't included in it.
|
||||
const jids = items.map(item => item.getAttribute('jid'));
|
||||
this.models.forEach(m => !m.get('requesting') && !jids.includes(m.get('jid')) && m.destroy());
|
||||
}
|
||||
items.forEach(item => this.updateContact(item));
|
||||
this.data.save('version', query.getAttribute('ver'));
|
||||
}
|
||||
@ -276,6 +284,7 @@ const RosterContacts = Collection.extend({
|
||||
log.error("Error while trying to fetch roster from the server");
|
||||
return;
|
||||
}
|
||||
|
||||
_converse.session.save('roster_cached', true);
|
||||
/**
|
||||
* When the roster has been received from the XMPP server.
|
||||
@ -348,7 +357,6 @@ const RosterContacts = Collection.extend({
|
||||
api.trigger('contactRequest', this.create(user_data));
|
||||
},
|
||||
|
||||
|
||||
handleIncomingSubscription (presence) {
|
||||
const jid = presence.getAttribute('from'),
|
||||
bare_jid = Strophe.getBareJidFromJid(jid),
|
||||
|
@ -132,6 +132,59 @@ describe("The Contacts Roster", function () {
|
||||
expect(_converse.roster.at(0).get('jid')).toBe('nurse@example.com');
|
||||
}));
|
||||
|
||||
it("can be refreshed", mock.initConverse(
|
||||
[], {}, async function (_converse) {
|
||||
|
||||
const sent_IQs = _converse.connection.IQ_stanzas;
|
||||
let stanza = await u.waitUntil(() => sent_IQs.filter(iq => iq.querySelector('iq query[xmlns="jabber:iq:roster"]')).pop());
|
||||
_converse.connection._dataRecv(mock.createRequest($iq({
|
||||
to: _converse.connection.jid,
|
||||
type: 'result',
|
||||
id: stanza.getAttribute('id')
|
||||
}).c('query', {
|
||||
xmlns: 'jabber:iq:roster',
|
||||
}).c('item', {
|
||||
jid: 'juliet@example.net',
|
||||
name: 'Juliet',
|
||||
subscription:'both'
|
||||
}).c('group').t('Friends').up().up()
|
||||
.c('item', {
|
||||
jid: 'mercutio@example.net',
|
||||
name: 'Mercutio',
|
||||
subscription:'from'
|
||||
}).c('group').t('Friends')));
|
||||
|
||||
while (sent_IQs.length) sent_IQs.pop();
|
||||
|
||||
await u.waitUntil(() => _converse.roster.length === 2);
|
||||
expect(_converse.roster.pluck('jid')).toEqual(['juliet@example.net', 'mercutio@example.net']);
|
||||
|
||||
const rosterview = document.querySelector('converse-roster');
|
||||
const sync_button = rosterview.querySelector('.sync-contacts');
|
||||
sync_button.click();
|
||||
|
||||
stanza = await u.waitUntil(() => sent_IQs.filter(iq => iq.querySelector('iq query[xmlns="jabber:iq:roster"]')).pop());
|
||||
_converse.connection._dataRecv(mock.createRequest($iq({
|
||||
to: _converse.connection.jid,
|
||||
type: 'result',
|
||||
id: stanza.getAttribute('id')
|
||||
}).c('query', {
|
||||
xmlns: 'jabber:iq:roster',
|
||||
}).c('item', {
|
||||
jid: 'juliet@example.net',
|
||||
name: 'Juliet',
|
||||
subscription:'both'
|
||||
}).c('group').t('Friends').up().up()
|
||||
.c('item', {
|
||||
jid: 'lord.capulet@example.net',
|
||||
name: 'Lord Capulet',
|
||||
subscription:'from'
|
||||
}).c('group').t('Acquaintences')));
|
||||
|
||||
await u.waitUntil(() => _converse.roster.pluck('jid').includes('lord.capulet@example.net'));
|
||||
expect(_converse.roster.pluck('jid')).toEqual(['juliet@example.net', 'lord.capulet@example.net']);
|
||||
}));
|
||||
|
||||
it("will also show contacts added afterwards", mock.initConverse([], {}, async function (_converse) {
|
||||
await mock.openControlBox(_converse);
|
||||
await mock.waitForRoster(_converse, 'current');
|
||||
@ -1175,6 +1228,7 @@ describe("The Contacts Roster", function () {
|
||||
|
||||
const pres = $pres({from: 'data@enterprise/resource', type: 'subscribe'});
|
||||
_converse.connection._dataRecv(mock.createRequest(pres));
|
||||
|
||||
expect(_converse.roster.pluck('jid').length).toBe(1);
|
||||
const rosterview = document.querySelector('converse-roster');
|
||||
await u.waitUntil(() => sizzle('a:contains("Contact requests")', rosterview).length, 700);
|
||||
|
Loading…
Reference in New Issue
Block a user