Bläddra i källkod

Move functions out of src/headless/core.js into utils

JC Brand 2 år sedan
förälder
incheckning
7539fc1a6f

+ 10 - 87
src/headless/core.js

@@ -3,28 +3,27 @@
  * @license Mozilla Public License (MPLv2)
  */
 import URI from 'urijs';
-import _converse from '@converse/headless/shared/_converse';
+import _converse from './shared/_converse';
 import advancedFormat from 'dayjs/plugin/advancedFormat';
-import connection_api from '@converse/headless/shared/connection/api.js';
+import connection_api from './shared/connection/api.js';
 import dayjs from 'dayjs';
-import i18n from '@converse/headless/shared/i18n';
+import i18n from './shared/i18n';
 import invoke from 'lodash-es/invoke';
 import isFunction from 'lodash-es/isFunction';
-import log from '@converse/headless/log.js';
+import log from './log.js';
 import pluggable from 'pluggable.js/src/pluggable.js';
 import sizzle from 'sizzle';
-import u, { setUnloadEvent, replacePromise } from '@converse/headless/utils/core.js';
+import u, { setUnloadEvent, replacePromise } from './utils/core.js';
 import { CHAT_STATES, KEYCODES } from './shared/constants.js';
 import { Collection } from "@converse/skeletor/src/collection";
-import { Connection, MockConnection } from '@converse/headless/shared/connection/index.js';
 import { Events } from '@converse/skeletor/src/events.js';
 import { Model } from '@converse/skeletor/src/model.js';
 import { Strophe, $build, $iq, $msg, $pres } from 'strophe.js/src/strophe';
-import { TimeoutError } from '@converse/headless/shared/errors';
+import { TimeoutError } from './shared/errors';
 import { getOpenPromise } from '@converse/openpromise';
 import { html } from 'lit';
-import { initAppSettings } from '@converse/headless/shared/settings/utils.js';
-import { settings_api, user_settings_api } from '@converse/headless/shared/settings/api.js';
+import { initAppSettings } from './shared/settings/utils.js';
+import { settings_api, user_settings_api } from './shared/settings/api.js';
 import { sprintf } from 'sprintf-js';
 
 export { _converse };
