Commit f032af91 authored by JC Brand's avatar JC Brand

Initial work on moving certain settings into a model

parent b02c70b4
......@@ -722,7 +722,7 @@
_converse.root.appendChild(el);
}
}
if (_.includes(['mobile', 'fullscreen'], _converse.view_mode)) {
if (_.includes(['mobile', 'fullscreen'], _converse.settings.get('view_mode'))) {
el.classList.add('fullscreen');
}
el.innerHTML = '';
......@@ -735,7 +735,7 @@
initialize () {
this.model.on("add", this.onChatBoxAdded, this);
this.model.on("destroy", this.removeChat, this);
this.el.classList.add(`converse-${_converse.view_mode}`);
this.el.classList.add(`converse-${_converse.settings.get('view_mode')}`);
this.render();
},
......
......@@ -406,8 +406,8 @@
this.render();
_.forEach(this.el.querySelectorAll('[data-title]'), (el) => {
const popover = new bootstrap.Popover(el, {
'trigger': _converse.view_mode === 'mobile' && 'click' || 'hover',
'dismissible': _converse.view_mode === 'mobile' && true || false,
'trigger': _converse.settings.get('view_mode') === 'mobile' && 'click' || 'hover',
'dismissible': _converse.settings.get('view_mode') === 'mobile' && true || false,
'container': _converse.chatboxviews.el
})
});
......@@ -465,9 +465,10 @@
if (!this.validate()) { return; }
const form_data = new FormData(ev.target);
_converse.trusted = form_data.get('trusted');
_converse.storage = form_data.get('trusted') ? 'local' : 'session';
_converse.settings.save({
'trusted': form_data.get('trusted'),
'storage': form_data.get('trusted') ? 'local' : 'session'
});
let jid = form_data.get('jid');
if (_converse.locked_domain) {
jid = Strophe.escapeNode(jid) + '@' + _converse.locked_domain;
......@@ -578,7 +579,7 @@
});
_converse.on('clearSession', () => {
if (_converse.trusted) {
if (_converse.settings.get('trusted')) {
const chatboxes = _.get(_converse, 'chatboxes', null);
if (!_.isNil(chatboxes)) {
const controlbox = chatboxes.get('controlbox');
......
......@@ -181,12 +181,12 @@
if (level === Strophe.LogLevel.ERROR) {
logger.error(`${prefix} ERROR: ${message}`, style);
} else if (level === Strophe.LogLevel.WARN) {
if (_converse.debug) {
if (_converse.settings.get('debug')) {
logger.warn(`${prefix} ${moment().format()} WARNING: ${message}`, style);
}
} else if (level === Strophe.LogLevel.FATAL) {
logger.error(`${prefix} FATAL: ${message}`, style);
} else if (_converse.debug) {
} else if (_converse.settings.get('debug')) {
if (level === Strophe.LogLevel.DEBUG) {
logger.debug(`${prefix} ${moment().format()} DEBUG: ${message}`, style);
} else {
......@@ -227,6 +227,20 @@
_converse.promises[promise] = u.getResolveablePromise();
}
// Instance level constants
_converse.TIMEOUTS = { // Set as module attr so that we can override in tests.
'PAUSED': 10000,
'INACTIVE': 90000
};
// XEP-0085 Chat states
// http://xmpp.org/extensions/xep-0085.html
_converse.INACTIVE = 'inactive';
_converse.ACTIVE = 'active';
_converse.COMPOSING = 'composing';
_converse.PAUSED = 'paused';
_converse.GONE = 'gone';
_converse.emit = function (name) {
/* Event emitter and promise resolver */
_converse.trigger.apply(this, arguments);
......@@ -236,16 +250,77 @@
}
};
_converse.router = new Backbone.Router();
// Converse has two kinds of settings.
//
// Both kinds of settings can be set when calling converse.initialize.
//
// The core settings (or instance settings), which are set directly on the
// _converse object and which we don't expect to change after
// initialization.
//
// Then there are the app settings, which are stored in the AppSettings
// model. These settings are cached and may be overridden during runtime.
// We now declare the defaults for the instance settings.
_converse.default_settings = {
'authentication': 'login', // Available values are "login", "prebind", "anonymous" and "external".
'auto_login': false, // Currently only used in connection with anonymous login
'auto_reconnect': true,
'blacklisted_plugins': [],
'connection_options': {},
'credentials_url': null, // URL from where login credentials can be fetched
'expose_rid_and_sid': false,
'geouri_regex': /https:\/\/www.openstreetmap.org\/.*#map=[0-9]+\/([\-0-9.]+)\/([\-0-9.]+)\S*/g,
'geouri_replacement': 'https://www.openstreetmap.org/?mlat=$1&mlon=$2#map=18/$1/$2',
'jid': undefined,
'keepalive': true,
'locales_url': 'locale/{{{locale}}}/LC_MESSAGES/converse.json',
'locales': [
'af', 'ar', 'bg', 'ca', 'de', 'es', 'eu', 'en', 'fr', 'he',
'hu', 'id', 'it', 'ja', 'nb', 'nl',
'pl', 'pt_BR', 'ru', 'tr', 'uk', 'zh_CN', 'zh_TW'
],
'message_carbons': true,
'password': undefined,
'prebind_url': null,
'rid': undefined,
'sid': undefined,
'root': window.document,
'storage': 'session',
'strict_plugin_dependencies': false,
'whitelisted_plugins': []
};
_converse.AppSettings = Backbone.Model.extend({
defaults () {
return {
'allow_non_roster_messaging': false,
'animate': true,
'auto_away': 0, // Seconds after which user status is set to 'away'
'auto_xa': 0, // Seconds after which user status is set to 'xa'
'bosh_service_url': undefined,
'csi_waiting_time': 0, // Support for XEP-0352. Seconds before client is considered idle and CSI is sent out.
'debug': false,
'default_state': 'online',
'nickname': undefined, // XXX: looks like this is not being used?
'priority': 0,
'trusted': true,
'view_mode': 'overlayed', // Choices are 'overlayed', 'fullscreen', 'mobile'
'websocket_url': undefined
};
}
});
_converse.initialize = function (settings, callback) {
"use strict";
settings = !_.isUndefined(settings) ? settings : {};
const init_promise = u.getResolveablePromise();
_.each(PROMISES, addPromise);
_converse.router = new Backbone.Router();
if (!_.isUndefined(_converse.connection)) {
// Looks like _converse.initialized was called again without logging
// out or disconnecting in the previous session.
......@@ -276,69 +351,28 @@
unloadevent = 'unload';
}
// Instance level constants
this.TIMEOUTS = { // Set as module attr so that we can override in tests.
'PAUSED': 10000,
'INACTIVE': 90000
};
// Apply default settings
// ----------------------
settings = !_.isUndefined(settings) ? settings : {};
// XEP-0085 Chat states
// http://xmpp.org/extensions/xep-0085.html
this.INACTIVE = 'inactive';
this.ACTIVE = 'active';
this.COMPOSING = 'composing';
this.PAUSED = 'paused';
this.GONE = 'gone';
// Default configuration values
// ----------------------------
this.default_settings = {
allow_non_roster_messaging: false,
animate: true,
authentication: 'login', // Available values are "login", "prebind", "anonymous" and "external".
auto_away: 0, // Seconds after which user status is set to 'away'
auto_login: false, // Currently only used in connection with anonymous login
auto_reconnect: true,
auto_xa: 0, // Seconds after which user status is set to 'xa'
blacklisted_plugins: [],
bosh_service_url: undefined,
connection_options: {},
credentials_url: null, // URL from where login credentials can be fetched
csi_waiting_time: 0, // Support for XEP-0352. Seconds before client is considered idle and CSI is sent out.
debug: false,
default_state: 'online',
expose_rid_and_sid: false,
geouri_regex: /https:\/\/www.openstreetmap.org\/.*#map=[0-9]+\/([\-0-9.]+)\/([\-0-9.]+)\S*/g,
geouri_replacement: 'https://www.openstreetmap.org/?mlat=$1&mlon=$2#map=18/$1/$2',
jid: undefined,
keepalive: true,
locales_url: 'locale/{{{locale}}}/LC_MESSAGES/converse.json',
locales: [
'af', 'ar', 'bg', 'ca', 'de', 'es', 'eu', 'en', 'fr', 'he',
'hu', 'id', 'it', 'ja', 'nb', 'nl',
'pl', 'pt_BR', 'ru', 'tr', 'uk', 'zh_CN', 'zh_TW'
],
message_carbons: true,
nickname: undefined,
password: undefined,
prebind_url: null,
priority: 0,
rid: undefined,
root: window.document,
sid: undefined,
storage: 'session',
strict_plugin_dependencies: false,
trusted: true,
view_mode: 'overlayed', // Choices are 'overlayed', 'fullscreen', 'mobile'
websocket_url: undefined,
whitelisted_plugins: []
};
_.assignIn(this, this.default_settings);
// Allow only whitelisted configuration attributes to be overwritten
_.assignIn(this, _.pick(settings, _.keys(this.default_settings)));
const instance_keys = _.keys(_converse.default_settings);
const instance_settings = _.pick(settings, instance_keys);
_.assignIn(_converse, instance_settings);
// TODO: need to also fetch from browserStorage here, and need to
// figure out how to not overwrite browserStorage with settings passed
// in via converse.initialize
_converse.settings = new _converse.AppSettings();
if (this.authentication === _converse.ANONYMOUS) {
if (this.auto_login && !this.jid) {
const id = b64_sha1(`converse.appsettings-${_converse.bare_jid}`);
_converse.xmppstatus.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
_converse.xmppstatus.fetch();
const app_settings = _.omit(settings, instance_keys);
_converse.settings.save(app_settings);
if (_converse.authentication === _converse.ANONYMOUS) {
if (_converse.auto_login && !_converse.jid) {
throw new Error("Config Error: you need to provide the server's " +
"domain via the 'jid' option when using anonymous " +
"authentication with auto_login.");
......@@ -369,7 +403,6 @@
// Module-level functions
// ----------------------
this.generateResource = () => `/converse.js-${Math.floor(Math.random()*139749528).toString()}`;
this.sendCSI = function (stat) {
......@@ -401,7 +434,7 @@
_converse.auto_changed_status = false;
// XXX: we should really remember the original state here, and
// then set it back to that...
_converse.xmppstatus.set('status', _converse.default_state);
_converse.xmppstatus.set('status', _converse.settings.get('default_state'));
}
};
......@@ -416,18 +449,18 @@
}
const stat = _converse.xmppstatus.get('status');
_converse.idle_seconds++;
if (_converse.csi_waiting_time > 0 &&
_converse.idle_seconds > _converse.csi_waiting_time &&
if (_converse.settings.get('csi_waiting_time') > 0 &&
_converse.idle_seconds > _converse.settings.get('csi_waiting_time') &&
!_converse.inactive) {
_converse.sendCSI(_converse.INACTIVE);
}
if (_converse.auto_away > 0 &&
_converse.idle_seconds > _converse.auto_away &&
if (_converse.settings.get('auto_away') > 0 &&
_converse.idle_seconds > _converse.settings.get('auto_away') &&
stat !== 'away' && stat !== 'xa' && stat !== 'dnd') {
_converse.auto_changed_status = true;
_converse.xmppstatus.set('status', 'away');
} else if (_converse.auto_xa > 0 &&
_converse.idle_seconds > _converse.auto_xa &&
} else if (_converse.settings.get('auto_xa') > 0 &&
_converse.idle_seconds > _converse.settings.get('auto_xa') &&
stat !== 'xa' && stat !== 'dnd') {
_converse.auto_changed_status = true;
_converse.xmppstatus.set('status', 'xa');
......@@ -438,7 +471,9 @@
/* Set an interval of one second and register a handler for it.
* Required for the auto_away, auto_xa and csi_waiting_time features.
*/
if (_converse.auto_away < 1 && _converse.auto_xa < 1 && _converse.csi_waiting_time < 1) {
if (_converse.settings.get('auto_away') < 1 &&
_converse.settings.get('auto_xa') < 1 &&
_converse.settings.get('csi_waiting_time') < 1) {
// Waiting time of less then one second means features aren't used.
return;
}
......@@ -591,8 +626,8 @@
};
this.incrementMsgCounter = function () {
this.msg_counter += 1;
const unreadMsgCount = this.msg_counter;
_converse.msg_counter += 1;
const unreadMsgCount = _converse.msg_counter;
let title = document.title;
if (_.isNil(title)) {
return;
......@@ -643,7 +678,7 @@
};
this.clearSession = function () {
if (!_converse.trusted) {
if (!_converse.settings.get('trusted')) {
window.localStorage.clear();
window.sessionStorage.clear();
} else if (!_.isUndefined(this.session) && this.session.browserStorage) {
......@@ -798,11 +833,10 @@
this.XMPPStatus = Backbone.Model.extend({
defaults () {
return {
"jid": _converse.bare_jid,
"status": _converse.default_state,
"status": _converse.settings.get('default_state'),
}
},
......@@ -827,7 +861,7 @@
constructPresence (type, status_message) {
let presence;
type = _.isString(type) ? type : (this.get('status') || _converse.default_state);
type = _.isString(type) ? type : (this.get('status') || _converse.settings.get('default_state'));
status_message = _.isString(status_message) ? status_message : this.get('status_message');
// Most of these presence types are actually not explicitly sent,
// but I add all of them here for reference and future proofing.
......@@ -864,11 +898,11 @@
Strophe.log = function (level, msg) {
_converse.log(msg, level);
};
if (this.debug) {
this.connection.xmlInput = function (body) {
if (_converse.settings.get('debug')) {
_converse.connection.xmlInput = function (body) {
_converse.log(body.outerHTML, Strophe.LogLevel.DEBUG, 'color: darkgoldenrod');
};
this.connection.xmlOutput = function (body) {
_converse.connection.xmlOutput = function (body) {
_converse.log(body.outerHTML, Strophe.LogLevel.DEBUG, 'color: darkcyan');
};
}
......@@ -983,7 +1017,7 @@
// or credentials fetching via HTTP
this.autoLogin(credentials);
} else if (this.auto_login) {
if (this.credentials_url) {
if (_converse.credentials_url) {
this.fetchLoginCredentials().then(
this.autoLogin.bind(this),
this.autoLogin.bind(this)
......@@ -1010,7 +1044,8 @@
// so we set them on the converse object.
this.jid = credentials.jid;
}
if (this.authentication === _converse.ANONYMOUS || this.authentication === _converse.EXTERNAL) {
if (_converse.authentication === _converse.ANONYMOUS ||
_converse.authentication === _converse.EXTERNAL) {
if (!this.jid) {
throw new Error("Config Error: when using anonymous login " +
"you need to provide the server's domain via the 'jid' option. " +
......@@ -1021,7 +1056,7 @@
this.connection.reset();
}
this.connection.connect(this.jid.toLowerCase(), null, this.onConnectStatusChanged);
} else if (this.authentication === _converse.LOGIN) {
} else if (_converse.authentication === _converse.LOGIN) {
const password = _.isNil(credentials) ? (_converse.connection.pass || this.password) : credentials.password;
if (!password) {
if (this.auto_login) {
......@@ -1048,10 +1083,10 @@
this.logIn = function (credentials, reconnecting) {
// We now try to resume or automatically set up a new session.
// Otherwise the user will be shown a login form.
if (this.authentication === _converse.PREBIND) {
this.attemptPreboundSession(reconnecting);
if (_converse.authentication === _converse.PREBIND) {
_converse.attemptPreboundSession(reconnecting);
} else {
this.attemptNonPreboundSession(credentials, reconnecting);
_converse.attemptNonPreboundSession(credentials, reconnecting);
}
};
......@@ -1059,14 +1094,14 @@
/* Creates a new Strophe.Connection instance if we don't already have one.
*/
if (!this.connection) {
if (!this.bosh_service_url && ! this.websocket_url) {
if (!_converse.settings.get('bosh_service_url') && ! _converse.settings.get('websocket_url')) {
throw new Error("initConnection: you must supply a value for either the bosh_service_url or websocket_url or both.");
}
if (('WebSocket' in window || 'MozWebSocket' in window) && this.websocket_url) {
this.connection = new Strophe.Connection(this.websocket_url, this.connection_options);
} else if (this.bosh_service_url) {
if (('WebSocket' in window || 'MozWebSocket' in window) && _converse.settings.get('websocket_url')) {
this.connection = new Strophe.Connection(_converse.settings.get('websocket_url'), this.connection_options);
} else if (_converse.settings.get('bosh_service_url')) {
this.connection = new Strophe.Connection(
this.bosh_service_url,
_converse.settings.get('bosh_service_url'),
_.assignIn(this.connection_options, {'keepalive': this.keepalive})
);
} else {
......@@ -1106,7 +1141,7 @@
const whitelist = _converse.core_plugins.concat(
_converse.whitelisted_plugins);
if (_converse.view_mode === 'embedded') {
if (_converse.settings.get('view_mode') === 'embedded') {
_.forEach([ // eslint-disable-line lodash/prefer-map
"converse-bookmarks",
"converse-controlbox",
......@@ -1219,23 +1254,8 @@
},
'settings': {
'update' (settings) {
u.merge(_converse.default_settings, settings);
u.merge(_converse, settings);
u.applyUserSettings(_converse, settings, _converse.user_settings);
},
'get' (key) {
if (_.includes(_.keys(_converse.default_settings), key)) {
return _converse[key];
}
},
'set' (key, val) {
const o = {};
if (_.isObject(key)) {
_.assignIn(_converse, _.pick(key, _.keys(_converse.default_settings)));
} else if (_.isString("string")) {
o[key] = val;
_.assignIn(_converse, _.pick(o, _.keys(_converse.default_settings)));
}
const user_settings = _.pick(_converse.user_settings, _.keys(settings));
_converse.settings.save(_.extend(settings, user_settings));
}
},
'promises': {
......
......@@ -41,7 +41,7 @@
dependencies: ["converse-chatview", "converse-headline", "converse-muc-views"],
enabled (_converse) {
return _converse.view_mode == 'overlayed';
return _converse.settings.get('view_mode') == 'overlayed';
},
overrides: {
......
......@@ -13,7 +13,7 @@
converse.plugins.add('converse-embedded', {
enabled (_converse) {
return _converse.view_mode === 'embedded';
return _converse.settings.get('view_mode') === 'embedded';
},
initialize () {
......
......@@ -21,7 +21,7 @@
converse.plugins.add('converse-fullscreen', {
enabled (_converse) {
return _.includes(['fullscreen', 'embedded'], _converse.view_mode);
return _.includes(['fullscreen', 'embedded'], _converse.settings.get('view_mode'));
},
overrides: {
......
......@@ -129,7 +129,7 @@
/* Handler method for all incoming messages of type "headline". */
const from_jid = message.getAttribute('from');
if (utils.isHeadlineMessage(_converse, message)) {
if (_.includes(from_jid, '@') && !_converse.allow_non_roster_messaging) {
if (_.includes(from_jid, '@') && !_converse.settings.get('allow_non_roster_messaging')) {
return;
}
const chatbox = _converse.chatboxes.create({
......
......@@ -221,7 +221,7 @@
processMessageText () {
var text = this.get('message');
text = u.geoUriToHttp(text, _converse.geouri_replacement);
text = u.geoUriToHttp(text, _converse.ggeouri_replacementeouri_replacement);
},
getExtraMessageClasses () {
......
......@@ -42,7 +42,7 @@
dependencies: ["converse-chatview", "converse-controlbox", "converse-muc", "converse-muc-views", "converse-headline"],
enabled (_converse) {
return _converse.view_mode == 'overlayed';
return _converse.settings.get('view_mode') == 'overlayed';
},
overrides: {
......
......@@ -108,14 +108,14 @@
// Refer to docs/source/configuration.rst for explanations of these
// configuration settings.
_converse.api.settings.update({
allow_muc: true,
allow_muc_invitations: true,
auto_join_on_invite: false,
auto_join_rooms: [],
muc_domain: undefined,
muc_history_max_stanzas: undefined,
muc_instant_rooms: true,
muc_nickname_from_jid: false
'allow_muc': true,
'allow_muc_invitations': true,
'auto_join_on_invite': false,
'auto_join_rooms': [],
'muc_domain': undefined,
'muc_history_max_stanzas': undefined,
'muc_instant_rooms': true,
'muc_nickname_from_jid': false
});
_converse.api.promises.add(['roomsAutoJoined']);
......
......@@ -71,7 +71,7 @@
};
_converse.isMessageToHiddenChat = function (message) {
if (_.includes(['mobile', 'fullscreen', 'embedded'], _converse.view_mode)) {
if (_.includes(['mobile', 'fullscreen', 'embedded'], _converse.settings.get('view_mode'))) {
const jid = Strophe.getBareJidFromJid(message.getAttribute('from'));
const model = _converse.chatboxes.get(jid);
if (!_.isNil(model)) {
......@@ -138,7 +138,7 @@
const full_from_jid = message.getAttribute('from'),
from_jid = Strophe.getBareJidFromJid(full_from_jid);
if (message.getAttribute('type') === 'headline') {
if (!_.includes(from_jid, '@') || _converse.allow_non_roster_messaging) {
if (!_.includes(from_jid, '@') || _converse.get('allow_non_roster_messaging')) {
title = __("Notification from %1$s", from_jid);
} else {
return;
......@@ -159,7 +159,7 @@
if (!_.isUndefined(roster_item)) {
title = __("%1$s says", roster_item.getDisplayName());
} else {
if (_converse.allow_non_roster_messaging) {
if (_converse.get('allow_non_roster_messaging')) {
title = __("%1$s says", from_jid);
} else {
return;
......
......@@ -821,7 +821,7 @@
}
this.filter_view.showOrHide();
return this;
}, _converse.animate ? 100 : 0),
}, _converse.get('animate') ? 100 : 0),
filter (query, type) {
// First we make sure the filter is restored to its
......
......@@ -46,7 +46,7 @@
ChatBoxes: {
chatBoxMayBeShown (chatbox) {
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.settings.get('view_mode'))) {
return !chatbox.get('hidden');
} else {
return this.__super__.chatBoxMayBeShown.apply(this, arguments);
......@@ -55,7 +55,7 @@
createChatBox (jid, attrs) {
/* Make sure new chat boxes are hidden by default. */
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.settings.get('view_mode'))) {
attrs = attrs || {};
attrs.hidden = true;
}
......@@ -65,7 +65,7 @@
ChatBoxView: {
shouldShowOnTextMessage () {
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.settings.get('view_mode'))) {
return false;
} else {
return this.__super__.shouldShowOnTextMessage.apply(this, arguments);
......@@ -77,7 +77,7 @@
* time. So before opening a chat, we make sure all other
* chats are hidden.
*/
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.settings.get('view_mode'))) {
_.each(this.__super__._converse.chatboxviews.xget(this.model.get('id')), hideChat);
this.model.set('hidden', false);
}
......@@ -87,7 +87,7 @@
ChatRoomView: {
show (focus) {
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.view_mode)) {
if (_.includes(['mobile', 'fullscreen', 'embedded'], this.__super__._converse.settings.get('view_mode'))) {
_.each(this.__super__._converse.chatboxviews.xget(this.model.get('id')), hideChat);
this.model.set('hidden', false);
}
......
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