2017-11-17 13:32:03 +01:00
|
|
|
// Converse.js (A browser based XMPP chat client)
|
|
|
|
// http://conversejs.org
|
|
|
|
//
|
|
|
|
// Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
|
|
|
|
// Licensed under the Mozilla Public License (MPLv2)
|
|
|
|
//
|
|
|
|
/*global define */
|
|
|
|
|
|
|
|
(function (root, factory) {
|
2017-11-17 14:14:42 +01:00
|
|
|
define(["converse-core",
|
2018-02-22 18:41:01 +01:00
|
|
|
"bootstrap",
|
2018-05-08 17:48:37 +02:00
|
|
|
"tpl!alert",
|
2018-02-21 12:31:25 +01:00
|
|
|
"tpl!chat_status_modal",
|
2018-02-23 16:32:47 +01:00
|
|
|
"tpl!profile_modal",
|
2018-02-15 15:50:55 +01:00
|
|
|
"tpl!profile_view",
|
2017-11-17 13:32:03 +01:00
|
|
|
"tpl!status_option",
|
2018-02-23 15:45:44 +01:00
|
|
|
"converse-vcard",
|
|
|
|
"converse-modal"
|
2017-11-17 13:32:03 +01:00
|
|
|
], factory);
|
|
|
|
}(this, function (
|
|
|
|
converse,
|
2018-02-21 12:31:25 +01:00
|
|
|
bootstrap,
|
2018-05-08 17:48:37 +02:00
|
|
|
tpl_alert,
|
2018-02-21 12:31:25 +01:00
|
|
|
tpl_chat_status_modal,
|
2018-02-23 16:32:47 +01:00
|
|
|
tpl_profile_modal,
|
2018-02-15 15:50:55 +01:00
|
|
|
tpl_profile_view,
|
2017-11-17 13:32:03 +01:00
|
|
|
tpl_status_option
|
|
|
|
) {
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
const { Strophe, Backbone, Promise, utils, _, moment } = converse.env;
|
2018-02-21 16:10:13 +01:00
|
|
|
const u = converse.env.utils;
|
2017-11-17 13:32:03 +01:00
|
|
|
|
|
|
|
|
|
|
|
converse.plugins.add('converse-profile', {
|
|
|
|
|
2018-05-08 17:48:37 +02:00
|
|
|
dependencies: ["converse-modal", "converse-vcard"],
|
2018-02-23 15:45:44 +01:00
|
|
|
|
2017-11-17 13:32:03 +01:00
|
|
|
initialize () {
|
|
|
|
/* The initialize function gets called as soon as the plugin is
|
|
|
|
* loaded by converse.js's plugin machinery.
|
|
|
|
*/
|
|
|
|
const { _converse } = this,
|
2018-02-21 14:40:41 +01:00
|
|
|
{ __ } = _converse;
|
2017-11-17 13:32:03 +01:00
|
|
|
|
2018-02-15 15:50:55 +01:00
|
|
|
|
2018-02-23 16:32:47 +01:00
|
|
|
_converse.ProfileModal = _converse.BootstrapModal.extend({
|
2018-05-08 17:48:37 +02:00
|
|
|
events: {
|
|
|
|
'click .change-avatar': "openFileSelection",
|
|
|
|
'change input[type="file"': "updateFilePreview",
|
|
|
|
'submit form': 'onFormSubmitted'
|
|
|
|
},
|
|
|
|
|
|
|
|
initialize () {
|
|
|
|
_converse.BootstrapModal.prototype.initialize.apply(this, arguments);
|
|
|
|
this.model.on('change', this.render, this);
|
|
|
|
},
|
2018-02-23 16:32:47 +01:00
|
|
|
|
|
|
|
toHTML () {
|
2018-05-08 19:24:50 +02:00
|
|
|
return tpl_profile_modal(_.extend(
|
|
|
|
this.model.toJSON(),
|
|
|
|
this.model.vcard.toJSON(), {
|
2018-02-23 23:10:46 +01:00
|
|
|
'heading_profile': __('Your Profile'),
|
2018-05-08 17:48:37 +02:00
|
|
|
'label_close': __('Close'),
|
|
|
|
'label_email': __('Email'),
|
|
|
|
'label_fullname': __('Full Name'),
|
|
|
|
'label_nickname': __('Nickname'),
|
|
|
|
'label_jid': __('XMPP Address (JID)'),
|
|
|
|
'label_role': __('Role'),
|
2018-05-08 19:51:56 +02:00
|
|
|
'label_role_help': __('Use commas to separate multiple roles. Your roles are shown next to your name on your chat messages.'),
|
2018-05-08 17:48:37 +02:00
|
|
|
'label_save': __('Save'),
|
|
|
|
'label_url': __('URL'),
|
|
|
|
'alt_avatar': __('Your avatar image')
|
2018-02-23 16:32:47 +01:00
|
|
|
}));
|
|
|
|
},
|
2018-05-08 17:48:37 +02:00
|
|
|
|
|
|
|
openFileSelection (ev) {
|
|
|
|
ev.preventDefault();
|
|
|
|
this.el.querySelector('input[type="file"]').click();
|
|
|
|
},
|
|
|
|
|
|
|
|
updateFilePreview (ev) {
|
|
|
|
const file = ev.target.files[0],
|
|
|
|
reader = new FileReader();
|
|
|
|
reader.onloadend = () => {
|
|
|
|
this.el.querySelector('.avatar').setAttribute('src', reader.result);
|
|
|
|
};
|
|
|
|
reader.readAsDataURL(file);
|
|
|
|
},
|
|
|
|
|
|
|
|
setVCard (body, data) {
|
|
|
|
_converse.api.vcard.set(data)
|
2018-05-09 10:09:42 +02:00
|
|
|
.then(() => _converse.api.vcard.update(this.model.vcard, true))
|
|
|
|
.catch((err) => {
|
2018-05-08 17:48:37 +02:00
|
|
|
_converse.log(err, Strophe.LogLevel.FATAL);
|
2018-05-09 10:09:42 +02:00
|
|
|
_converse.api.alert.show(
|
|
|
|
Strophe.LogLevel.ERROR,
|
|
|
|
__('Error'),
|
|
|
|
[__("Sorry, an error happened while trying to save your profile data."),
|
|
|
|
__("You can check your browser's developer console for any error output.")]
|
|
|
|
)
|
2018-05-08 17:48:37 +02:00
|
|
|
});
|
2018-05-09 10:09:42 +02:00
|
|
|
this.modal.hide();
|
2018-05-08 17:48:37 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
onFormSubmitted (ev) {
|
|
|
|
ev.preventDefault();
|
|
|
|
const reader = new FileReader(),
|
|
|
|
form_data = new FormData(ev.target),
|
|
|
|
body = this.el.querySelector('.modal-body'),
|
|
|
|
image_file = form_data.get('image');
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
'fn': form_data.get('fn'),
|
2018-05-24 10:15:25 +02:00
|
|
|
'nickname': form_data.get('nickname'),
|
2018-05-08 17:48:37 +02:00
|
|
|
'role': form_data.get('role'),
|
|
|
|
'email': form_data.get('email'),
|
|
|
|
'url': form_data.get('url'),
|
|
|
|
};
|
|
|
|
if (!image_file.size) {
|
|
|
|
_.extend(data, {
|
2018-05-15 10:16:52 +02:00
|
|
|
'image': this.model.vcard.get('image'),
|
|
|
|
'image_type': this.model.vcard.get('image_type')
|
2018-05-08 17:48:37 +02:00
|
|
|
});
|
|
|
|
this.setVCard(body, data);
|
|
|
|
} else {
|
|
|
|
reader.onloadend = () => {
|
|
|
|
_.extend(data, {
|
|
|
|
'image': btoa(reader.result),
|
|
|
|
'image_type': image_file.type
|
|
|
|
});
|
|
|
|
this.setVCard(body, data);
|
|
|
|
};
|
|
|
|
reader.readAsBinaryString(image_file);
|
|
|
|
}
|
|
|
|
}
|
2018-02-23 16:32:47 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
|
2018-02-23 15:45:44 +01:00
|
|
|
_converse.ChatStatusModal = _converse.BootstrapModal.extend({
|
2018-02-21 14:40:41 +01:00
|
|
|
events: {
|
2018-02-21 16:10:13 +01:00
|
|
|
"submit form#set-xmpp-status": "onFormSubmitted",
|
|
|
|
"click .clear-input": "clearStatusMessage"
|
2018-02-21 14:40:41 +01:00
|
|
|
},
|
2018-02-21 12:31:25 +01:00
|
|
|
|
|
|
|
toHTML () {
|
2018-05-08 19:24:50 +02:00
|
|
|
return tpl_chat_status_modal(
|
|
|
|
_.extend(
|
|
|
|
this.model.toJSON(),
|
|
|
|
this.model.vcard.toJSON(), {
|
|
|
|
'label_away': __('Away'),
|
|
|
|
'label_close': __('Close'),
|
|
|
|
'label_busy': __('Busy'),
|
|
|
|
'label_cancel': __('Cancel'),
|
|
|
|
'label_custom_status': __('Custom status'),
|
|
|
|
'label_offline': __('Offline'),
|
|
|
|
'label_online': __('Online'),
|
|
|
|
'label_save': __('Save'),
|
|
|
|
'label_xa': __('Away for long'),
|
|
|
|
'modal_title': __('Change chat status'),
|
|
|
|
'placeholder_status_message': __('Personal status message')
|
|
|
|
}));
|
2018-02-21 14:40:41 +01:00
|
|
|
},
|
|
|
|
|
2018-03-26 21:11:32 +02:00
|
|
|
afterRender () {
|
|
|
|
this.el.addEventListener('shown.bs.modal', () => {
|
|
|
|
this.el.querySelector('input[name="status_message"]').focus();
|
|
|
|
}, false);
|
|
|
|
},
|
|
|
|
|
2018-02-21 16:10:13 +01:00
|
|
|
clearStatusMessage (ev) {
|
|
|
|
if (ev && ev.preventDefault) {
|
|
|
|
ev.preventDefault();
|
|
|
|
u.hideElement(this.el.querySelector('.clear-input'));
|
|
|
|
}
|
|
|
|
const roster_filter = this.el.querySelector('input[name="status_message"]');
|
|
|
|
roster_filter.value = '';
|
|
|
|
},
|
|
|
|
|
2018-02-21 14:40:41 +01:00
|
|
|
onFormSubmitted (ev) {
|
|
|
|
ev.preventDefault();
|
2018-02-21 16:10:13 +01:00
|
|
|
const data = new FormData(ev.target);
|
|
|
|
this.model.save({
|
|
|
|
'status_message': data.get('status_message'),
|
|
|
|
'status': data.get('chat_status')
|
|
|
|
});
|
|
|
|
this.modal.hide();
|
2018-02-21 12:31:25 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2018-02-15 15:50:55 +01:00
|
|
|
_converse.XMPPStatusView = Backbone.VDOMView.extend({
|
|
|
|
tagName: "div",
|
2017-11-17 13:32:03 +01:00
|
|
|
events: {
|
2018-02-23 16:32:47 +01:00
|
|
|
"click a.show-profile": "showProfileModal",
|
2018-02-21 16:10:13 +01:00
|
|
|
"click a.change-status": "showStatusChangeModal",
|
2018-02-20 16:51:59 +01:00
|
|
|
"click .logout": "logOut"
|
2017-11-17 13:32:03 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
initialize () {
|
2018-02-19 22:12:50 +01:00
|
|
|
this.model.on("change", this.render, this);
|
2018-05-08 19:24:50 +02:00
|
|
|
this.model.vcard.on("change", this.render, this);
|
2017-11-17 13:32:03 +01:00
|
|
|
},
|
|
|
|
|
2018-02-15 15:50:55 +01:00
|
|
|
toHTML () {
|
2017-11-17 13:32:03 +01:00
|
|
|
const chat_status = this.model.get('status') || 'offline';
|
2018-05-08 19:24:50 +02:00
|
|
|
return tpl_profile_view(_.extend(
|
|
|
|
this.model.toJSON(),
|
|
|
|
this.model.vcard.toJSON(), {
|
|
|
|
'fullname': this.model.vcard.get('fullname') || _converse.bare_jid,
|
2018-02-15 15:50:55 +01:00
|
|
|
'status_message': this.model.get('status_message') ||
|
|
|
|
__("I am %1$s", this.getPrettyStatus(chat_status)),
|
|
|
|
'chat_status': chat_status,
|
2018-03-25 10:43:56 +02:00
|
|
|
'_converse': _converse,
|
2018-02-15 15:50:55 +01:00
|
|
|
'title_change_settings': __('Change settings'),
|
|
|
|
'title_change_status': __('Click to change your chat status'),
|
2018-02-20 15:57:01 +01:00
|
|
|
'title_log_out': __('Log out'),
|
2018-02-15 15:50:55 +01:00
|
|
|
'title_your_profile': __('Your profile')
|
|
|
|
}));
|
2017-11-17 13:32:03 +01:00
|
|
|
},
|
|
|
|
|
2018-02-23 16:32:47 +01:00
|
|
|
showProfileModal (ev) {
|
|
|
|
if (_.isUndefined(this.profile_modal)) {
|
|
|
|
this.profile_modal = new _converse.ProfileModal({model: this.model});
|
|
|
|
}
|
|
|
|
this.profile_modal.show(ev);
|
|
|
|
},
|
|
|
|
|
|
|
|
showStatusChangeModal (ev) {
|
2018-02-23 15:45:44 +01:00
|
|
|
if (_.isUndefined(this.status_modal)) {
|
|
|
|
this.status_modal = new _converse.ChatStatusModal({model: this.model});
|
|
|
|
}
|
|
|
|
this.status_modal.show(ev);
|
2018-02-21 16:10:13 +01:00
|
|
|
},
|
|
|
|
|
2018-02-20 16:51:59 +01:00
|
|
|
logOut (ev) {
|
2017-11-17 13:32:03 +01:00
|
|
|
ev.preventDefault();
|
2018-02-20 16:51:59 +01:00
|
|
|
const result = confirm(__("Are you sure you want to log out?"));
|
|
|
|
if (result === true) {
|
2017-11-17 13:32:03 +01:00
|
|
|
_converse.logOut();
|
|
|
|
}
|
2018-02-20 16:51:59 +01:00
|
|
|
},
|
|
|
|
|
2017-11-17 13:32:03 +01:00
|
|
|
getPrettyStatus (stat) {
|
|
|
|
if (stat === 'chat') {
|
|
|
|
return __('online');
|
|
|
|
} else if (stat === 'dnd') {
|
|
|
|
return __('busy');
|
|
|
|
} else if (stat === 'xa') {
|
|
|
|
return __('away for long');
|
|
|
|
} else if (stat === 'away') {
|
|
|
|
return __('away');
|
|
|
|
} else if (stat === 'offline') {
|
|
|
|
return __('offline');
|
|
|
|
} else {
|
|
|
|
return __(stat) || __('online');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}));
|