Browse Source

Update to latest Skeletor

- Fix Skeletor import paths so that we have type definitions
- Fix more type errors
JC Brand 1 year ago
parent
commit
2238339836
56 changed files with 130 additions and 102 deletions
  1. 3 3
      package-lock.json
  2. 3 3
      src/headless/log.js
  3. 1 1
      src/headless/package.json
  4. 1 1
      src/headless/plugins/adhoc/api.js
  5. 7 11
      src/headless/plugins/bookmarks/collection.js
  6. 5 3
      src/headless/plugins/bookmarks/index.js
  7. 1 1
      src/headless/plugins/bookmarks/model.js
  8. 8 5
      src/headless/plugins/bookmarks/utils.js
  9. 21 17
      src/headless/plugins/bosh.js
  10. 1 1
      src/headless/plugins/caps/tests/caps.js
  11. 1 1
      src/headless/plugins/chat/messages.js
  12. 1 1
      src/headless/plugins/chat/model.js
  13. 1 1
      src/headless/plugins/chat/utils.js
  14. 1 1
      src/headless/plugins/chatboxes/chatboxes.js
  15. 1 1
      src/headless/plugins/disco/entities.js
  16. 2 2
      src/headless/plugins/disco/entity.js
  17. 1 1
      src/headless/plugins/disco/utils.js
  18. 1 1
      src/headless/plugins/emoji/index.js
  19. 1 1
      src/headless/plugins/mam/placeholder.js
  20. 1 1
      src/headless/plugins/muc/messages.js
  21. 1 1
      src/headless/plugins/muc/muc.js
  22. 1 1
      src/headless/plugins/muc/occupant.js
  23. 2 2
      src/headless/plugins/muc/occupants.js
  24. 1 1
      src/headless/plugins/roster/contact.js
  25. 2 2
      src/headless/plugins/roster/contacts.js
  26. 1 1
      src/headless/plugins/roster/filter.js
  27. 1 1
      src/headless/plugins/roster/presence.js
  28. 1 1
      src/headless/plugins/roster/presences.js
  29. 1 1
      src/headless/plugins/roster/resource.js
  30. 1 1
      src/headless/plugins/roster/resources.js
  31. 1 1
      src/headless/plugins/roster/utils.js
  32. 1 1
      src/headless/plugins/status/status.js
  33. 1 1
      src/headless/plugins/vcard/vcard.js
  34. 1 1
      src/headless/plugins/vcard/vcards.js
  35. 21 4
      src/headless/shared/_converse.js
  36. 2 2
      src/headless/shared/api/public.js
  37. 1 1
      src/headless/shared/connection/feedback.js
  38. 1 1
      src/headless/shared/settings/utils.js
  39. 1 1
      src/headless/utils/index.js
  40. 5 2
      src/headless/utils/init.js
  41. 1 2
      src/headless/utils/session.js
  42. 1 1
      src/plugins/bookmark-views/components/bookmarks-list.js
  43. 3 2
      src/plugins/bookmark-views/mixins.js
  44. 4 1
      src/plugins/chatview/tests/styling.js
  45. 1 1
      src/plugins/controlbox/model.js
  46. 1 1
      src/plugins/minimize/toggle.js
  47. 1 1
      src/plugins/modal/api.js
  48. 1 1
      src/plugins/muc-views/heading.js
  49. 1 1
      src/plugins/muc-views/modals/occupant.js
  50. 1 1
      src/plugins/omemo/device.js
  51. 1 1
      src/plugins/omemo/devicelist.js
  52. 1 1
      src/plugins/omemo/devicelists.js
  53. 1 1
      src/plugins/omemo/devices.js
  54. 1 1
      src/plugins/omemo/store.js
  55. 1 1
      src/plugins/roomslist/model.js
  56. 1 1
      src/plugins/rosterview/rosterview.js

+ 3 - 3
package-lock.json

