Commit 97dade10 authored by JC Brand's avatar JC Brand

Initial work on #1038

parent a15c9e54
This diff is collapsed.
......@@ -87,6 +87,7 @@ require.config({
"converse-otr": "src/converse-otr",
"converse-ping": "src/converse-ping",
"converse-profile": "src/converse-profile",
"converse-pubsub": "src/converse-pubsub",
"converse-register": "src/converse-register",
"converse-roomslist": "src/converse-roomslist",
"converse-rosterview": "src/converse-rosterview",
......
......@@ -27,7 +27,7 @@
tpl_bookmarks_list
) {
const { Backbone, Promise, Strophe, $iq, b64_sha1, sizzle, _ } = converse.env;
const { Backbone, Promise, Strophe, f, $iq, b64_sha1, sizzle, _ } = converse.env;
const u = converse.env.utils;
converse.plugins.add('converse-bookmarks', {
......@@ -257,7 +257,7 @@
initialize () {
this.on('add', _.flow(this.openBookmarkedRoom, this.markRoomAsBookmarked));
this.on('remove', this.markRoomAsUnbookmarked, this);
this.on('remove', this.sendBookmarkStanza, this);
this.on('remove', this.persistBookmarks, this);
const cache_key = `converse.room-bookmarks${_converse.bare_jid}`;
this.fetched_flag = b64_sha1(cache_key+'fetched');
......@@ -300,11 +300,141 @@
},
createBookmark (options) {
_converse.bookmarks.create(options);
_converse.bookmarks.sendBookmarkStanza();
this.create(options);
this.persistBookmarks().catch(() => {
this.findWhere({'jid': options.jid}).destroy();
const model = _converse.chatboxes.get(options.jid);
model.set('bookmarked', false);
});
},
addFormFields (stanza, config) {
_.each(_.keys(config), (key) => {
if (config[key].type === 'hidden') {
stanza.c('field', {'var': key, 'type': 'hidden'});
} else {
stanza.c('field', {'var': key});
}
if (_.isEmpty(config[key].values)) {
stanza.c('value').t('').up().up();
} else {
_.each(config[key].values, (value) => {
stanza.c('value').t(value).up().up();
});
}
});
return stanza;
},
createNode (jid, node, config) {
return _converse.api.disco.supports(Strophe.NS.PUBSUB+'#create-nodes', _converse.bare_jid)
.then((result) => {
return new Promise((resolve, reject) => {
const stanza = $iq({
'type': 'set',
'from': _converse.connection.jid
}).c('pubsub', {'xmlns': Strophe.NS.PUBSUB})
.c('create', {'node': node}).up();
if (config) {
stanza.c('configure').c('x', {'xmlns': Strophe.NS.XFORM, 'type': 'submit'});
this.addFormFields(stanza, config);
}
_converse.connection.sendIQ(stanza, resolve, resolve);
});
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
},
sendBookmarkStanza () {
fetchNodeConfiguration (jid, node) {
return new Promise((resolve, reject) => {
const stanza = $iq({
'type': 'get',
'from': _converse.connection.jid
}).c('pubsub', {'xmlns': Strophe.NS.PUBSUB+'#owner'})
.c('configure', {'node': node});
_converse.connection.sendIQ(stanza, resolve, resolve);
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
},
parseConfiguration (iq) {
const fields = iq.querySelectorAll('field');
const get_key_value = (el) => {
let values = _.map(_.get(el.querySelectorAll('value'), 'textContent'));
if (_.isEmpty(values)) {
// We need an empty `<values></values>` element if no value (and required)
values = [''];
}
return [
el.getAttribute('var'),
{
'values': values,
'required': !_.isNull(el.querySelector('required')),
'type': el.getAttribute('type')
}
];
}
return f.fromPairs(f.map(get_key_value, fields));
},
constructConfigStanza (jid, node, config) {
const stanza = $iq({
'type': 'set',
'from': _converse.connection.jid,
'to': jid
}).c('pubsub', {'xmlns': Strophe.NS.PUBSUB+'#owner'})
.c('configure', {'node': node})
.c('x', {'xmlns': Strophe.NS.XFORM, 'type': 'submit'});
this.addFormFields(stanza, config);
return stanza;
},
configureNode (jid, node, config) {
return new Promise((resolve, reject) => {
_converse.connection.sendIQ(this.constructConfigStanza(jid, node, config), resolve, resolve);
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
},
saveConfiguration (config) {
// FIXME: check what the config settings are before setting them
return this.fetchNodeConfiguration()
.then(this.parseConfiguration)
.then((config) => {
config['pubsub#access_model'] = {'values': ['whitelist']};
config['pubsub#persist_items'] = {'values': ['1']}; // More compatible with older OpenFire than `true`
this.configureNode(undefined, 'storage:bookmarks', config);
})
.catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
},
persistBookmarks () {
return new Promise((resolve, reject) => {
_converse.api.disco.supports(Strophe.NS.PUBSUB+'#publish-options', _converse.bare_jid).then((result) => {
if (result.supported) {
this.sendBookmarkStanza(resolve);
} else {
const config = {
'FORM_TYPE': {'values': ['http://jabber.org/protocol/pubsub#node_config'], 'type': 'hidden'},
'pubsub#access_model': {'values': ['whitelist']},
'pubsub#persist_items': {'values': ['1']} // More compatible with older OpenFire than `true`
}
this.fetchNodeConfiguration(undefined, 'storage:bookmarks').then((iq) => {
if (iq.getAttribute('type') === 'error') {
if (iq.querySelector('error[type="cancel"] item-not-found')) {
this.createNode(undefined, 'storage:bookmarks', config).then(resolve);
} else {
reject(new Error("Error while trying to configure 'storage:bookmarks' PEP node"), iq);
}
} else {
this.saveConfiguration(config).then(this.sendBookmarkStanza.bind(this, resolve));
}
});
}
});
});
},
sendBookmarkStanza (callback) {
let stanza = $iq({
'type': 'set',
'from': _converse.connection.jid,
......@@ -320,8 +450,9 @@
'jid': model.get('jid'),
}).c('nick').t(model.get('nick')).up().up();
});
stanza.up().up().up();
stanza.c('publish-options')
_converse.api.disco.supports(Strophe.NS.PUBSUB+'#publish-options', _converse.bare_jid).then(() => {
stanza.up().up().up().c('publish-options')
.c('x', {'xmlns': Strophe.NS.XFORM, 'type':'submit'})
.c('field', {'var':'FORM_TYPE', 'type':'hidden'})
.c('value').t('http://jabber.org/protocol/pubsub#publish-options').up().up()
......@@ -329,7 +460,8 @@
.c('value').t('true').up().up()
.c('field', {'var':'pubsub#access_model'})
.c('value').t('whitelist');
_converse.connection.sendIQ(stanza, null, this.onBookmarkError.bind(this));
});
_converse.connection.sendIQ(stanza, callback, this.onBookmarkError.bind(this));
},
onBookmarkError (iq) {
......
......@@ -91,6 +91,7 @@
'converse-otr',
'converse-ping',
'converse-profile',
'converse-pubsub',
'converse-register',
'converse-roomslist',
'converse-rosterview',
......@@ -1571,9 +1572,11 @@
};
if (this.debug) {
this.connection.xmlInput = function (body) {
console.log(body);
_converse.log(body.outerHTML, Strophe.LogLevel.DEBUG, 'color: darkgoldenrod');
};
this.connection.xmlOutput = function (body) {
console.log(body);
_converse.log(body.outerHTML, Strophe.LogLevel.DEBUG, 'color: darkcyan');
};
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment