Bladeren bron

Use optional chaining instead of lodash.get

JC Brand 5 jaren geleden
bovenliggende
commit
967154d314

+ 9 - 8
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);
             },

+ 5 - 5
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);

+ 5 - 6
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;
                }

+ 2 - 2
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');
                 }

+ 2 - 2
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);
             },

+ 7 - 6
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 ************************/

+ 9 - 13
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
                 });
             },
 

+ 1 - 2
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;
             }

+ 3 - 3
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();

+ 6 - 5
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) {

+ 5 - 5
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");

+ 1 - 2
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
                     });
                 });
             },

+ 7 - 7
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();
                         }));
                     }

+ 5 - 5
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;
         },
 
         /**

+ 3 - 3
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')
                     });
                 });

+ 14 - 14
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 <x/> 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});

+ 5 - 5
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',

+ 3 - 3
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;

+ 9 - 9
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) {

+ 5 - 5
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);
 
 

+ 6 - 6
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 {};

+ 10 - 10
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 '<p class="form-help">'+text+'</p>';
     } 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
         });
     }
 }