@@ -1834,8 +1834,8 @@
     },
     "node_modules/@converse/skeletor": {
       "version": "0.0.8",
-      "resolved": "git+ssh://git@github.com/conversejs/skeletor.git#dc5acf92369fffef548252d5ba2e9ba754fa262c",
-      "integrity": "sha512-z6ghozaR2H9BqPyHe5NK5By4G6zUaN1vWhHbtjP7FAM5Y0+PReB8Xhw3VJpp9S8PLw6VI9xMP68VaUfixt7Uiw==",
+      "resolved": "git+ssh://git@github.com/conversejs/skeletor.git#81b33ecd868b597a0c8b108ab8e3c9c77a5d9d05",
+      "integrity": "sha512-5miToCgbGuNKCa/4ui4dtB4Z67OKsyQhqkhx2rh7jYGZTOCbmCehOYnKQVn2TI9DitcI/8dl6G5OvEJfL7y3AQ==",
       "license": "MIT",
       "dependencies": {
         "@converse/localforage-getitems": "1.4.3",
@@ -11419,7 +11419,7 @@
       "license": "MPL-2.0",
       "dependencies": {
         "@converse/openpromise": "^0.0.1",
-        "@converse/skeletor": "conversejs/skeletor#dc5acf92369fffef548252d5ba2e9ba754fa262c",
+        "@converse/skeletor": "conversejs/skeletor#81b33ecd868b597a0c8b108ab8e3c9c77a5d9d05",
         "dayjs": "^1.11.8",
         "dompurify": "^2.3.1",
         "filesize": "^10.0.7",

+ 3 - 3
src/headless/log.js

@@ -43,8 +43,8 @@ export default {
      * When using the 'error' or 'warn' loglevels, a full stacktrace will be
      * logged as well.
      * @method log#log
-     * @param { string | Error } message - The message to be logged
-     * @param { string } level - The loglevel which allows for filtering of log messages
+     * @param {string|Element|Error} message - The message to be logged
+     * @param {string} level - The loglevel which allows for filtering of log messages
      */
     log (message, level, style='') {
         if (LEVELS[level] < LEVELS[this.loglevel]) {
@@ -59,7 +59,7 @@ export default {
         if (message instanceof Error) {
             message = message.stack;
         } else if (isElement(message)) {
-            message = message.outerHTML;
+            message = /** @type {Element} */(message).outerHTML;
         }
         const prefix = style ? '%c' : '';
         if (level === 'error') {

+ 1 - 1
src/headless/package.json

@@ -32,7 +32,7 @@
   },
   "dependencies": {
     "@converse/openpromise": "^0.0.1",
-    "@converse/skeletor": "conversejs/skeletor#dc5acf92369fffef548252d5ba2e9ba754fa262c",
+    "@converse/skeletor": "conversejs/skeletor#81b33ecd868b597a0c8b108ab8e3c9c77a5d9d05",
     "dayjs": "^1.11.8",
     "dompurify": "^2.3.1",
     "filesize": "^10.0.7",

+ 1 - 1
src/headless/plugins/adhoc/api.js

@@ -72,7 +72,7 @@ export default {
          * @param { String } sessionid
          * @param { 'execute' | 'cancel' | 'prev' | 'next' | 'complete' } action
          * @param { String } node
-         * @param { Array<{ string: string }> } inputs
+         * @param { Array<{ [k:string]: string }> } inputs
          */
         async runCommand (jid, sessionid, node, action, inputs) {
             const iq =

+ 7 - 11
src/headless/plugins/bookmarks/collection.js

@@ -3,7 +3,7 @@ import Bookmark from './model.js';
 import _converse from '../../shared/_converse.js';
 import api, { converse } from '../../shared/api/index.js';
 import log from "../../log.js";
-import { Collection } from "@converse/skeletor/src/collection.js";
+import { Collection } from "@converse/skeletor";
 import { getOpenPromise } from '@converse/openpromise';
 import { initStorage } from '../../utils/storage.js';
 
@@ -13,15 +13,10 @@ const { Strophe, $iq, sizzle } = converse.env;
 class Bookmarks extends Collection {
 
     constructor () {
-        super();
+        super([], { comparator: (/** @type {Bookmark} */b) => b.get('name').toLowerCase() });
         this.model = Bookmark;
     }
 
-    // eslint-disable-next-line class-methods-use-this
-    comparator (item) {
-        return item.get('name').toLowerCase();
-    }
-
     async initialize () {
         this.on('add', bm => this.openBookmarkedRoom(bm)
             .then(bm => this.markRoomAsBookmarked(bm))
@@ -31,7 +26,8 @@ class Bookmarks extends Collection {
         this.on('remove', this.markRoomAsUnbookmarked, this);
         this.on('remove', this.sendBookmarkStanza, this);
 
-        const cache_key = `converse.room-bookmarks${_converse.bare_jid}`;
+        const { session } = _converse;
+        const cache_key = `converse.room-bookmarks${session.get('bare_jid')}`;
         this.fetched_flag = cache_key+'fetched';
         initStorage(this, cache_key);
 
@@ -41,7 +37,7 @@ class Bookmarks extends Collection {
          * Triggered once the _converse.Bookmarks collection
          * has been created and cached bookmarks have been fetched.
          * @event _converse#bookmarksInitialized
-         * @type { _converse.Bookmarks }
+         * @type { Bookmarks }
          * @example _converse.api.listen.on('bookmarksInitialized', (bookmarks) => { ... });
          */
         api.trigger('bookmarksInitialized', this);
@@ -157,7 +153,7 @@ class Bookmarks extends Collection {
 
     onBookmarksReceived (deferred, iq) {
         this.createBookmarksFromStanza(iq);
-        window.sessionStorage.setItem(this.fetched_flag, true);
+        window.sessionStorage.setItem(this.fetched_flag, 'true');
         if (deferred !== undefined) {
             return deferred.resolve();
         }
@@ -174,7 +170,7 @@ class Bookmarks extends Collection {
         } else if (deferred) {
             if (iq.querySelector('error[type="cancel"] item-not-found')) {
                 // Not an exception, the user simply doesn't have any bookmarks.
-                window.sessionStorage.setItem(this.fetched_flag, true);
+                window.sessionStorage.setItem(this.fetched_flag, 'true');
                 return deferred.resolve();
             } else {
                 log.error('Error while fetching bookmarks');

+ 5 - 3
src/headless/plugins/bookmarks/index.js

@@ -53,8 +53,9 @@ converse.plugins.add('converse-bookmarks', {
 
         api.promises.add('bookmarksInitialized');
 
-        _converse.Bookmark = Bookmark;
-        _converse.Bookmarks = Bookmarks;
+        const exports  = { Bookmark, Bookmarks };
+        Object.assign(_converse, exports); // TODO: DEPRECATED
+        Object.assign(_converse.exports, exports);
 
         api.listen.on('addClientFeatures', () => {
             if (api.settings.get('allow_bookmarks')) {
@@ -72,7 +73,8 @@ converse.plugins.add('converse-bookmarks', {
 
         api.listen.on('connected', async () =>  {
             // Add a handler for bookmarks pushed from other connected clients
-            api.connection.get().addHandler(handleBookmarksPush, null, 'message', 'headline', null, _converse.bare_jid);
+            const bare_jid = _converse.session.get('bare_jid');
+            api.connection.get().addHandler(handleBookmarksPush, null, 'message', 'headline', null, bare_jid);
             await Promise.all([api.waitUntil('chatBoxesFetched')]);
             initBookmarks();
         });

+ 1 - 1
src/headless/plugins/bookmarks/model.js

@@ -1,5 +1,5 @@
 import { converse } from '../../shared/api/index.js';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 
 const { Strophe } = converse.env;
 

+ 8 - 5
src/headless/plugins/bookmarks/utils.js

@@ -5,11 +5,12 @@ import log from "../../log.js";
 const { Strophe, sizzle } = converse.env;
 
 export async function checkBookmarksSupport () {
-    const identity = await api.disco.getIdentity('pubsub', 'pep', _converse.bare_jid);
+    const bare_jid = _converse.session.get('bare_jid');
+    const identity = await api.disco.getIdentity('pubsub', 'pep', bare_jid);
     if (api.settings.get('allow_public_bookmarks')) {
         return !!identity;
     } else {
-        return api.disco.supports(Strophe.NS.PUBSUB + '#publish-options', _converse.bare_jid);
+        return api.disco.supports(Strophe.NS.PUBSUB + '#publish-options', bare_jid);
     }
 }
 
@@ -18,7 +19,9 @@ export async function initBookmarks () {
         return;
     }
     if (await checkBookmarksSupport()) {
-        _converse.bookmarks = new _converse.Bookmarks();
+        _converse.state.bookmarks = new _converse.exports.Bookmarks();
+        // TODO: DEPRECATED
+        _converse.bookmarks = _converse.state.bookmarks;
     }
 }
 
@@ -26,13 +29,13 @@ export function getNicknameFromBookmark (jid) {
     if (!api.settings.get('allow_bookmarks')) {
         return null;
     }
-    return _converse.bookmarks?.get(jid)?.get('nick');
+    return _converse.state.bookmarks?.get(jid)?.get('nick');
 }
 
 export function handleBookmarksPush (message) {
     if (sizzle(`event[xmlns="${Strophe.NS.PUBSUB}#event"] items[node="${Strophe.NS.BOOKMARKS}"]`, message).length) {
         api.waitUntil('bookmarksInitialized')
-            .then(() => _converse.bookmarks.createBookmarksFromStanza(message))
+            .then(() => _converse.state.bookmarks.createBookmarksFromStanza(message))
             .catch(e => log.fatal(e));
     }
     return true;

+ 21 - 17
src/headless/plugins/bosh.js

@@ -8,7 +8,7 @@ import _converse from '../shared/_converse.js';
 import api, { converse } from '../shared/api/index.js';
 import log from "../log.js";
 import { BOSH_WAIT } from '../shared/constants.js';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { setUserJID, } from '../utils/init.js';
 import { isTestEnv } from '../utils/session.js';
 import { createStore } from '../utils/storage.js';
@@ -17,6 +17,8 @@ const { Strophe } = converse.env;
 
 const BOSH_SESSION_ID = 'converse.bosh-session';
 
+let bosh_session;
+
 
 converse.plugins.add('converse-bosh', {
 
@@ -33,22 +35,24 @@ converse.plugins.add('converse-bosh', {
 
         async function initBOSHSession () {
             const id = BOSH_SESSION_ID;
-            if (!_converse.bosh_session) {
-                _converse.bosh_session = new Model({id});
-                _converse.bosh_session.browserStorage = createStore(id, "session");
-                await new Promise(resolve => _converse.bosh_session.fetch({'success': resolve, 'error': resolve}));
+            if (!bosh_session) {
+                bosh_session = new Model({id});
+                bosh_session.browserStorage = createStore(id, "session");
+                await new Promise(resolve => bosh_session.fetch({'success': resolve, 'error': resolve}));
             }
-            if (_converse.jid) {
-                if (_converse.bosh_session.get('jid') !== _converse.jid) {
-                    const jid = await setUserJID(_converse.jid);
-                    _converse.bosh_session.clear({'silent': true });
-                    _converse.bosh_session.save({jid});
+
+            let jid = _converse.session.get('jid');
+            if (jid) {
+                if (bosh_session.get('jid') !== jid) {
+                    jid = await setUserJID(jid);
+                    bosh_session.clear({'silent': true });
+                    bosh_session.save({jid});
                 }
             } else { // Keepalive
-                const jid = _converse.bosh_session.get('jid');
+                const jid = bosh_session.get('jid');
                 jid && await setUserJID(jid);
             }
-            return _converse.bosh_session;
+            return bosh_session;
         }
 
 
@@ -107,21 +111,21 @@ converse.plugins.add('converse-bosh', {
 
         /************************ BEGIN Event Handlers ************************/
         api.listen.on('clearSession', () => {
-            if (_converse.bosh_session === undefined) {
+            if (bosh_session === undefined) {
                 // Remove manually, even if we don't have the corresponding
                 // model, to avoid trying to reconnect to a stale BOSH session
                 const id = BOSH_SESSION_ID;
                 sessionStorage.removeItem(id);
                 sessionStorage.removeItem(`${id}-${id}`);
             } else {
-                _converse.bosh_session.destroy();
-                delete _converse.bosh_session;
+                bosh_session.destroy();
+                bosh_session = undefined;
             }
         });
 
         api.listen.on('setUserJID', () => {
-            if (_converse.bosh_session !== undefined) {
-                _converse.bosh_session.save({'jid': _converse.jid});
+            if (bosh_session !== undefined) {
+                bosh_session.save({'jid': _converse.session.get('jid')});
             }
         });
 

+ 1 - 1
src/headless/plugins/caps/tests/caps.js

@@ -8,7 +8,7 @@ describe("A sent presence stanza", function () {
     beforeEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = 7000));
     afterEach(() => (jasmine.DEFAULT_TIMEOUT_INTERVAL = original_timeout));
 
-    it("includes a entity capabilities node",
+    it("includes an entity capabilities node",
             mock.initConverse([], {}, async (_converse) => {
 
         await mock.waitForRoster(_converse, 'current', 0);

+ 1 - 1
src/headless/plugins/chat/messages.js

@@ -1,5 +1,5 @@
 import Message from './message.js';
-import { Collection } from '@converse/skeletor/src/collection';
+import { Collection } from '@converse/skeletor';
 
 class Messages extends Collection {
 

+ 1 - 1
src/headless/plugins/chat/model.js

@@ -11,7 +11,7 @@ import api, { converse } from '../../shared/api/index.js';
 import isMatch from "lodash-es/isMatch";
 import log from '../../log.js';
 import pick from "lodash-es/pick";
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { PRIVATE_CHAT_TYPE, COMPOSING, INACTIVE, PAUSED, GONE } from '@converse/headless/shared/constants.js';
 import { TimeoutError } from '../../shared/errors.js';
 import { debouncedPruneHistory, handleCorrection } from '../../shared/chat/utils.js';

+ 1 - 1
src/headless/plugins/chat/utils.js

@@ -1,5 +1,5 @@
 import sizzle from "sizzle";
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import _converse from '../../shared/_converse.js';
 import api, { converse } from '../../shared/api/index.js';
 import log from '../../log.js';

+ 1 - 1
src/headless/plugins/chatboxes/chatboxes.js

@@ -1,6 +1,6 @@
 import _converse from '../../shared/_converse.js';
 import api from '../../shared/api/index.js';
-import { Collection } from "@converse/skeletor/src/collection";
+import { Collection } from "@converse/skeletor";
 import { initStorage } from '../../utils/storage.js';
 
 class ChatBoxes extends Collection {

+ 1 - 1
src/headless/plugins/disco/entities.js

@@ -1,6 +1,6 @@
 import DiscoEntity from './entity.js';
 import log from "../../log.js";
-import { Collection } from "@converse/skeletor/src/collection";
+import { Collection } from "@converse/skeletor";
 
 
 class DiscoEntities extends Collection {

+ 2 - 2
src/headless/plugins/disco/entity.js

@@ -2,8 +2,8 @@ import _converse from '../../shared/_converse.js';
 import api, { converse } from '../../shared/api/index.js';
 import log from '../../log.js';
 import sizzle from 'sizzle';
-import { Collection } from '@converse/skeletor/src/collection';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Collection } from '@converse/skeletor';
+import { Model } from '@converse/skeletor';
 import { getOpenPromise } from '@converse/openpromise';
 import { createStore } from '../../utils/storage.js';
 

+ 1 - 1
src/headless/plugins/disco/utils.js

@@ -1,6 +1,6 @@
 import _converse from '../../shared/_converse.js';
 import api, { converse } from '../../shared/api/index.js';
-import { Collection } from "@converse/skeletor/src/collection";
+import { Collection } from "@converse/skeletor";
 import { createStore } from '../../utils/storage.js';
 
 const { Strophe, $iq } = converse.env;

+ 1 - 1
src/headless/plugins/emoji/index.js

@@ -6,7 +6,7 @@
 import './utils.js';
 import _converse from '../../shared/_converse.js';
 import api, { converse } from '../../shared/api/index.js';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { getOpenPromise } from '@converse/openpromise';
 
 

+ 1 - 1
src/headless/plugins/mam/placeholder.js

@@ -1,4 +1,4 @@
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { getUniqueId } from '../../utils/index.js';
 
 export default class MAMPlaceholderMessage extends Model {

+ 1 - 1
src/headless/plugins/muc/messages.js

@@ -1,5 +1,5 @@
 import MUCMessage from './message';
-import { Collection } from '@converse/skeletor/src/collection';
+import { Collection } from '@converse/skeletor';
 
 /**
  * Collection which stores MUC messages

+ 1 - 1
src/headless/plugins/muc/muc.js

@@ -11,7 +11,7 @@ import log from '../../log';
 import p from '../../utils/parse-helpers';
 import pick from 'lodash-es/pick';
 import sizzle from 'sizzle';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { ROOMSTATUS } from './constants.js';
 import { CHATROOMS_TYPE } from '../../shared/constants.js';
 import { Strophe, $build, $iq, $msg, $pres } from 'strophe.js';

+ 1 - 1
src/headless/plugins/muc/occupant.js

@@ -1,4 +1,4 @@
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 
 /**
  * Represents a participant in a MUC

+ 2 - 2
src/headless/plugins/muc/occupants.js

@@ -1,9 +1,9 @@
 import ChatRoomOccupant from './occupant.js';
 import _converse from '../../shared/_converse.js';
 import api, { converse } from '../../shared/api/index.js';
-import { Collection } from '@converse/skeletor/src/collection.js';
+import { Collection } from '@converse/skeletor';
 import { MUC_ROLE_WEIGHTS } from './constants.js';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { Strophe } from 'strophe.js';
 import { getAffiliationList } from './affiliations/utils.js';
 import { getAutoFetchedAffiliationLists } from './utils.js';

+ 1 - 1
src/headless/plugins/roster/contact.js

@@ -1,7 +1,7 @@
 import '../../plugins/status/api.js';
 import _converse from '../../shared/_converse.js';
 import api, { converse } from '../../shared/api/index.js';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { getOpenPromise } from '@converse/openpromise';
 import { rejectPresenceSubscription } from './utils.js';
 

+ 2 - 2
src/headless/plugins/roster/contacts.js

@@ -2,8 +2,8 @@ import RosterContact from './contact.js';
 import _converse from '../../shared/_converse.js';
 import api, { converse } from '../../shared/api/index.js';
 import log from "../../log.js";
-import { Collection } from "@converse/skeletor/src/collection";
-import { Model } from "@converse/skeletor/src/model";
+import { Collection } from "@converse/skeletor";
+import { Model } from "@converse/skeletor";
 import { initStorage } from '../../utils/storage.js';
 import { rejectPresenceSubscription } from './utils.js';
 

+ 1 - 1
src/headless/plugins/roster/filter.js

@@ -1,4 +1,4 @@
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 
 class RosterFilter extends Model {
     initialize () {

+ 1 - 1
src/headless/plugins/roster/presence.js

@@ -1,5 +1,5 @@
 import Resources from "./resources.js";
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { converse } from '../../shared/api/index.js';
 import { initStorage } from '../../utils/storage.js';
 

+ 1 - 1
src/headless/plugins/roster/presences.js

@@ -1,4 +1,4 @@
-import { Collection } from "@converse/skeletor/src/collection";
+import { Collection } from "@converse/skeletor";
 import Presence from "./presence.js";
 
 class Presences extends Collection {

+ 1 - 1
src/headless/plugins/roster/resource.js

@@ -1,4 +1,4 @@
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 
 class Resource extends Model {
     get idAttribute () { // eslint-disable-line class-methods-use-this

+ 1 - 1
src/headless/plugins/roster/resources.js

@@ -1,4 +1,4 @@
-import { Collection } from "@converse/skeletor/src/collection";
+import { Collection } from "@converse/skeletor";
 import Resource from "./resource";
 
 class Resources extends Collection {

+ 1 - 1
src/headless/plugins/roster/utils.js

@@ -2,7 +2,7 @@ import _converse from '../../shared/_converse.js';
 import api, { converse } from '../../shared/api/index.js';
 import log from "../../log.js";
 import { Strophe } from 'strophe.js';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { RosterFilter } from '../../plugins/roster/filter.js';
 import { STATUS_WEIGHTS, PRIVATE_CHAT_TYPE } from "../../shared/constants";
 import { initStorage } from '../../utils/storage.js';

+ 1 - 1
src/headless/plugins/status/status.js

@@ -1,6 +1,6 @@
 import _converse from '../../shared/_converse.js';
 import api, { converse } from '../../shared/api/index.js';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 
 const { Strophe, $pres } = converse.env;
 

+ 1 - 1
src/headless/plugins/vcard/vcard.js

@@ -1,5 +1,5 @@
 import _converse from '../../shared/_converse.js';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 
 /**
  * Represents a VCard

+ 1 - 1
src/headless/plugins/vcard/vcards.js

@@ -1,5 +1,5 @@
 import VCard from "./vcard";
-import { Collection } from "@converse/skeletor/src/collection";
+import { Collection } from "@converse/skeletor";
 import { api } from "../../index.js";
 
 class VCards extends Collection {

+ 21 - 4
src/headless/shared/_converse.js

@@ -3,7 +3,7 @@
  */
 import i18n from './i18n.js';
 import pluggable from 'pluggable.js/src/pluggable.js';
-import { EventEmitter } from '@converse/skeletor';
+import { EventEmitter, Model } from '@converse/skeletor';
 import { getOpenPromise } from '@converse/openpromise';
 
 import {
@@ -72,22 +72,39 @@ class ConversePrivateGlobal extends EventEmitter(Object) {
             INACTIVE: 90000
         };
 
+        // TODO: DEPRECATED
+        this.bookmarks = null;
         this.chatboxes = null;
 
+        this.api = /** @type {module:shared-api.APIEndpoint} */ null;
+
         /**
          * Namespace for storing code that might be useful to 3rd party
          * plugins. We want to make it possible for 3rd party plugins to have
          * access to code (e.g. classes) from converse.js without having to add
          * converse.js as a dependency.
          */
-        this.exports = /** @type { Record<string, Object> } */{};
+        this.exports = /** @type {Record<string, Object>} */{};
+
+        /**
+         * Namespace for storing the state, as represented by instances of
+         * Models and Collections.
+         */
+        this.state = /** @type {Record<string, Model|Collection>} */{};
+
+        this.initSession();
+    }
+
+    initSession () {
+        this.session?.destroy();
+        this.session = new Model();
     }
 
     /**
      * Translate the given string based on the current locale.
      * @method __
      * @memberOf _converse
-     * @param { ...String } args
+     * @param {...String} args
      */
     __ (...args) {
         return i18n.__(...args);
@@ -106,7 +123,7 @@ class ConversePrivateGlobal extends EventEmitter(Object) {
      *
      * @method ___
      * @memberOf _converse
-     * @param { String } str
+     * @param {String} str
      */
     ___ (str) {
         return str;

+ 2 - 2
src/headless/shared/api/public.js

@@ -8,8 +8,8 @@ import sizzle from 'sizzle';
 import u, { setLogLevelFromRoute } from '../../utils/index.js';
 import { ANONYMOUS, CHAT_STATES, KEYCODES, VERSION_NAME } from '../constants.js';
 import { setUnloadEvent, isTestEnv } from '../../utils/session.js';
-import { Collection } from "@converse/skeletor/src/collection";
-import { Model } from '@converse/skeletor/src/model.js';
+import { Collection } from "@converse/skeletor";
+import { Model } from '@converse/skeletor';
 import { Strophe, $build, $iq, $msg, $pres, stx } from 'strophe.js';
 import { TimeoutError } from '../errors.js';
 import { filesize } from 'filesize';

+ 1 - 1
src/headless/shared/connection/feedback.js

@@ -1,5 +1,5 @@
 import _converse from '../_converse';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { Strophe } from 'strophe.js';
 
 

+ 1 - 1
src/headless/shared/settings/utils.js

@@ -4,7 +4,7 @@ import isEqual from "lodash-es/isEqual.js";
 import log from '../../log.js';
 import pick from 'lodash-es/pick';
 import { DEFAULT_SETTINGS } from './constants.js';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { initStorage } from '../../utils/storage.js';
 import { merge } from '../../utils/object.js';
 

+ 1 - 1
src/headless/utils/index.js

@@ -4,7 +4,7 @@
  * @description This is the core utilities module.
  */
 import log, { LEVELS } from '../log.js';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { toStanza } from 'strophe.js';
 import { getOpenPromise } from '@converse/openpromise';
 import { saveWindowState, shouldClearCache } from './session.js';

+ 5 - 2
src/headless/utils/init.js

@@ -7,7 +7,7 @@ import log from '../log.js';
 import syncDriver from 'localforage-webextensionstorage-driver/sync';
 import { ANONYMOUS, CORE_PLUGINS, EXTERNAL, LOGIN } from '../shared/constants.js';
 import { Connection } from '../shared/connection/index.js';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { Strophe } from 'strophe.js';
 import { createStore, initStorage } from './storage.js';
 import { getConnectionServiceURL } from '../shared/connection/utils';
@@ -131,10 +131,13 @@ function saveJIDtoSession (_converse, jid) {
     if (_converse.api.settings.get("authentication") !== ANONYMOUS && !Strophe.getResourceFromJid(jid)) {
         jid = jid.toLowerCase() + Connection.generateResource();
     }
+
+    // TODO: Storing directly on _converse is deprecated
     _converse.jid = jid;
     _converse.bare_jid = Strophe.getBareJidFromJid(jid);
     _converse.resource = Strophe.getResourceFromJid(jid);
     _converse.domain = Strophe.getDomainFromJid(jid);
+
     _converse.session.save({
        'jid': jid,
        'bare_jid': _converse.bare_jid,
@@ -183,7 +186,7 @@ export async function initSession (_converse, jid) {
     if (_converse.session?.get('id') !== id) {
         initPersistentStorage(_converse, bare_jid);
 
-        _converse.session = new Model({ id });
+        _converse.session.set({ id });
         initStorage(_converse.session, id, is_shared_session ? "persistent" : "session");
         await new Promise(r => _converse.session.fetch({'success': r, 'error': r}));
 

+ 1 - 2
src/headless/utils/session.js

@@ -100,8 +100,7 @@ export async function tearDown () {
 
 
 export function clearSession () {
-    _converse.session?.destroy();
-    delete _converse.session;
+    _converse.initSession();
     shouldClearCache() && _converse.api.user.settings.clear();
     /**
      * Synchronouse event triggered once the user session has been cleared,

+ 1 - 1
src/plugins/bookmark-views/components/bookmarks-list.js

@@ -2,7 +2,7 @@ import debounce from "lodash-es/debounce";
 import tplBookmarksList from './templates/list.js';
 import tplSpinner from "templates/spinner.js";
 import { CustomElement } from 'shared/components/element.js';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { _converse, api } from '@converse/headless';
 import { initStorage } from '@converse/headless/utils/storage.js';
 

+ 3 - 2
src/plugins/bookmark-views/mixins.js

@@ -8,8 +8,9 @@ export const bookmarkableChatRoomView = {
      * @private
      */
     setBookmarkState () {
-        if (_converse.bookmarks !== undefined) {
-            const models = _converse.bookmarks.where({ 'jid': this.model.get('jid') });
+        const { bookmarks } = _converse.state;
+        if (bookmarks) {
+            const models = bookmarks.where({ 'jid': this.model.get('jid') });
             if (!models.length) {
                 this.model.save('bookmarked', false);
             } else {

+ 4 - 1
src/plugins/chatview/tests/styling.js

@@ -173,8 +173,11 @@ describe("An incoming chat Message", function () {
         await u.waitUntil(() => view.querySelectorAll('.chat-msg__text').length === 9);
         msg_el = Array.from(view.querySelectorAll('converse-chat-message-body')).pop();
         expect(msg_el.innerText).toBe(msg_text);
+
         await u.waitUntil(() => msg_el.innerHTML.replace(/<!-.*?->/g, '') ===
-            'Go to ~https://conversejs.org~now <span class="styling-directive">_</span><i>please</i><span class="styling-directive">_</span>');
+            'Go to ~<a target="_blank" rel="noopener" href="https://conversejs.org~now/">https://conversejs.org~now</a> '+
+            '<span class="styling-directive">_</span><i>please</i><span class="styling-directive">_</span>'
+        );
 
         msg_text = `Go to _https://converse_js.org_ _please_`;
         msg = mock.createChatMessage(_converse, contact_jid, msg_text)

+ 1 - 1
src/plugins/controlbox/model.js

@@ -1,5 +1,5 @@
 import { _converse, api, converse } from '@converse/headless';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { CONTROLBOX_TYPE } from '@converse/headless/shared/constants';
 
 const { dayjs } = converse.env;

+ 1 - 1
src/plugins/minimize/toggle.js

@@ -1,4 +1,4 @@
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 
 class MinimizedChatsToggle extends Model {
     defaults () { // eslint-disable-line class-methods-use-this

+ 1 - 1
src/plugins/modal/api.js

@@ -1,6 +1,6 @@
 import './alert.js';
 import Confirm from './confirm.js';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 
 let modals = [];
 let modals_map = {};

+ 1 - 1
src/plugins/muc-views/heading.js

@@ -3,7 +3,7 @@ import './modals/muc-invite.js';
 import './modals/nickname.js';
 import tplMUCHead from './templates/muc-head.js';
 import { CustomElement } from 'shared/components/element.js';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { __ } from 'i18n';
 import { _converse, api, converse } from "@converse/headless";
 import { destroyMUC, showModeratorToolsModal } from './utils.js';

+ 1 - 1
src/plugins/muc-views/modals/occupant.js

@@ -1,6 +1,6 @@
 import BaseModal from "plugins/modal/modal.js";
 import tplOccupantModal from "./templates/occupant.js";
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { __ } from 'i18n';
 import { _converse, api, converse } from "@converse/headless";
 

+ 1 - 1
src/plugins/omemo/device.js

@@ -1,5 +1,5 @@
 import { IQError } from './errors.js';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { UNDECIDED } from './consts.js';
 import { _converse, api, converse, log } from '@converse/headless';
 import { getRandomInt } from '@converse/headless/utils/index.js';

+ 1 - 1
src/plugins/omemo/devicelist.js

@@ -1,4 +1,4 @@
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { _converse, api, converse, log } from '@converse/headless';
 import { getOpenPromise } from '@converse/openpromise';
 import { initStorage } from '@converse/headless/utils/storage.js';

+ 1 - 1
src/plugins/omemo/devicelists.js

@@ -1,5 +1,5 @@
 import DeviceList from './devicelist.js';
-import { Collection } from '@converse/skeletor/src/collection';
+import { Collection } from '@converse/skeletor';
 
 class DeviceLists extends Collection {
 

+ 1 - 1
src/plugins/omemo/devices.js

@@ -1,5 +1,5 @@
 import Device from './device.js';
-import { Collection } from '@converse/skeletor/src/collection';
+import { Collection } from '@converse/skeletor';
 
 class Devices extends Collection {
 

+ 1 - 1
src/plugins/omemo/store.js

@@ -1,6 +1,6 @@
 /* global libsignal */
 import range from 'lodash-es/range';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { generateDeviceID } from './utils.js';
 import { _converse, api, converse, log } from '@converse/headless';
 

+ 1 - 1
src/plugins/roomslist/model.js

@@ -1,4 +1,4 @@
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { _converse, api, converse } from "@converse/headless";
 
 const { Strophe } = converse.env;

+ 1 - 1
src/plugins/rosterview/rosterview.js

@@ -1,6 +1,6 @@
 import tplRoster from "./templates/roster.js";
 import { CustomElement } from 'shared/components/element.js';
-import { Model } from '@converse/skeletor/src/model.js';
+import { Model } from '@converse/skeletor';
 import { _converse, api } from "@converse/headless";
 import { initStorage } from '@converse/headless/utils/storage.js';
 import { slideIn, slideOut } from 'utils/html.js';