diff --git a/src/converse-bookmark-views.js b/src/converse-bookmark-views.js index 005d4f48c..05abc8466 100644 --- a/src/converse-bookmark-views.js +++ b/src/converse-bookmark-views.js @@ -5,14 +5,15 @@ * @license Mozilla Public License (MPLv2) */ import "@converse/headless/converse-muc"; -import { Model } from 'skeletor.js/src/model.js'; -import { View } from 'skeletor.js/src/view.js'; -import { __ } from '@converse/headless/i18n'; import converse from "@converse/headless/converse-core"; import tpl_bookmarks_list from "templates/bookmarks_list.js" import tpl_muc_bookmark_form from "templates/muc_bookmark_form.js"; +import { Model } from 'skeletor.js/src/model.js'; +import { View } from 'skeletor.js/src/view.js'; +import { __ } from '@converse/headless/i18n'; +import { invokeMap } from 'lodash'; -const { Strophe, _ } = converse.env; +const { Strophe } = converse.env; const u = converse.env.utils; @@ -85,7 +86,7 @@ converse.plugins.add('converse-bookmark-views', { const name = ev.target.getAttribute('data-bookmark-name'); const jid = ev.target.getAttribute('data-room-jid'); if (confirm(__("Are you sure you want to remove the bookmark \"%1$s\"?", name))) { - _.invokeMap(_converse.bookmarks.where({'jid': jid}), Model.prototype.destroy); + invokeMap(_converse.bookmarks.where({'jid': jid}), Model.prototype.destroy); } }, @@ -166,9 +167,9 @@ converse.plugins.add('converse-bookmark-views', { ev.preventDefault(); _converse.bookmarks.createBookmark({ 'jid': this.model.get('jid'), - 'autojoin': _.get(ev.target.querySelector('input[name="autojoin"]'), 'checked') || false, - 'name': _.get(ev.target.querySelector('input[name=name]'), 'value'), - 'nick': _.get(ev.target.querySelector('input[name=nick]'), 'value') + 'autojoin': ev.target.querySelector('input[name="autojoin"]')?.checked || false, + 'name': ev.target.querySelector('input[name=name]')?.value, + 'nick': ev.target.querySelector('input[name=nick]')?.value }); this.closeBookmarkForm(ev); }, diff --git a/src/converse-chatview.js b/src/converse-chatview.js index 1ac557eec..226f03450 100644 --- a/src/converse-chatview.js +++ b/src/converse-chatview.js @@ -8,7 +8,7 @@ import "converse-message-view"; import "converse-modal"; import { BootstrapModal } from "./converse-modal.js"; import { Overview } from "skeletor.js/src/overview"; -import { debounce, get, isString } from "lodash"; +import { debounce, isString } from "lodash"; import { html, render } from "lit-html"; import converse from "@converse/headless/converse-core"; import log from "@converse/headless/log"; @@ -96,7 +96,7 @@ converse.plugins.add('converse-chatview', { }, toHTML () { - const vcard = get(this.model, 'vcard'), + const vcard = this.model?.vcard, vcard_json = vcard ? vcard.toJSON() : {}; return tpl_user_details_modal(Object.assign( this.model.toJSON(), @@ -295,10 +295,10 @@ converse.plugins.add('converse-chatview', { Object.assign(this.model.toJSON(), { '__': __, 'message_limit': _converse.message_limit, - 'hint_value': get(this.el.querySelector('.spoiler-hint'), 'value'), + 'hint_value': this.el.querySelector('.spoiler-hint')?.value, 'label_message': this.model.get('composing_spoiler') ? __('Hidden message') : __('Message'), 'label_spoiler_hint': __('Optional hint'), - 'message_value': get(this.el.querySelector('.chat-textarea'), 'value'), + 'message_value': this.el.querySelector('.chat-textarea')?.value, 'show_send_button': _converse.show_send_button, 'show_toolbar': _converse.show_toolbar, 'unread_msgs': __('You have unread messages') @@ -403,7 +403,7 @@ converse.plugins.add('converse-chatview', { }, generateHeadingTemplate () { - const vcard = get(this.model, 'vcard'); + const vcard = this.model?.vcard; const vcard_json = vcard ? vcard.toJSON() : {}; const heading_btns = this.getHeadingButtons(); const standalone_btns = heading_btns.filter(b => b.standalone); diff --git a/src/converse-controlbox.js b/src/converse-controlbox.js index 615ac8a04..97f1426a2 100644 --- a/src/converse-controlbox.js +++ b/src/converse-controlbox.js @@ -4,7 +4,6 @@ * @license Mozilla Public License (MPLv2) */ import "converse-chatview"; -import { get } from "lodash"; import { Model } from 'skeletor.js/src/model.js'; import { View } from "skeletor.js/src/view"; import bootstrap from "bootstrap.native"; @@ -209,7 +208,7 @@ converse.plugins.add('converse-controlbox', { this.hide(); } - const connection = get(_converse, 'connection', {}); + const connection = _converse?.connection || {}; if (!connection.connected || !connection.authenticated || connection.disconnecting) { this.renderLoginPanel(); } else if (this.model.get('connected')) { @@ -284,7 +283,7 @@ converse.plugins.add('converse-controlbox', { async close (ev) { if (ev && ev.preventDefault) { ev.preventDefault(); } - if (get(ev, 'name') === 'closeAllChatBoxes' && + if (ev?.name === 'closeAllChatBoxes' && (_converse.disconnection_cause !== _converse.LOGOUT || _converse.show_controlbox_by_default)) { return; @@ -292,7 +291,7 @@ converse.plugins.add('converse-controlbox', { if (_converse.sticky_controlbox) { return; } - const connection = get(_converse, 'connection', {}); + const connection = _converse?.connection || {}; if (connection.connected && !connection.disconnecting) { await new Promise((resolve, reject) => { return this.model.save( @@ -574,11 +573,11 @@ converse.plugins.add('converse-controlbox', { }); _converse.api.listen.on('clearSession', () => { - const chatboxviews = get(_converse, 'chatboxviews', null); + const chatboxviews = _converse?.chatboxviews; const view = chatboxviews && chatboxviews.get('controlbox'); if (view) { u.safeSave(view.model, {'connected': false}); - if (get(view, 'controlbox_pane')) { + if (view?.controlbox_pane) { view.controlbox_pane.remove(); delete view.controlbox_pane; } diff --git a/src/converse-dragresize.js b/src/converse-dragresize.js index 442b000c5..0d53ddc1f 100644 --- a/src/converse-dragresize.js +++ b/src/converse-dragresize.js @@ -5,7 +5,7 @@ */ import "converse-chatview"; import "converse-controlbox"; -import { debounce, get } from "lodash"; +import { debounce } from "lodash"; import converse from "@converse/headless/converse-core"; import tpl_dragresize from "templates/dragresize.html"; @@ -168,7 +168,7 @@ converse.plugins.add('converse-dragresize', { // Initialize last known mouse position this.prev_pageY = 0; this.prev_pageX = 0; - if (get(_converse.connection, 'connected')) { + if (_converse.connection?.connected) { this.height = this.model.get('height'); this.width = this.model.get('width'); } diff --git a/src/converse-emoji-views.js b/src/converse-emoji-views.js index b0b0018c6..1087f58d6 100644 --- a/src/converse-emoji-views.js +++ b/src/converse-emoji-views.js @@ -5,7 +5,7 @@ */ import "@converse/headless/converse-emoji"; import { View } from "skeletor.js/src/view"; -import { debounce, find, get } from "lodash"; +import { debounce, find } from "lodash"; import DOMNavigator from "./dom-navigator"; import bootstrap from "bootstrap.native"; import emoji_picker from "templates/emoji_picker.js"; @@ -255,7 +255,7 @@ converse.plugins.add('converse-emoji-views', { if (intersection_with_selected) { current = intersection_with_selected; } else { - current = ev.reduce((p, c) => c.intersectionRatio >= get(p, 'intersectionRatio', 0) ? c : p, null); + current = ev.reduce((p, c) => c.intersectionRatio >= (p?.intersectionRatio || 0) ? c : p, null); } current && current.isIntersecting && this.setCategoryForElement(current.target); }, diff --git a/src/converse-minimize.js b/src/converse-minimize.js index 8d92a8a86..c46826ecd 100644 --- a/src/converse-minimize.js +++ b/src/converse-minimize.js @@ -8,12 +8,13 @@ import { Model } from 'skeletor.js/src/model.js'; import { Overview } from "skeletor.js/src/overview"; import { View } from "skeletor.js/src/view"; import { __ } from '@converse/headless/i18n'; +import { debounce, sum } from 'lodash'; import converse from "@converse/headless/converse-core"; import tpl_chats_panel from "templates/chats_panel.html"; import tpl_toggle_chats from "templates/toggle_chats.html"; import tpl_trimmed_chat from "templates/trimmed_chat.html"; -const { _ , dayjs } = converse.env; +const { dayjs } = converse.env; const u = converse.env.utils; @@ -292,7 +293,7 @@ converse.plugins.add('converse-minimize', { }, getMinimizedWidth () { - const minimized_el = _.get(_converse.minimized_chats, 'el'); + const minimized_el = _converse.minimized_chats?.el; return this.model.pluck('minimized').includes(true) ? u.getOuterWidth(minimized_el, true) : 0; }, @@ -328,7 +329,7 @@ converse.plugins.add('converse-minimize', { return; } await _converse.api.waitUntil('minimizedChatsInitialized'); - const minimized_el = _.get(_converse.minimized_chats, 'el'); + const minimized_el = _converse.minimized_chats?.el; if (minimized_el) { while ((this.getMinimizedWidth() + this.getBoxesWidth(newchat)) > body_width) { const new_id = newchat ? newchat.model.get('id') : null; @@ -417,7 +418,7 @@ converse.plugins.add('converse-minimize', { return this; }, - restore: _.debounce(function (ev) { + restore: debounce(function (ev) { if (ev && ev.preventDefault) { ev.preventDefault(); } this.model.off('change:num_unread', null, this); this.remove(); @@ -513,7 +514,7 @@ converse.plugins.add('converse-minimize', { }, updateUnreadMessagesCounter () { - this.toggleview.model.save({'num_unread': _.sum(this.model.pluck('num_unread'))}); + this.toggleview.model.save({'num_unread': sum(this.model.pluck('num_unread'))}); this.render(); } }); @@ -569,7 +570,7 @@ converse.plugins.add('converse-minimize', { _converse.api.listen.on('chatBoxInsertedIntoDOM', view => _converse.chatboxviews.trimChats(view)); _converse.api.listen.on('controlBoxOpened', view => _converse.chatboxviews.trimChats(view)); - const debouncedTrimChats = _.debounce(() => _converse.chatboxviews.trimChats(), 250); + const debouncedTrimChats = debounce(() => _converse.chatboxviews.trimChats(), 250); _converse.api.listen.on('registeredGlobalEventHandlers', () => window.addEventListener("resize", debouncedTrimChats)); _converse.api.listen.on('unregisteredGlobalEventHandlers', () => window.removeEventListener("resize", debouncedTrimChats)); /************************ END Event Handlers ************************/ diff --git a/src/converse-muc-views.js b/src/converse-muc-views.js index 2c39cc4ca..8646e4030 100644 --- a/src/converse-muc-views.js +++ b/src/converse-muc-views.js @@ -8,7 +8,7 @@ import "converse-modal"; import "@converse/headless/utils/muc"; import { Model } from 'skeletor.js/src/model.js'; import { View } from 'skeletor.js/src/view.js'; -import { get, head, isString, isUndefined } from "lodash"; +import { head, isString, isUndefined } from "lodash"; import { BootstrapModal } from "./converse-modal.js"; import { render } from "lit-html"; import { __ } from '@converse/headless/i18n'; @@ -172,8 +172,8 @@ converse.plugins.add('converse-muc-views', { 'beforeEnd', tpl_room_description({ 'jid': stanza.getAttribute('from'), - 'desc': get(head(sizzle('field[var="muc#roominfo_description"] value', stanza)), 'textContent'), - 'occ': get(head(sizzle('field[var="muc#roominfo_occupants"] value', stanza)), 'textContent'), + 'desc': head(sizzle('field[var="muc#roominfo_description"] value', stanza))?.textContent, + 'occ': head(sizzle('field[var="muc#roominfo_occupants"] value', stanza))?.textContent, 'hidden': sizzle('feature[var="muc_hidden"]', stanza).length, 'membersonly': sizzle('feature[var="muc_membersonly"]', stanza).length, 'moderated': sizzle('feature[var="muc_moderated"]', stanza).length, @@ -764,11 +764,7 @@ converse.plugins.add('converse-muc-views', { if (!(existing_actors?.length)) { return result; } - const actors = existing_actors - .map(a => this.model.getOccupant(a)) - .filter(a => a) - .map(a => a.getDisplayName()); - + const actors = existing_actors.map(a => this.model.getOccupant(a)?.getDisplayName() || a.nick); if (actors.length === 1) { if (state === 'composing') { return `${result} ${__('%1$s is typing', actors[0])}\n`; @@ -1941,7 +1937,7 @@ converse.plugins.add('converse-muc-views', { if (date && date.split('T')[0] !== today) { return; } - const data = get(el, 'dataset', {}); + const data = el?.dataset || {}; if (data.join === nick || data.leave === nick || data.leavejoin === nick || @@ -1960,7 +1956,7 @@ converse.plugins.add('converse-muc-views', { const nick = occupant.get('nick'), stat = _converse.muc_show_join_leave_status ? occupant.get('status') : null, prev_info_el = this.getPreviousJoinOrLeaveNotification(this.content.lastElementChild, nick), - data = get(prev_info_el, 'dataset', {}); + data = prev_info_el?.dataset || {}; if (data.leave === nick) { let message; @@ -2015,7 +2011,7 @@ converse.plugins.add('converse-muc-views', { const nick = occupant.get('nick'), stat = _converse.muc_show_join_leave_status ? occupant.get('status') : null, prev_info_el = this.getPreviousJoinOrLeaveNotification(this.content.lastElementChild, nick), - dataset = get(prev_info_el, 'dataset', {}); + dataset = prev_info_el?.dataset || {}; if (dataset.join === nick) { let message; @@ -2192,9 +2188,9 @@ converse.plugins.add('converse-muc-views', { return tpl_muc_config_form({ 'closeConfigForm': ev => this.closeConfigForm(ev), 'fields': fields.map(f => u.xForm2webForm(f, stanza, options)), - 'instructions': get(stanza.querySelector('instructions'), 'textContent'), + 'instructions': stanza.querySelector('instructions')?.textContent, 'submitConfigForm': ev => this.submitConfigForm(ev), - 'title': get(stanza.querySelector('title'), 'textContent') + 'title': stanza.querySelector('title')?.textContent }); }, diff --git a/src/converse-notification.js b/src/converse-notification.js index 91f2e4f2d..8ba2948f8 100644 --- a/src/converse-notification.js +++ b/src/converse-notification.js @@ -4,7 +4,6 @@ * @license Mozilla Public License (MPLv2) */ import converse from "@converse/headless/converse-core"; -import { get } from "lodash"; import log from "@converse/headless/log"; const { Strophe, sizzle } = converse.env; @@ -166,7 +165,7 @@ converse.plugins.add('converse-notification', { // the message... const body = sizzle(`encrypted[xmlns="${Strophe.NS.OMEMO}"]`, message).length ? __('OMEMO Message received') : - get(message.querySelector('body'), 'textContent'); + message.querySelector('body')?.textContent; if (!body) { return; } diff --git a/src/converse-omemo.js b/src/converse-omemo.js index e103b4f8a..5c060f19e 100644 --- a/src/converse-omemo.js +++ b/src/converse-omemo.js @@ -8,7 +8,7 @@ import "converse-profile"; import { Collection } from "skeletor.js/src/collection"; import { Model } from 'skeletor.js/src/model.js'; -import { concat, debounce, difference, get, invokeMap, range, omit } from "lodash"; +import { concat, debounce, difference, invokeMap, range, omit } from "lodash"; import converse from "@converse/headless/converse-core"; import log from "@converse/headless/log"; import tpl_toolbar_omemo from "templates/toolbar_omemo.html"; @@ -377,7 +377,7 @@ converse.plugins.add('converse-omemo', { 'device_id': header.getAttribute('sid'), 'iv': header.querySelector('iv').textContent, 'key': key.textContent, - 'payload': get(encrypted.querySelector('payload'), 'textContent', null), + 'payload': encrypted.querySelector('payload')?.textContent || null, 'prekey': ['true', '1'].includes(key.getAttribute('prekey')) } return this.decrypt(attrs); @@ -481,7 +481,7 @@ converse.plugins.add('converse-omemo', { async function generateFingerprint (device) { - if (get(device.get('bundle'), 'fingerprint')) { + if (device.get('bundle')?.fingerprint) { return; } const bundle = await device.getBundle(); diff --git a/src/converse-push.js b/src/converse-push.js index 61004fb93..9c6778916 100644 --- a/src/converse-push.js +++ b/src/converse-push.js @@ -7,9 +7,10 @@ * @license Mozilla Public License (MPLv2) */ import converse from "@converse/headless/converse-core"; +import { filter, reject } from 'lodash'; import log from "@converse/headless/log"; -const { Strophe, $iq, _ } = converse.env; +const { Strophe, $iq } = converse.env; Strophe.addNamespace('PUSH', 'urn:xmpp:push:0'); @@ -96,10 +97,10 @@ converse.plugins.add('converse-push', { if (push_enabled.includes(domain)) { return; } - const enabled_services = _.reject(_converse.push_app_servers, 'disable'); - const disabled_services = _.filter(_converse.push_app_servers, 'disable'); - const enabled = _.map(enabled_services, _.partial(enablePushAppServer, domain)); - const disabled = _.map(disabled_services, _.partial(disablePushAppServer, domain)); + const enabled_services = reject(_converse.push_app_servers, 'disable'); + const disabled_services = filter(_converse.push_app_servers, 'disable'); + const enabled = enabled_services.map(s => enablePushAppServer(domain, s)); + const disabled = disabled_services.map(s => disablePushAppServer(domain, s)); try { await Promise.all(enabled.concat(disabled)); } catch (e) { diff --git a/src/converse-register.js b/src/converse-register.js index 6229354d7..206ff0d31 100644 --- a/src/converse-register.js +++ b/src/converse-register.js @@ -8,7 +8,7 @@ */ import "converse-controlbox"; import { View } from "skeletor.js/src/view"; -import { get, pick } from "lodash"; +import { pick } from "lodash"; import converse from "@converse/headless/converse-core"; import log from "@converse/headless/log"; import tpl_form_input from "templates/form_input.html"; @@ -287,7 +287,7 @@ converse.plugins.add('converse-register', { */ onProviderChosen (form) { const domain_input = form.querySelector('input[name=domain]'), - domain = get(domain_input, 'value'); + domain = domain_input?.value; if (!domain) { // TODO: add validation message domain_input.classList.add('error'); @@ -597,12 +597,12 @@ converse.plugins.add('converse-register', { }, _setFieldsFromXForm (xform) { - this.title = get(xform.querySelector('title'), 'textContent'); - this.instructions = get(xform.querySelector('instructions'), 'textContent'); + this.title = xform.querySelector('title')?.textContent; + this.instructions = xform.querySelector('instructions')?.textContent; xform.querySelectorAll('field').forEach(field => { const _var = field.getAttribute('var'); if (_var) { - this.fields[_var.toLowerCase()] = get(field.querySelector('value'), 'textContent', ''); + this.fields[_var.toLowerCase()] = field.querySelector('value')?.textContent ?? ''; } else { // TODO: other option seems to be type="fixed" log.warn("Found field we couldn't parse"); diff --git a/src/headless/converse-bookmarks.js b/src/headless/converse-bookmarks.js index 74dc5a2a7..3d966ad07 100644 --- a/src/headless/converse-bookmarks.js +++ b/src/headless/converse-bookmarks.js @@ -9,7 +9,6 @@ import "@converse/headless/converse-muc"; import converse from "@converse/headless/converse-core"; import { Collection } from "skeletor.js/src/collection"; import { Model } from 'skeletor.js/src/model.js'; -import { get } from "lodash"; import log from "./log"; const { Strophe, $iq, sizzle } = converse.env; @@ -215,7 +214,7 @@ converse.plugins.add('converse-bookmarks', { 'jid': jid, 'name': bookmark.getAttribute('name') || jid, 'autojoin': bookmark.getAttribute('autojoin') === 'true', - 'nick': get(bookmark.querySelector('nick'), 'textContent') + 'nick': bookmark.querySelector('nick')?.textContent }); }); }, diff --git a/src/headless/converse-chat.js b/src/headless/converse-chat.js index dd8ec228a..3ca5e74fb 100644 --- a/src/headless/converse-chat.js +++ b/src/headless/converse-chat.js @@ -3,7 +3,7 @@ * @copyright 2020, the Converse.js contributors * @license Mozilla Public License (MPLv2) */ -import { find, get, isMatch, isObject, isString, pick } from "lodash"; +import { find, isMatch, isObject, isString, pick } from "lodash"; import { Collection } from "skeletor.js/src/collection"; import { Model } from 'skeletor.js/src/model.js'; import converse from "./converse-core"; @@ -1033,8 +1033,8 @@ converse.plugins.add('converse-chat', { return; } const data = item.dataforms.where({'FORM_TYPE': {'value': Strophe.NS.HTTPUPLOAD, 'type': "hidden"}}).pop(), - max_file_size = window.parseInt(get(data, 'attributes.max-file-size.value')), - slot_request_url = get(item, 'id'); + max_file_size = window.parseInt((data?.attributes || {})['max-file-size']?.value), + slot_request_url = item?.id; if (!slot_request_url) { this.createMessage({ @@ -1224,7 +1224,7 @@ converse.plugins.add('converse-chat', { } // Get chat box, but only create when the message has something to show to the user const has_body = sizzle(`body, encrypted[xmlns="${Strophe.NS.OMEMO}"]`, stanza).length > 0; - const roster_nick = get(contact, 'attributes.nickname'); + const roster_nick = contact?.attributes?.nickname; const chatbox = await _converse.api.chats.get(contact_jid, {'nickname': roster_nick}, has_body); chatbox && await chatbox.queueMessage(stanza, original_stanza, from_jid); /** @@ -1336,9 +1336,9 @@ converse.plugins.add('converse-chat', { */ async create (jids, attrs) { if (isString(jids)) { - if (attrs && !get(attrs, 'fullname')) { + if (attrs && !attrs?.fullname) { const contact = await _converse.api.contacts.get(jids); - attrs.fullname = get(contact, 'attributes.fullname'); + attrs.fullname = contact?.attributes?.fullname; } const chatbox = _converse.api.chats.get(jids, attrs, true); if (!chatbox) { @@ -1350,7 +1350,7 @@ converse.plugins.add('converse-chat', { if (Array.isArray(jids)) { return Promise.all(jids.forEach(async jid => { const contact = await _converse.api.contacts.get(jids); - attrs.fullname = get(contact, 'attributes.fullname'); + attrs.fullname = contact?.attributes?.fullname; return _converse.api.chats.get(jid, attrs, true).maybeShow(); })); } diff --git a/src/headless/converse-core.js b/src/headless/converse-core.js index a9bda7003..1fa41f78e 100644 --- a/src/headless/converse-core.js +++ b/src/headless/converse-core.js @@ -4,7 +4,7 @@ * @license Mozilla Public License (MPLv2) */ import { __, i18n } from './i18n'; -import { assignIn, debounce, get, invoke, isFunction, isObject, isString, pick } from 'lodash'; +import { assignIn, debounce, invoke, isFunction, isObject, isString, pick } from 'lodash'; import { Collection } from "skeletor.js/src/collection"; import { Events } from 'skeletor.js/src/events.js'; import { Model } from 'skeletor.js/src/model.js'; @@ -486,7 +486,7 @@ function connect (credentials) { BOSH_WAIT ); } else if (_converse.authentication === _converse.LOGIN) { - const password = credentials ? credentials.password : (get(_converse.connection, 'pass') || _converse.password); + const password = credentials ? credentials.password : (_converse.connection?.pass || _converse.password); if (!password) { if (_converse.auto_login) { throw new Error("autoLogin: If you use auto_login and "+ @@ -1063,7 +1063,7 @@ _converse.initialize = async function (settings, callback) { return finishDisconnection(); } } else if (_converse.disconnection_cause === _converse.LOGOUT || - (reason !== undefined && reason === get(Strophe, 'ErrorCondition.NO_AUTH_MECH')) || + (reason !== undefined && reason === Strophe?.ErrorCondition.NO_AUTH_MECH) || reason === "host-unknown" || reason === "remote-connection-failed" || !_converse.auto_reconnect) { @@ -1139,7 +1139,7 @@ _converse.initialize = async function (settings, callback) { if (message === "host-unknown" || message == "remote-connection-failed") { feedback = __("Sorry, we could not connect to the XMPP host with domain: %1$s", `\"${Strophe.getDomainFromJid(_converse.connection.jid)}\"`); - } else if (message !== undefined && message === get(Strophe, 'ErrorCondition.NO_AUTH_MECH')) { + } else if (message !== undefined && message === Strophe?.ErrorCondition?.NO_AUTH_MECH) { feedback = __("The XMPP server did not offer a supported authentication mechanism"); } _converse.setConnectionStatus(status, feedback); @@ -1206,7 +1206,7 @@ _converse.api = { * @returns {boolean} Whether there is an established connection or not. */ connected () { - return get(_converse, 'connection', {}).connected && true; + return _converse?.connection?.connected && true; }, /** diff --git a/src/headless/converse-disco.js b/src/headless/converse-disco.js index 0c7b5b2ee..9a9194372 100644 --- a/src/headless/converse-disco.js +++ b/src/headless/converse-disco.js @@ -4,7 +4,7 @@ * @license Mozilla Public License (MPLv2) * @description Converse plugin which add support for XEP-0030: Service Discovery */ -import { get, isEmpty, isObject } from "lodash"; +import { isEmpty, isObject } from "lodash"; import { Collection } from "skeletor.js/src/collection"; import { Model } from 'skeletor.js/src/model.js'; import converse from "./converse-core"; @@ -195,7 +195,7 @@ converse.plugins.add('converse-disco', { const data = {}; sizzle('field', form).forEach(field => { data[field.getAttribute('var')] = { - 'value': get(field.querySelector('value'), 'textContent'), + 'value': field.querySelector('value')?.textContent, 'type': field.getAttribute('type') }; }); @@ -216,7 +216,7 @@ converse.plugins.add('converse-disco', { sizzle('x[type="result"][xmlns="jabber:x:data"] field', stanza).forEach(field => { this.fields.create({ 'var': field.getAttribute('var'), - 'value': get(field.querySelector('value'), 'textContent'), + 'value': field.querySelector('value')?.textContent, 'from': stanza.getAttribute('from') }); }); diff --git a/src/headless/converse-muc.js b/src/headless/converse-muc.js index 4ff416ad4..ec34c9e35 100644 --- a/src/headless/converse-muc.js +++ b/src/headless/converse-muc.js @@ -9,7 +9,7 @@ import "./converse-disco"; import "./converse-emoji"; import { Collection } from "skeletor.js/src/collection"; import { Model } from 'skeletor.js/src/model.js'; -import { clone, debounce, get, intersection, invoke, isElement, isObject, isString, pick, uniq, zipObject } from "lodash"; +import { clone, debounce, intersection, invoke, isElement, isObject, isString, pick, uniq, zipObject } from "lodash"; import converse from "./converse-core"; import log from "./log"; import muc_utils from "./utils/muc"; @@ -259,7 +259,7 @@ converse.plugins.add('converse-muc', { onOccupantRemoved () { this.stopListening(this.occupant); delete this.occupant; - const chatbox = get(this, 'collection.chatbox'); + const chatbox = this?.collection?.chatbox; if (!chatbox) { return log.error(`Could not get collection.chatbox for message: ${JSON.stringify(this.toJSON())}`); } @@ -270,7 +270,7 @@ converse.plugins.add('converse-muc', { if (occupant.get('nick') === Strophe.getResourceFromJid(this.get('from'))) { this.occupant = occupant; this.listenTo(this.occupant, 'destroy', this.onOccupantRemoved); - const chatbox = get(this, 'collection.chatbox'); + const chatbox = this?.collection?.chatbox; if (!chatbox) { return log.error(`Could not get collection.chatbox for message: ${JSON.stringify(this.toJSON())}`); } @@ -280,7 +280,7 @@ converse.plugins.add('converse-muc', { setOccupant () { if (this.get('type') !== 'groupchat') { return; } - const chatbox = get(this, 'collection.chatbox'); + const chatbox = this?.collection?.chatbox; if (!chatbox) { return log.error(`Could not get collection.chatbox for message: ${JSON.stringify(this.toJSON())}`); } @@ -1210,7 +1210,7 @@ converse.plugins.add('converse-muc', { * @returns { ('none'|'visitor'|'participant'|'moderator') } */ getOwnRole () { - return get(this.getOwnOccupant(), 'attributes.role'); + return this.getOwnOccupant()?.attributes?.role; }, /** @@ -1220,7 +1220,7 @@ converse.plugins.add('converse-muc', { * @returns { ('none'|'outcast'|'member'|'admin'|'owner') } */ getOwnAffiliation () { - return get(this.getOwnOccupant(), 'attributes.affiliation'); + return this.getOwnOccupant()?.attributes?.affiliation; }, /** @@ -1534,8 +1534,8 @@ converse.plugins.add('converse-muc', { } const jid = data.jid || ''; const attributes = Object.assign(data, { - 'jid': Strophe.getBareJidFromJid(jid) || get(occupant, 'attributes.jid'), - 'resource': Strophe.getResourceFromJid(jid) || get(occupant, 'attributes.resource') + 'jid': Strophe.getBareJidFromJid(jid) || occupant?.attributes?.jid, + 'resource': Strophe.getResourceFromJid(jid) || occupant?.attributes?.resource }); if (occupant) { occupant.save(attributes); @@ -1580,7 +1580,7 @@ converse.plugins.add('converse-muc', { } }); } else if (child.getAttribute("xmlns") === Strophe.NS.VCARDUPDATE) { - data.image_hash = get(child.querySelector('photo'), 'textContent'); + data.image_hash = child.querySelector('photo')?.textContent; } } }); @@ -1959,7 +1959,7 @@ converse.plugins.add('converse-muc', { }, handleModifyError(pres) { - const text = get(pres.querySelector('error text'), 'textContent'); + const text = pres.querySelector('error text')?.textContent; if (text) { if (this.session.get('connection_status') === converse.ROOMSTATUS.CONNECTING) { this.setDisconnectionMessage(text); @@ -1991,7 +1991,7 @@ converse.plugins.add('converse-muc', { // element. This appears to be a safe assumption, since // each element pertains to a single user. const item = x.querySelector('item'); - const reason = item ? get(item.querySelector('reason'), 'textContent') : undefined; + const reason = item ? item.querySelector('reason')?.textContent : undefined; const actor = item ? invoke(item.querySelector('actor'), 'getAttribute', 'nick') : undefined; const message = _converse.muc.disconnect_messages[disconnection_codes[0]]; this.setDisconnectionMessage(message, reason, actor); @@ -2038,7 +2038,7 @@ converse.plugins.add('converse-muc', { const nick = Strophe.getResourceFromJid(stanza.getAttribute('from')); const item = x.querySelector('item'); data.actor = item ? invoke(item.querySelector('actor'), 'getAttribute', 'nick') : undefined; - data.reason = item ? get(item.querySelector('reason'), 'textContent') : undefined; + data.reason = item ? item.querySelector('reason')?.textContent : undefined; data.message = this.getActionInfoMessage(code, nick, data.actor); } else if (is_self && (code in _converse.muc.new_nickname_messages)) { let nick; @@ -2107,7 +2107,7 @@ converse.plugins.add('converse-muc', { onErrorPresence (stanza) { const error = stanza.querySelector('error'); const error_type = error.getAttribute('type'); - const reason = get(sizzle(`text[xmlns="${Strophe.NS.STANZAS}"]`, error).pop(), 'textContent'); + const reason = sizzle(`text[xmlns="${Strophe.NS.STANZAS}"]`, error).pop()?.textContent; if (error_type === 'modify') { this.handleModifyError(stanza); @@ -2131,7 +2131,7 @@ converse.plugins.add('converse-muc', { const message = __("Your nickname doesn't conform to this groupchat's policies."); this.setDisconnectionMessage(message, reason); } else if (sizzle(`gone[xmlns="${Strophe.NS.STANZAS}"]`, error).length) { - const moved_jid = get(sizzle(`gone[xmlns="${Strophe.NS.STANZAS}"]`, error).pop(), 'textContent') + const moved_jid = sizzle(`gone[xmlns="${Strophe.NS.STANZAS}"]`, error).pop()?.textContent .replace(/^xmpp:/, '') .replace(/\?join$/, ''); this.save({ moved_jid, 'destroyed_reason': reason}); diff --git a/src/headless/converse-roster.js b/src/headless/converse-roster.js index 616519ab6..22baa85a6 100644 --- a/src/headless/converse-roster.js +++ b/src/headless/converse-roster.js @@ -6,7 +6,7 @@ import "@converse/headless/converse-status"; import { Collection } from "skeletor.js/src/collection"; import { Model } from 'skeletor.js/src/model.js'; -import { get, invoke, isEmpty, isNaN, isString, propertyOf, sum } from "lodash"; +import { invoke, isEmpty, isNaN, isString, propertyOf, sum } from "lodash"; import converse from "@converse/headless/converse-core"; import log from "./log"; @@ -136,7 +136,7 @@ converse.plugins.add('converse-roster', { onResourcesChanged () { const hpr = this.getHighestPriorityResource(); - const show = get(hpr, 'attributes.show', 'offline'); + const show = hpr?.attributes?.show || 'offline'; if (this.get('show') !== show) { this.save({'show': show}); } @@ -538,7 +538,7 @@ converse.plugins.add('converse-roster', { contact.authorize().subscribe(); } else { // Can happen when a subscription is retried or roster was deleted - const nickname = get(sizzle(`nick[xmlns="${Strophe.NS.NICK}"]`, presence).pop(), 'textContent', null); + const nickname = sizzle(`nick[xmlns="${Strophe.NS.NICK}"]`, presence).pop()?.textContent || null; const contact = await this.addContactToRoster(bare_jid, nickname, [], {'subscription': 'from'}); if (contact instanceof _converse.RosterContact) { contact.authorize().subscribe(); @@ -686,8 +686,8 @@ converse.plugins.add('converse-roster', { }, createRequestingContact (presence) { - const bare_jid = Strophe.getBareJidFromJid(presence.getAttribute('from')), - nickname = get(sizzle(`nick[xmlns="${Strophe.NS.NICK}"]`, presence).pop(), 'textContent', null); + const bare_jid = Strophe.getBareJidFromJid(presence.getAttribute('from')); + const nickname = sizzle(`nick[xmlns="${Strophe.NS.NICK}"]`, presence).pop()?.textContent || null; const user_data = { 'jid': bare_jid, 'subscription': 'none', diff --git a/src/headless/converse-status.js b/src/headless/converse-status.js index 26b8c3039..b020ea6d5 100644 --- a/src/headless/converse-status.js +++ b/src/headless/converse-status.js @@ -3,7 +3,7 @@ * @copyright The Converse.js contributors * @license Mozilla Public License (MPLv2) */ -import { get, isNaN, isObject, isString } from "lodash"; +import { isNaN, isObject, isString } from "lodash"; import { Model } from 'skeletor.js/src/model.js'; import converse from "@converse/headless/converse-core"; @@ -97,7 +97,7 @@ converse.plugins.add('converse-status', { if (_converse.idle_seconds > 0) { _converse.idle_seconds = 0; } - if (!get(_converse.connection, 'authenticated')) { + if (!_converse.connection?.authenticated) { // We can't send out any stanzas when there's no authenticated connection. // This can happen when the connection reconnects. return; @@ -121,7 +121,7 @@ converse.plugins.add('converse-status', { /* An interval handler running every second. * Used for CSI and the auto_away and auto_xa features. */ - if (!get(_converse.connection, 'authenticated')) { + if (!_converse.connection?.authenticated) { // We can't send out any stanzas when there's no authenticated connection. // This can happen when the connection reconnects. return; diff --git a/src/headless/converse-vcard.js b/src/headless/converse-vcard.js index 5e1ca3671..9206696af 100644 --- a/src/headless/converse-vcard.js +++ b/src/headless/converse-vcard.js @@ -6,7 +6,7 @@ import "./converse-status"; import { Collection } from "skeletor.js/src/collection"; import { Model } from 'skeletor.js/src/model.js'; -import { get, has, isString } from "lodash"; +import { has, isString } from "lodash"; import converse from "./converse-core"; import log from "@converse/headless/log"; import tpl_vcard from "./templates/vcard.html"; @@ -117,13 +117,13 @@ converse.plugins.add('converse-vcard', { if (vcard !== null) { result = { 'stanza': iq, - 'fullname': get(vcard.querySelector('FN'), 'textContent'), - 'nickname': get(vcard.querySelector('NICKNAME'), 'textContent'), - 'image': get(vcard.querySelector('PHOTO BINVAL'), 'textContent'), - 'image_type': get(vcard.querySelector('PHOTO TYPE'), 'textContent'), - 'url': get(vcard.querySelector('URL'), 'textContent'), - 'role': get(vcard.querySelector('ROLE'), 'textContent'), - 'email': get(vcard.querySelector('EMAIL USERID'), 'textContent'), + 'fullname': vcard.querySelector('FN')?.textConte?.t, + 'nickname': vcard.querySelector('NICKNAME')?.textConte?.t, + 'image': vcard.querySelector('PHOTO BINVAL')?.textConte?.t, + 'image_type': vcard.querySelector('PHOTO TYPE')?.textConte?.t, + 'url': vcard.querySelector('URL')?.textConte?.t, + 'role': vcard.querySelector('ROLE')?.textConte?.t, + 'email': vcard.querySelector('EMAIL USERID')?.textConte?.t, 'vcard_updated': (new Date()).toISOString(), 'vcard_error': undefined }; @@ -184,7 +184,7 @@ converse.plugins.add('converse-vcard', { function getVCardForChatroomOccupant (message) { - const chatbox = get(message, 'collection.chatbox'); + const chatbox = message?.collection?.chatbox; const nick = Strophe.getResourceFromJid(message.get('from')); if (chatbox && chatbox.get('nick') === nick) { diff --git a/src/headless/log.js b/src/headless/log.js index eb0f62900..42bab6f91 100644 --- a/src/headless/log.js +++ b/src/headless/log.js @@ -1,4 +1,4 @@ -import { get, isElement } from 'lodash'; +import { isElement } from 'lodash'; const LEVELS = { 'debug': 0, @@ -9,10 +9,10 @@ const LEVELS = { } const logger = Object.assign({ - 'debug': get(console, 'log') ? console.log.bind(console) : function noop () {}, - 'error': get(console, 'log') ? console.log.bind(console) : function noop () {}, - 'info': get(console, 'log') ? console.log.bind(console) : function noop () {}, - 'warn': get(console, 'log') ? console.log.bind(console) : function noop () {} + 'debug': console?.log ? console.log.bind(console) : function noop () {}, + 'error': console?.log ? console.log.bind(console) : function noop () {}, + 'info': console?.log ? console.log.bind(console) : function noop () {}, + 'warn': console?.log ? console.log.bind(console) : function noop () {} }, console); diff --git a/src/headless/utils/stanza.js b/src/headless/utils/stanza.js index edfdf04b3..71b218ab0 100644 --- a/src/headless/utils/stanza.js +++ b/src/headless/utils/stanza.js @@ -1,5 +1,5 @@ import * as strophe from 'strophe.js/src/core'; -import { get, propertyOf } from "lodash"; +import { propertyOf } from "lodash"; import dayjs from 'dayjs'; import log from '@converse/headless/log'; import sizzle from 'sizzle'; @@ -95,7 +95,7 @@ const stanza_utils = { 'moderated': 'retracted', 'moderated_by': moderated.getAttribute('by'), 'moderated_id': applies_to_id, - 'moderation_reason': get(moderated.querySelector('reason'), 'textContent') + 'moderation_reason': moderated.querySelector('reason')?.textContent } } } @@ -109,7 +109,7 @@ const stanza_utils = { 'is_tombstone': true, 'moderated_by': tombstone.getAttribute('by'), 'retracted': tombstone.getAttribute('stamp'), - 'moderation_reason': get(tombstone.querySelector('reason'), 'textContent') + 'moderation_reason': tombstone.querySelector('reason')?.textContent } } @@ -202,7 +202,7 @@ const stanza_utils = { const spoiler = sizzle(`spoiler[xmlns="${Strophe.NS.SPOILER}"]`, stanza).pop(); return { 'is_spoiler': !!spoiler, - 'spoiler_hint': get(spoiler, 'textContent') + 'spoiler_hint': spoiler?.textContent } }, @@ -210,8 +210,8 @@ const stanza_utils = { const xform = sizzle(`x[xmlns="${Strophe.NS.OUTOFBAND}"]`, stanza).pop(); if (xform) { return { - 'oob_url': get(xform.querySelector('url'), 'textContent'), - 'oob_desc': get(xform.querySelector('desc'), 'textContent') + 'oob_url': xform.querySelector('url')?.textContent, + 'oob_desc': xform.querySelector('desc')?.textContent } } return {}; diff --git a/src/utils/html.js b/src/utils/html.js index b33132c83..86b480190 100644 --- a/src/utils/html.js +++ b/src/utils/html.js @@ -4,7 +4,7 @@ * @description This is the DOM/HTML utilities module. */ import URI from "urijs"; -import { get, isFunction } from "lodash"; +import { isFunction } from "lodash"; import log from '@converse/headless/log'; import sizzle from "sizzle"; import tpl_audio from "../templates/audio.js"; @@ -588,9 +588,9 @@ u.xForm2webForm = function (field, stanza, options) { if (field.getAttribute('type') === 'list-single' || field.getAttribute('type') === 'list-multi') { - const values = u.queryChildren(field, 'value').map(el => get(el, 'textContent')); + const values = u.queryChildren(field, 'value').map(el => el?.textContent); const options = u.queryChildren(field, 'option').map(option => { - const value = get(option.querySelector('value'), 'textContent'); + const value = option.querySelector('value')?.textContent; return tpl_select_option({ 'value': value, 'label': option.getAttribute('label'), @@ -607,13 +607,13 @@ u.xForm2webForm = function (field, stanza, options) { 'required': !!field.querySelector('required') }); } else if (field.getAttribute('type') === 'fixed') { - const text = get(field.querySelector('value'), 'textContent'); + const text = field.querySelector('value')?.textContent; return '

'+text+'

'; } else if (field.getAttribute('type') === 'jid-multi') { return tpl_form_textarea({ 'name': field.getAttribute('var'), 'label': field.getAttribute('label') || '', - 'value': get(field.querySelector('value'), 'textContent'), + 'value': field.querySelector('value')?.textContent, 'required': !!field.querySelector('required') }); } else if (field.getAttribute('type') === 'boolean') { @@ -621,13 +621,13 @@ u.xForm2webForm = function (field, stanza, options) { 'id': u.getUniqueId(), 'name': field.getAttribute('var'), 'label': field.getAttribute('label') || '', - 'checked': get(field.querySelector('value'), 'textContent') === "1" && 'checked="1"' || '', + 'checked': field.querySelector('value')?.textContent === "1" && 'checked="1"' || '', 'required': !!field.querySelector('required') }); } else if (field.getAttribute('var') === 'url') { return tpl_form_url({ 'label': field.getAttribute('label') || '', - 'value': get(field.querySelector('value'), 'textContent') + 'value': field.querySelector('value')?.textContent }); } else if (field.getAttribute('var') === 'username') { return tpl_form_username({ @@ -635,7 +635,7 @@ u.xForm2webForm = function (field, stanza, options) { 'name': field.getAttribute('var'), 'type': XFORM_TYPE_MAP[field.getAttribute('type')], 'label': field.getAttribute('label') || '', - 'value': get(field.querySelector('value'), 'textContent'), + 'value': field.querySelector('value')?.textContent, 'required': !!field.querySelector('required') }); } else if (field.getAttribute('var') === 'ocr') { // Captcha @@ -644,7 +644,7 @@ u.xForm2webForm = function (field, stanza, options) { return tpl_form_captcha({ 'label': field.getAttribute('label'), 'name': field.getAttribute('var'), - 'data': get(el, 'textContent'), + 'data': el?.textContent, 'type': uri.getAttribute('type'), 'required': !!field.querySelector('required') }); @@ -659,7 +659,7 @@ u.xForm2webForm = function (field, stanza, options) { 'placeholder': null, 'required': !!field.querySelector('required'), 'type': XFORM_TYPE_MAP[field.getAttribute('type')], - 'value': get(field.querySelector('value'), 'textContent') + 'value': field.querySelector('value')?.textContent }); } }