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
|
- GIFs don't render inside unfurls and cause a TypeError
|
||||||
- Improve how the `muc_domain` setting is populated via service discovery
|
- 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
|
- #2746: Always reply to all iqs, even those not understood
|
||||||
- #2868: Selected emoji is inserted into all open chat boxes
|
- #2868: Selected emoji is inserted into all open chat boxes
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ const RosterContacts = Collection.extend({
|
|||||||
'add': true,
|
'add': true,
|
||||||
'silent': true,
|
'silent': true,
|
||||||
'success': resolve,
|
'success': resolve,
|
||||||
'error': (c, e) => reject(e)
|
'error': (_, e) => reject(e)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
if (u.isErrorObject(result)) {
|
if (u.isErrorObject(result)) {
|
||||||
@ -262,11 +262,19 @@ const RosterContacts = Collection.extend({
|
|||||||
if (this.rosterVersioningSupported()) {
|
if (this.rosterVersioningSupported()) {
|
||||||
stanza.attrs({'ver': this.data.get('version')});
|
stanza.attrs({'ver': this.data.get('version')});
|
||||||
}
|
}
|
||||||
|
|
||||||
const iq = await api.sendIQ(stanza, null, false);
|
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();
|
const query = sizzle(`query[xmlns="${Strophe.NS.ROSTER}"]`, iq).pop();
|
||||||
if (query) {
|
if (query) {
|
||||||
const items = sizzle(`item`, 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));
|
items.forEach(item => this.updateContact(item));
|
||||||
this.data.save('version', query.getAttribute('ver'));
|
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");
|
log.error("Error while trying to fetch roster from the server");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_converse.session.save('roster_cached', true);
|
_converse.session.save('roster_cached', true);
|
||||||
/**
|
/**
|
||||||
* When the roster has been received from the XMPP server.
|
* 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));
|
api.trigger('contactRequest', this.create(user_data));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
handleIncomingSubscription (presence) {
|
handleIncomingSubscription (presence) {
|
||||||
const jid = presence.getAttribute('from'),
|
const jid = presence.getAttribute('from'),
|
||||||
bare_jid = Strophe.getBareJidFromJid(jid),
|
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');
|
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) {
|
it("will also show contacts added afterwards", mock.initConverse([], {}, async function (_converse) {
|
||||||
await mock.openControlBox(_converse);
|
await mock.openControlBox(_converse);
|
||||||
await mock.waitForRoster(_converse, 'current');
|
await mock.waitForRoster(_converse, 'current');
|
||||||
@ -1175,6 +1228,7 @@ describe("The Contacts Roster", function () {
|
|||||||
|
|
||||||
const pres = $pres({from: 'data@enterprise/resource', type: 'subscribe'});
|
const pres = $pres({from: 'data@enterprise/resource', type: 'subscribe'});
|
||||||
_converse.connection._dataRecv(mock.createRequest(pres));
|
_converse.connection._dataRecv(mock.createRequest(pres));
|
||||||
|
|
||||||
expect(_converse.roster.pluck('jid').length).toBe(1);
|
expect(_converse.roster.pluck('jid').length).toBe(1);
|
||||||
const rosterview = document.querySelector('converse-roster');
|
const rosterview = document.querySelector('converse-roster');
|
||||||
await u.waitUntil(() => sizzle('a:contains("Contact requests")', rosterview).length, 700);
|
await u.waitUntil(() => sizzle('a:contains("Contact requests")', rosterview).length, 700);
|
||||||
|
Loading…
Reference in New Issue
Block a user