UNPKG

@converse/headless

Version:

Converse.js Headless build

172 lines (160 loc) 4.63 kB
/** * @copyright The Converse.js contributors * @license Mozilla Public License (MPLv2) * @description This is the core utilities module. */ import { Model } from '@converse/skeletor'; import log, { LEVELS } from '@converse/log'; import * as array from './array.js'; import * as arraybuffer from './arraybuffer.js'; import * as color from './color.js'; import * as html from './html.js'; import * as init from './init.js'; import * as jid from './jid.js'; import * as object from './object.js'; import * as promise from './promise.js'; import * as session from './session.js'; import * as stanza from './stanza.js'; import * as storage from './storage.js'; import * as text from './text.js'; import * as url from './url.js'; /** * The utils object * @namespace u * @type {import('./types').CommonUtils & import('./types').PluginUtils} */ const u = { bookmarks: null, emojis: null, mam: null, muc: null, omemo: null, reactions: null, roster: null, }; /** * @param {Event} [event] */ export function setLogLevelFromRoute(event) { if (location.hash.startsWith('#converse?loglevel=')) { event?.preventDefault(); const level = location.hash.split('=').pop(); if (Object.keys(LEVELS).includes(level)) { log.setLogLevel(/** @type {keyof LEVELS} */ (level)); } else { log.error(`Could not set loglevel of ${level}`); } } } export function isEmptyMessage(attrs) { if (attrs instanceof Model) { attrs = attrs.attributes; } return ( !attrs['oob_url'] && !attrs['file'] && !(attrs['is_encrypted'] && attrs['plaintext']) && !attrs['message'] && !attrs['body'] ); } /** * Given a message object, return its text with @ chars * inserted before the mentioned nicknames. * @param {import('../shared/message').default} message */ export function prefixMentions(message) { let text = message.getMessageText(); (message.get('references') || []) .sort((a, b) => b.begin - a.begin) .forEach((ref) => { text = `${text.slice(0, ref.begin)}@${text.slice(ref.begin)}`; }); return text; } function shouldCreateMessage(attrs) { return ( attrs['retracted'] || // Retraction received *before* the message // An error (e.g. a failed OMEMO decryption) should be surfaced to the // user rather than silently dropped, even when the stanza carried no // fallback body for us to show. See #2097. attrs['is_error'] || !isEmptyMessage(attrs) ); } /** * Call the callback once all the events have been triggered * @param { Array } events: An array of objects, with keys `object` and * `event`, representing the event name and the object it's triggered upon. * @param { Function } callback: The function to call once all events have * been triggered. */ function onMultipleEvents(events = [], callback) { let triggered = []; function handler(result) { triggered.push(result); if (events.length === triggered.length) { callback(triggered); triggered = []; } } events.forEach((e) => e.object.on(e.event, handler)); } /** * @param {Element} el * @param {string} name * @param {string} [type] * @param {boolean} [bubbles] * @param {boolean} [cancelable] */ function triggerEvent(el, name, type = 'Event', bubbles = true, cancelable = true) { const evt = document.createEvent(type); evt.initEvent(name, bubbles, cancelable); el.dispatchEvent(evt); } export function getRandomInt(max) { return (Math.random() * max) | 0; } /** * @param {string} [suffix] * @return {string} */ export function getUniqueId(suffix) { const uuid = crypto.randomUUID?.() ?? 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { const r = getRandomInt(16); const v = c === 'x' ? r : (r & 0x3) | 0x8; return v.toString(16); }); if (typeof suffix === 'string' || typeof suffix === 'number') { return uuid + ':' + suffix; } else { return uuid; } } export default Object.assign( { ...array, ...arraybuffer, ...color, ...html, ...init, ...jid, ...object, ...promise, ...session, ...stanza, ...storage, ...text, ...url, getRandomInt, getUniqueId, isEmptyMessage, onMultipleEvents, prefixMentions, shouldCreateMessage, triggerEvent, }, u, );