@@ -33,8 +32,8 @@ export { i18n };
 import {
     attemptNonPreboundSession,
     cleanup,
-    getConnectionServiceURL,
     initClientConfig,
+    initConnection,
     initPlugins,
     initSessionStorage,
     registerGlobalEventHandlers,
@@ -203,7 +202,7 @@ export const api = _converse.api = {
         async login (jid, password, automatic=false) {
             jid = jid || api.settings.get('jid');
             if (!_converse.connection?.jid || (jid && !u.isSameDomain(_converse.connection.jid, jid))) {
-                await _converse.initConnection();
+                initConnection();
             }
             if (api.settings.get("connection_options")?.worker && (await _converse.connection.restoreWorkerSession())) {
                 return;
@@ -487,82 +486,6 @@ _converse.shouldClearCache = () => (
 );
 
 
-_converse.initConnection = function () {
-    const api = _converse.api;
-
-    if (! api.settings.get('bosh_service_url')) {
-        if (api.settings.get("authentication") === _converse.PREBIND) {
-            throw new Error("authentication is set to 'prebind' but we don't have a BOSH connection");
-        }
-    }
-
-    const XMPPConnection = _converse.isTestEnv() ? MockConnection : Connection;
-    _converse.connection = new XMPPConnection(
-        getConnectionServiceURL(),
-        Object.assign(
-            _converse.default_connection_options,
-            api.settings.get("connection_options"),
-            {'keepalive': api.settings.get("keepalive")}
-        )
-    );
-
-    setUpXMLLogging();
-    /**
-     * Triggered once the `Connection` constructor has been initialized, which
-     * will be responsible for managing the connection to the XMPP server.
-     *
-     * @event _converse#connectionInitialized
-     */
-    api.trigger('connectionInitialized');
-}
-
-
-function setUpXMLLogging () {
-    const lmap = {}
-    lmap[Strophe.LogLevel.DEBUG] = 'debug';
-    lmap[Strophe.LogLevel.INFO] = 'info';
-    lmap[Strophe.LogLevel.WARN] = 'warn';
-    lmap[Strophe.LogLevel.ERROR] = 'error';
-    lmap[Strophe.LogLevel.FATAL] = 'fatal';
-
-    Strophe.log = (level, msg) => log.log(msg, lmap[level]);
-    Strophe.error = (msg) => log.error(msg);
-
-    _converse.connection.xmlInput = body => log.debug(body.outerHTML, 'color: darkgoldenrod');
-    _converse.connection.xmlOutput = body => log.debug(body.outerHTML, 'color: darkcyan');
-}
-
-_converse.saveWindowState = function (ev) {
-    // XXX: eventually we should be able to just use
-    // document.visibilityState (when we drop support for older
-    // browsers).
-    let state;
-    const event_map = {
-        'focus': "visible",
-        'focusin': "visible",
-        'pageshow': "visible",
-        'blur': "hidden",
-        'focusout': "hidden",
-        'pagehide': "hidden"
-    };
-    ev = ev || document.createEvent('Events');
-    if (ev.type in event_map) {
-        state = event_map[ev.type];
-    } else {
-        state = document.hidden ? "hidden" : "visible";
-    }
-    _converse.windowState = state;
-    /**
-        * Triggered when window state has changed.
-        * Used to determine when a user left the page and when came back.
-        * @event _converse#windowStateChanged
-        * @type { object }
-        * @property{ string } state - Either "hidden" or "visible"
-        * @example _converse.api.listen.on('windowStateChanged', obj => { ... });
-        */
-    api.trigger('windowStateChanged', {state});
-}
-
 _converse.ConnectionFeedback = Model.extend({
     defaults: {
         'connection_status': Strophe.Status.DISCONNECTED,

+ 6 - 6
src/headless/shared/_converse.js

@@ -1,10 +1,10 @@
-import i18n from '@converse/headless/shared/i18n';
-import log from '@converse/headless/log';
-import { CONNECTION_STATUS } from '@converse/headless/shared/constants';
+import i18n from './i18n.js';
+import log from '../log.js';
+import { CONNECTION_STATUS } from './constants';
 import { Router } from '@converse/skeletor/src/router.js';
-import { TimeoutError } from '@converse/headless/shared/errors';
-import { createStore, getDefaultStore } from '@converse/headless/utils/storage.js';
-import { getInitSettings } from '@converse/headless/shared/settings/utils.js';
+import { TimeoutError } from './errors.js';
+import { createStore, getDefaultStore } from '../utils/storage.js';
+import { getInitSettings } from './settings/utils.js';
 import { getOpenPromise } from '@converse/openpromise';
 
 

+ 0 - 1
src/headless/shared/errors.js

@@ -1,4 +1,3 @@
-
 /**
  * Custom error for indicating timeouts
  * @namespace _converse

+ 38 - 1
src/headless/utils/core.js

@@ -41,6 +41,7 @@ export function isUniView () {
     return ['mobile', 'fullscreen', 'embedded'].includes(settings_api.get("view_mode"));
 }
 
+
 export async function tearDown () {
     await _converse.api.trigger('beforeTearDown', {'synchronous': true});
     window.removeEventListener('click', _converse.onUserActivity);
@@ -83,7 +84,6 @@ export function prefixMentions (message) {
 }
 
 
-
 /**
  * The utils object
  * @namespace u
@@ -541,6 +541,7 @@ u.waitUntil = function (func, max_wait=300, check_delay=3) {
     return promise;
 };
 
+
 export function setUnloadEvent () {
     if ('onpagehide' in window) {
         // Pagehide gets thrown in more cases than unload. Specifically it
@@ -555,6 +556,7 @@ export function setUnloadEvent () {
     }
 }
 
+
 export function replacePromise (name) {
     const existing_promise = _converse.promises[name];
     if (!existing_promise) {
@@ -569,6 +571,7 @@ export function replacePromise (name) {
     }
 }
 
+
 const element = document.createElement('div');
 
 export function decodeHTMLEntities (str) {
@@ -580,6 +583,39 @@ export function decodeHTMLEntities (str) {
     return str;
 }
 
+
+export function saveWindowState (ev) {
+    // XXX: eventually we should be able to just use
+    // document.visibilityState (when we drop support for older
+    // browsers).
+    let state;
+    const event_map = {
+        'focus': "visible",
+        'focusin': "visible",
+        'pageshow': "visible",
+        'blur': "hidden",
+        'focusout': "hidden",
+        'pagehide': "hidden"
+    };
+    ev = ev || document.createEvent('Events');
+    if (ev.type in event_map) {
+        state = event_map[ev.type];
+    } else {
+        state = document.hidden ? "hidden" : "visible";
+    }
+    _converse.windowState = state;
+    /**
+     * Triggered when window state has changed.
+     * Used to determine when a user left the page and when came back.
+     * @event _converse#windowStateChanged
+     * @type { object }
+     * @property{ string } state - Either "hidden" or "visible"
+     * @example _converse.api.listen.on('windowStateChanged', obj => { ... });
+     */
+    _converse.api.trigger('windowStateChanged', {state});
+}
+
+
 export default Object.assign({
     getRandomInt,
     getUniqueId,
@@ -587,6 +623,7 @@ export default Object.assign({
     isValidJID,
     merge,
     prefixMentions,
+    saveWindowState,
     stx,
     toStanza,
 }, u);

+ 70 - 21
src/headless/utils/init.js

@@ -1,15 +1,72 @@
 import Storage from '@converse/skeletor/src/storage.js';
-import _converse from '@converse/headless/shared/_converse';
+import _converse from '../shared/_converse';
 import debounce from 'lodash-es/debounce';
 import localDriver from 'localforage-webextensionstorage-driver/local';
-import log from '@converse/headless/log';
+import log from '../log.js';
 import syncDriver from 'localforage-webextensionstorage-driver/sync';
-import { CORE_PLUGINS } from '@converse/headless/shared/constants.js';
-import { Connection } from '@converse/headless/shared/connection/index.js';
+import { CORE_PLUGINS } from '../shared/constants.js';
+import { Connection, MockConnection } from '../shared/connection/index.js';
 import { Model } from '@converse/skeletor/src/model.js';
 import { Strophe } from 'strophe.js/src/strophe';
-import { createStore, initStorage } from '@converse/headless/utils/storage.js';
-import { isValidJID } from './core.js';
+import { createStore, initStorage } from './storage.js';
+import { saveWindowState, isValidJID } from './core.js';
+
+
+function setUpXMLLogging () {
+    const lmap = {}
+    lmap[Strophe.LogLevel.DEBUG] = 'debug';
+    lmap[Strophe.LogLevel.INFO] = 'info';
+    lmap[Strophe.LogLevel.WARN] = 'warn';
+    lmap[Strophe.LogLevel.ERROR] = 'error';
+    lmap[Strophe.LogLevel.FATAL] = 'fatal';
+
+    Strophe.log = (level, msg) => log.log(msg, lmap[level]);
+    Strophe.error = (msg) => log.error(msg);
+
+    _converse.connection.xmlInput = body => log.debug(body.outerHTML, 'color: darkgoldenrod');
+    _converse.connection.xmlOutput = body => log.debug(body.outerHTML, 'color: darkcyan');
+}
+
+
+function getConnectionServiceURL () {
+    const { api } = _converse;
+    if (('WebSocket' in window || 'MozWebSocket' in window) && api.settings.get("websocket_url")) {
+        return api.settings.get('websocket_url');
+    } else if (api.settings.get('bosh_service_url')) {
+        return api.settings.get('bosh_service_url');
+    }
+    return '';
+}
+
+
+export function initConnection () {
+    const api = _converse.api;
+
+    if (! api.settings.get('bosh_service_url')) {
+        if (api.settings.get("authentication") === _converse.PREBIND) {
+            throw new Error("authentication is set to 'prebind' but we don't have a BOSH connection");
+        }
+    }
+
+    const XMPPConnection = _converse.isTestEnv() ? MockConnection : Connection;
+    _converse.connection = new XMPPConnection(
+        getConnectionServiceURL(),
+        Object.assign(
+            _converse.default_connection_options,
+            api.settings.get("connection_options"),
+            {'keepalive': api.settings.get("keepalive")}
+        )
+    );
+
+    setUpXMLLogging();
+    /**
+     * Triggered once the `Connection` constructor has been initialized, which
+     * will be responsible for managing the connection to the XMPP server.
+     *
+     * @event _converse#connectionInitialized
+     */
+    api.trigger('connectionInitialized');
+}
 
 
 export function initPlugins (_converse) {
@@ -54,6 +111,7 @@ export function initPlugins (_converse) {
     _converse.api.trigger('pluginsInitialized');
 }
 
+
 export async function initClientConfig (_converse) {
     /* The client config refers to configuration of the client which is
      * independent of any particular user.
@@ -76,6 +134,7 @@ export async function initClientConfig (_converse) {
     _converse.api.trigger('clientConfigInitialized');
 }
 
+
 export async function initSessionStorage (_converse) {
     await Storage.sessionStorageInitialized;
     _converse.storage = {
@@ -87,6 +146,7 @@ export async function initSessionStorage (_converse) {
     };
 }
 
+
 function initPersistentStorage (_converse, store_name) {
     if (_converse.api.settings.get('persistent_store') === 'sessionStorage') {
         return;
@@ -151,7 +211,7 @@ function saveJIDtoSession (_converse, jid) {
  *
  * Given that we can only create an XMPP connection if we know the domain of
  * the server connect to and we only know this once we know the JID, we also
- * call {@link _converse.initConnection } (if necessary) to make sure that the
+ * call {@link initConnection } (if necessary) to make sure that the
  * connection is set up.
  *
  * @emits _converse#setUserJID
@@ -206,8 +266,8 @@ export async function initSession (_converse, jid) {
 
 
 export function registerGlobalEventHandlers (_converse) {
-    document.addEventListener("visibilitychange", _converse.saveWindowState);
-    _converse.saveWindowState({'type': document.hidden ? "blur" : "focus"}); // Set initial state
+    document.addEventListener("visibilitychange", saveWindowState);
+    saveWindowState({'type': document.hidden ? "blur" : "focus"}); // Set initial state
     /**
      * Called once Converse has registered its global event handlers
      * (for events such as window resize or unload).
@@ -222,7 +282,7 @@ export function registerGlobalEventHandlers (_converse) {
 
 function unregisterGlobalEventHandlers (_converse) {
     const { api } = _converse;
-    document.removeEventListener("visibilitychange", _converse.saveWindowState);
+    document.removeEventListener("visibilitychange", saveWindowState);
     api.trigger('unregisteredGlobalEventHandlers');
 }
 
@@ -365,17 +425,6 @@ export async function attemptNonPreboundSession (credentials, automatic) {
 }
 
 
-export function getConnectionServiceURL () {
-    const { api } = _converse;
-    if (('WebSocket' in window || 'MozWebSocket' in window) && api.settings.get("websocket_url")) {
-        return api.settings.get('websocket_url');
-    } else if (api.settings.get('bosh_service_url')) {
-        return api.settings.get('bosh_service_url');
-    }
-    return '';
-}
-
-
 /**
  * Fetch the stored SCRAM keys for the given JID, if available.
  *

+ 2 - 2
src/plugins/chatview/tests/unreads.js

@@ -105,7 +105,7 @@ describe("A ChatBox's Unread Message Count", function () {
         expect(chatbox.get('first_unread_id')).toBe(msgid);
         await u.waitUntil(() => sent_stanzas.filter(s => s.nodeName === 'message').length === 1);
         expect(sent_stanzas[0].querySelector('received')).toBeDefined();
-        _converse.saveWindowState({'type': 'focus'});
+        u.saveWindowState({'type': 'focus'});
         await u.waitUntil(() => sent_stanzas.filter(s => s.nodeName === 'message').length === 2);
         expect(sent_stanzas[1].querySelector('displayed')).toBeDefined();
         expect(chatbox.get('num_unread')).toBe(0);
@@ -148,7 +148,7 @@ describe("A ChatBox's Unread Message Count", function () {
         expect(chatbox.get('first_unread_id')).toBe(msgid);
         await u.waitUntil(() => sent_stanzas.filter(s => s.nodeName === 'message').length === 1);
         expect(sent_stanzas[0].querySelector('received')).toBeDefined();
-        _converse.saveWindowState({'type': 'focus'});
+        u.saveWindowState({'type': 'focus'});
         await u.waitUntil(() => chatbox.get('num_unread') === 1);
         expect(chatbox.get('first_unread_id')).toBe(msgid);
         expect(sent_stanzas[0].querySelector('received')).toBeDefined();

+ 4 - 3
src/plugins/controlbox/loginform.js

@@ -1,7 +1,8 @@
 import bootstrap from 'bootstrap.native';
 import tpl_login_panel from './templates/loginform.js';
 import { CustomElement } from 'shared/components/element.js';
-import { _converse, api, converse } from '@converse/headless/core';
+import { _converse, api, converse } from '@converse/headless/core.js';
+import { initConnection } from '@converse/headless/utils/init.js';
 import { updateSettingsWithFormData, validateJID } from './utils.js';
 
 const { Strophe, u } = converse.env;
@@ -60,7 +61,7 @@ class LoginForm extends CustomElement {
     }
 
     // eslint-disable-next-line class-methods-use-this
-    async discoverConnectionMethods (ev) {
+    discoverConnectionMethods (ev) {
         if (!api.settings.get("discover_connection_methods")) {
             return;
         }
@@ -68,7 +69,7 @@ class LoginForm extends CustomElement {
         const jid = form_data.get('jid');
         const domain = Strophe.getDomainFromJid(jid);
         if (!_converse.connection?.jid || (jid && !u.isSameDomain(_converse.connection.jid, jid))) {
-            await _converse.initConnection();
+            initConnection();
         }
         return _converse.connection.discoverConnectionMethods(domain);
     }

+ 3 - 3
src/plugins/notifications/tests/notification.js

@@ -239,7 +239,7 @@ describe("Notifications", function () {
 
             // Check that it's cleared when the window is focused
             _converse.windowState = 'hidden';
-            _converse.saveWindowState({'type': 'focus'});
+            u.saveWindowState({'type': 'focus'});
             await u.waitUntil(() => favico.badge.calls.count() === 2);
             expect(favico.badge.calls.mostRecent().args.pop()).toBe(0);
 
@@ -256,7 +256,7 @@ describe("Notifications", function () {
             const favico = jasmine.createSpyObj('favico', ['badge']);
             spyOn(converse.env, 'Favico').and.returnValue(favico);
 
-            _converse.saveWindowState({'type': 'focus'});
+            u.saveWindowState({'type': 'focus'});
             const message = 'This message will not increment the message counter';
             const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit',
                 msg = $msg({
@@ -305,7 +305,7 @@ describe("Notifications", function () {
             expect(view.model.get('num_unread')).toBe(1);
 
             // come back to converse-chat page
-            _converse.saveWindowState({'type': 'focus'});
+            u.saveWindowState({'type': 'focus'});
 
 
             await u.waitUntil(() => u.isVisible(view));

+ 4 - 3
src/plugins/register/panel.js

@@ -8,7 +8,8 @@ import tpl_spinner from "templates/spinner.js";
 import utils from "@converse/headless/utils/form";
 import { ElementView } from "@converse/skeletor/src/element";
 import { __ } from 'i18n';
-import { _converse, api, converse } from "@converse/headless/core";
+import { _converse, api, converse } from "@converse/headless/core.js";
+import { initConnection } from '@converse/headless/utils/init.js';
 import { render } from 'lit';
 
 // Strophe methods for building stanzas
@@ -211,13 +212,13 @@ class RegisterPanel extends ElementView {
      * @method _converse.RegisterPanel#fetchRegistrationForm
      * @param { String } domain_name - XMPP server domain
      */
-    async fetchRegistrationForm (domain_name) {
+    fetchRegistrationForm (domain_name) {
         this.model.set('registration_status', FETCHING_FORM);
         this.reset({
             'domain': Strophe.getDomainFromJid(domain_name),
             '_registering': true
         });
-        await _converse.initConnection(this.domain);
+        initConnection(this.domain);
         // When testing, the test tears down before the async function
         // above finishes. So we use optional chaining here
         _converse.connection?.connect(this.domain, "", status => this.onConnectStatusChanged(status));