xmpp.chapril.org-conversejs/src/modals/add-contact.js
JC Brand bb3f52d2f2 Move the autocomplete code into ./shared
And remove it as a plugin.
2020-12-10 11:17:57 +01:00

144 lines
5.5 KiB
JavaScript

import 'shared/autocomplete/index.js';
import BootstrapModal from "./base.js";
import tpl_add_contact_modal from "./templates/add-contact.js";
import { __ } from '../i18n';
import { _converse, api, converse } from "@converse/headless/core";
import { compact, debounce } from "lodash-es";
const { Strophe } = converse.env;
const u = converse.env.utils;
const AddContactModal = BootstrapModal.extend({
id: "add-contact-modal",
events: {
'submit form': 'addContactFromForm'
},
initialize () {
BootstrapModal.prototype.initialize.apply(this, arguments);
this.listenTo(this.model, 'change', this.render);
},
toHTML () {
const label_nickname = api.settings.get('xhr_user_search_url') ? __('Contact name') : __('Optional nickname');
return tpl_add_contact_modal(Object.assign(this.model.toJSON(), { _converse, label_nickname }));
},
afterRender () {
if (typeof api.settings.get('xhr_user_search_url') === 'string') {
this.initXHRAutoComplete();
} else {
this.initJIDAutoComplete();
}
const jid_input = this.el.querySelector('input[name="jid"]');
this.el.addEventListener('shown.bs.modal', () => jid_input.focus(), false);
},
initJIDAutoComplete () {
if (!api.settings.get('autocomplete_add_contact')) {
return;
}
const el = this.el.querySelector('.suggestion-box__jid').parentElement;
this.jid_auto_complete = new _converse.AutoComplete(el, {
'data': (text, input) => `${input.slice(0, input.indexOf("@"))}@${text}`,
'filter': _converse.FILTER_STARTSWITH,
'list': [...new Set(_converse.roster.map(item => Strophe.getDomainFromJid(item.get('jid'))))]
});
},
initXHRAutoComplete () {
if (!api.settings.get('autocomplete_add_contact')) {
return this.initXHRFetch();
}
const el = this.el.querySelector('.suggestion-box__name').parentElement;
this.name_auto_complete = new _converse.AutoComplete(el, {
'auto_evaluate': false,
'filter': _converse.FILTER_STARTSWITH,
'list': []
});
const xhr = new window.XMLHttpRequest();
// `open` must be called after `onload` for mock/testing purposes.
xhr.onload = () => {
if (xhr.responseText) {
const r = xhr.responseText;
this.name_auto_complete.list = JSON.parse(r).map(i => ({'label': i.fullname || i.jid, 'value': i.jid}));
this.name_auto_complete.auto_completing = true;
this.name_auto_complete.evaluate();
}
};
const input_el = this.el.querySelector('input[name="name"]');
input_el.addEventListener('input', debounce(() => {
xhr.open("GET", `${api.settings.get('xhr_user_search_url')}q=${encodeURIComponent(input_el.value)}`, true);
xhr.send()
} , 300));
this.name_auto_complete.on('suggestion-box-selectcomplete', ev => {
this.el.querySelector('input[name="name"]').value = ev.text.label;
this.el.querySelector('input[name="jid"]').value = ev.text.value;
});
},
initXHRFetch () {
this.xhr = new window.XMLHttpRequest();
this.xhr.onload = () => {
if (this.xhr.responseText) {
const r = this.xhr.responseText;
const list = JSON.parse(r).map(i => ({'label': i.fullname || i.jid, 'value': i.jid}));
if (list.length !== 1) {
const el = this.el.querySelector('.invalid-feedback');
el.textContent = __('Sorry, could not find a contact with that name')
u.addClass('d-block', el);
return;
}
const jid = list[0].value;
if (this.validateSubmission(jid)) {
const form = this.el.querySelector('form');
const name = list[0].label;
this.afterSubmission(form, jid, name);
}
}
};
},
validateSubmission (jid) {
const el = this.el.querySelector('.invalid-feedback');
if (!jid || compact(jid.split('@')).length < 2) {
u.addClass('is-invalid', this.el.querySelector('input[name="jid"]'));
u.addClass('d-block', el);
return false;
} else if (_converse.roster.get(Strophe.getBareJidFromJid(jid))) {
el.textContent = __('This contact has already been added')
u.addClass('d-block', el);
return false;
}
u.removeClass('d-block', el);
return true;
},
afterSubmission (form, jid, name) {
_converse.roster.addAndSubscribe(jid, name);
this.model.clear();
this.modal.hide();
},
addContactFromForm (ev) {
ev.preventDefault();
const data = new FormData(ev.target),
jid = (data.get('jid') || '').trim();
if (!jid && typeof api.settings.get('xhr_user_search_url') === 'string') {
const input_el = this.el.querySelector('input[name="name"]');
this.xhr.open("GET", `${api.settings.get('xhr_user_search_url')}q=${encodeURIComponent(input_el.value)}`, true);
this.xhr.send()
return;
}
if (this.validateSubmission(jid)) {
this.afterSubmission(ev.target, jid, data.get('name'));
}
}
});
_converse.AddContactModal = AddContactModal;
export default AddContactModal;