-
Xavier Ferrer de la Penyita authoredXavier Ferrer de la Penyita authored
solid-xmpp-chat.js 10.41 KiB
import './conversejs/converse.min.js';
import './conversejs/emojis.js';
import './plugins/converse-rai.js';
import { Helpers, store } from 'https://unpkg.com/@startinblox/core@0.12';
import { Sib } from "https://unpkg.com/@startinblox/core@0.12/dist/libs/Sib.js";
import { StoreMixin } from 'https://unpkg.com/@startinblox/core@0.12/dist/mixins/storeMixin.js';
import ComponentPath from './path.js';
class Deferred {
constructor() {
this.promise = new Promise(((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
}).bind(this));
this.then = this.promise.then.bind(this.promise);
this.catch = this.promise.catch.bind(this.promise);
}
}
export const SolidXMPPChat = {
name: 'solid-xmpp-chat',
use: [ StoreMixin ],
attributes: {
authentication: {
type: String,
default: 'login',
},
autoLogin: {
type: Boolean,
default: true,
},
i18n: {
type: String,
default: 'fr',
},
websocketUrl: {
type: String,
default: 'wss://jabber.happy-dev.fr/xmpp-websocket',
},
},
get extra_context() {
return { "foaf": 'http://xmlns.com/foaf/0.1/', "chatProfile": "http://happy-dev.fr/owl/#chatProfile", "jabberID": "foaf:jabberID" };
},
async created() {
const check_identified = await document.querySelector('sib-auth').getUserIdToken();
if(check_identified) {
this.element.attachShadow({
mode: "open"
});
this.element.shadowRoot.append(...Helpers.importCSS(
`${ComponentPath}/dist/conversejs/converse.min.css`,
`${ComponentPath}/dist/index.css`
));
if (window.converse_sib === undefined) {
this.initializeConverse();
}
} // Else, not logged in on page load (even if not on chat)
},
empty() {
this.element.innerHTML = '';
},
async populate() {
if(typeof converse_sib !== 'undefined') {
await converse_sib.loaded_deferred;
if (await this.resource.jabberRoom) {
this.jid = await this.resource['jabberID'];
} else {
this.jid = await this.resource['chatProfile.jabberID'];
}
await converse_sib.connected_deferred
converse_sib.service.plugins.sibChat.changeChat(
this.jid,
await this.resource.jabberRoom,
this.element.shadowRoot,
);
window.dispatchEvent(new CustomEvent('read', {
detail: {
resource: {
"@id": this.resource['@id']
}
}
}));
} // Else, not logged in, on chat change
},
async initializeConverse() {
window.converse_sib = {};
// Deferred resolved at the end of this function
converse_sib.loaded_deferred = new Deferred();
// Deferred resolved after converse.initialize
converse_sib.connected_deferred = new Deferred();
// Registering window.converse_sib.service
converse_sib.service = {
'waitUntilLoaded': converse_sib.loaded_deferred.promise,
'initialize': function (options) {
this.waitUntilLoaded().done(this.api.initialize, options);
},
'waitUntilConnected': converse_sib.connected_deferred.promise,
'plugins': {}
};
// Alias for solid-xmpp-chat use # want to un-expose converse from window later
// window.converse_sib.service.api === window.converse
converse_sib.service.api = converse;
// Change chat plugin
converse_sib.service.plugins.sibChat = new(class {
changeChat(jid, is_groupchat, root) {
if (!jid) {
return;
}
jid = jid.toLowerCase();
this._converse.root = root;
// Get the current used solid-xmpp-chat
const converse_el = Array.from(document.querySelectorAll('solid-xmpp-chat'))
.map(el => el.shadowRoot.getElementById('conversejs'))
.filter(el => el)
.pop();
if (converse_el) {
root.appendChild(converse_el);
}
if (is_groupchat) {
this._converse.api.rooms.open(jid, {}, true);
} else {
this._converse.api.chats.open(jid, {}, true);
}
}
});
// Initialize change change plugin
converse.plugins.add('conversejs-changechat', converse_sib.service.plugins.sibChat);
// Initialize deferred resolution plugin
converse.plugins.add('conversejs-sib-connected', {
initialize() {
this._converse.api.listen.on('connected', converse_sib.connected_deferred.resolve);
}
});
// Initialize AUTHFAIL plugin
converse.plugins.add('conversejs-sib-disconnected', {
initialize() {
this._converse.api.listen.on('disconnected', () => {
if(this._converse.connfeedback.attributes.connection_status === converse.env.Strophe.Status.AUTHFAIL) {
Array.from(document.querySelectorAll('solid-xmpp-chat')).map(el => el.shadowRoot.innerHTML =
`<div style='margin:3em;line-height:32px;'><b style='color:red;'>Erreur d'authentification.</b><br /><i style='color:grey;'>Êtes-vous sur le Hubl affilié à votre compte ?</i></div>`
);
}
});
}
});
// Initialize rai plugin
converse.plugins.add('conversejs-rai', {
async initialize() {
let userRooms = (await Promise.all([
new Promise((resolve, reject) => {
const circleInterval = setInterval(async () => {
let retry = false;
let circles = [];
const user = await document.querySelector('sib-auth').getUser();
const userProfile = await store.getData(user['@id'], this.context);
for (let circleMembership of await userProfile['circles.ldp:contains']) {
if (circleMembership) {
circles.push(await circleMembership['circle.jabberID']);
} else {
retry = true;
}
}
if (retry) {
} else {
clearInterval(circleInterval);
resolve(circles);
}
}, 250);
}),
new Promise((resolve, reject) => {
const projectInterval = setInterval(async () => {
let retry = false;
let projects = [];
const user = await document.querySelector('sib-auth').getUser();
const userProfile = await store.getData(user['@id'], this.context);
for (let projectMembership of await userProfile['projects.ldp:contains']) {
if (projectMembership) {
projects.push(await projectMembership['project.jabberID']);
} else {
retry = true;
}
}
if (retry) {
} else {
clearInterval(projectInterval);
resolve(projects);
}
}, 250);
})
])).flat();
// @MattJ Here userRooms is an array of each jabberID the user is on.
this._converse.api.trigger('raiRoomsUpdated', userRooms);
this._converse.api.listen.on('chatRoomActivityIndicators', function (jid) {
window.dispatchEvent(new CustomEvent('newMessage', {
detail: {
jid: jid
}
}));
});
}
});
// Initialize deferred resolution plugin
converse.plugins.add('conversejs-sib-focused', {
initialize() {
this._converse.api.listen.on('chatBoxFocused', function() {
// Get the currently used solid-xmpp-chat & send read event of
const resource = Array.from(document.querySelectorAll('solid-xmpp-chat'))
.filter(el => {return el.shadowRoot.getElementById('conversejs')})
.pop()
.component.resource;
window.dispatchEvent(new CustomEvent('read', {
detail: {
resource: resource
}
}));
});
}
});
const user = await document.querySelector('sib-auth').getUser();
const userProfile = await store.getData(user['@id'], this.context);
const jabberID = await userProfile['chatProfile.jabberID'];
if(this.resource) {
if (await this.resource.jabberRoom) {
this.jid = await this.resource['jabberID'];
} else {
this.jid = await this.resource['chatProfile.jabberID'];
}
} else {
this.jid = jabberID;
}
const idToken = await document.querySelector('sib-auth').getUserIdToken();
sessionStorage.clear();
indexedDB.deleteDatabase('converse-persistent');
converse.initialize({
'assets_path': ComponentPath + '/dist/conversejs/',
'authentication': this.element.dataset.authentication || 'login',
'password': idToken,
'allow_chat_pending_contacts': true,
'allow_message_retraction': 'moderator',
'allow_non_roster_messaging': true,
'allow_dragresize': false,
'allow_logout': false,
'archived_messages_page_size': "30",
'auto_list_rooms': true,
'auto_login': this.element.dataset.autoLogin === 'true',
'auto_join_on_invite': true,
'auto_reconnect': true,
'auto_register_muc_nickname': true,
'websocket_url': this.element.dataset.websocketUrl || 'wss://jabber.happy-dev.fr/xmpp-websocket',
'enable_smacks': true,
"clear_messages_on_reconnection": false,
"discover_connection_methods": false,
'jid': jabberID.toLowerCase(),
'i18n': this.element.dataset.i18n || 'fr',
'loglevel': 'fatal',
'message_archiving': 'always',
'message_archiving_timeout': 60000,
'muc_disable_slash_commands': true,
'muc_hats': ['hats', 'vcard_roles', 'moderator'],
'role_affiliation_hat_conversions': {'moderator': 'Administrateur'},
'muc_nickname_from_jid': true,
'muc_fetch_members': true,
'muc_show_info_messages': [],
'play_sounds': false,
'root': this.element.shadowRoot,
'show_client_info': false,
'show_desktop_notifications': false,
'persistent_store': 'IndexedDB',
'sounds_path': ComponentPath + '/dist/conversejs/',
'show_send_button': false,
'view_mode': 'fullscreen',
'visible_toolbar_buttons': {
call: false,
spoiler: false,
emoji: true,
fileupload: false, // Not working in current Converse
toggle_occupants: false
},
'whitelisted_plugins': ['rai', 'conversejs-sib-disconnected', 'conversejs-sib-connected', 'conversejs-sib-focused', 'conversejs-changechat', 'conversejs-rai'],
});
converse_sib.loaded_deferred.resolve();
}
};
Sib.register(SolidXMPPChat);