Ver código fonte

Create a new BaseMessage class

JC Brand 4 meses atrás
pai
commit
e808c2537a
96 arquivos alterados com 1080 adições e 1131 exclusões
  1. 2 2
      src/headless/plugins/blocklist/plugin.js
  2. 5 283
      src/headless/plugins/chat/message.js
  3. 1 1
      src/headless/plugins/chat/model.js
  4. 1 1
      src/headless/plugins/chat/parsers.js
  5. 0 64
      src/headless/plugins/chat/types.ts
  6. 1 1
      src/headless/plugins/chat/utils.js
  7. 6 13
      src/headless/plugins/muc/message.js
  8. 9 8
      src/headless/plugins/muc/muc.js
  9. 1 1
      src/headless/plugins/muc/occupant.js
  10. 1 1
      src/headless/plugins/muc/types.ts
  11. 1 1
      src/headless/shared/actions.js
  12. 296 0
      src/headless/shared/message.js
  13. 22 23
      src/headless/shared/model-with-messages.js
  14. 63 0
      src/headless/shared/types.ts
  15. 3 286
      src/headless/types/plugins/chat/message.d.ts
  16. 24 24
      src/headless/types/plugins/chat/model.d.ts
  17. 2 2
      src/headless/types/plugins/chat/parsers.d.ts
  18. 0 57
      src/headless/types/plugins/chat/types.d.ts
  19. 1 1
      src/headless/types/plugins/chat/utils.d.ts
  20. 4 77
      src/headless/types/plugins/muc/message.d.ts
  21. 33 32
      src/headless/types/plugins/muc/muc.d.ts
  22. 26 22
      src/headless/types/plugins/muc/occupant.d.ts
  23. 1 1
      src/headless/types/plugins/muc/types.d.ts
  24. 2 2
      src/headless/types/plugins/vcard/utils.d.ts
  25. 2 2
      src/headless/types/shared/actions.d.ts
  26. 20 20
      src/headless/types/shared/chatbox.d.ts
  27. 290 0
      src/headless/types/shared/message.d.ts
  28. 37 37
      src/headless/types/shared/model-with-messages.d.ts
  29. 62 0
      src/headless/types/shared/types.d.ts
  30. 3 3
      src/plugins/mam-views/tests/mam.js
  31. 1 1
      src/plugins/muc-views/tests/mam.js
  32. 1 1
      src/plugins/muc-views/tests/muc-messages.js
  33. 1 1
      src/plugins/omemo/utils.js
  34. 1 1
      src/types/plugins/adhoc-views/adhoc-commands.d.ts
  35. 2 2
      src/types/plugins/bookmark-views/components/bookmarks-list.d.ts
  36. 2 2
      src/types/plugins/chatview/message-form.d.ts
  37. 1 1
      src/types/plugins/controlbox/controlbox.d.ts
  38. 2 2
      src/types/plugins/controlbox/loginform.d.ts
  39. 2 2
      src/types/plugins/controlbox/model.d.ts
  40. 1 1
      src/types/plugins/controlbox/utils.d.ts
  41. 4 4
      src/types/plugins/dragresize/utils.d.ts
  42. 1 1
      src/types/plugins/headlines-view/feed-list.d.ts
  43. 1 1
      src/types/plugins/headlines-view/view.d.ts
  44. 1 1
      src/types/plugins/minimize/utils.d.ts
  45. 2 2
      src/types/plugins/minimize/view.d.ts
  46. 1 1
      src/types/plugins/modal/api.d.ts
  47. 2 3
      src/types/plugins/modal/modal.d.ts
  48. 0 1
      src/types/plugins/muc-views/bottom-panel.d.ts
  49. 2 2
      src/types/plugins/muc-views/message-form.d.ts
  50. 1 1
      src/types/plugins/muc-views/modals/muc-list.d.ts
  51. 1 2
      src/types/plugins/muc-views/modtools.d.ts
  52. 1 1
      src/types/plugins/muc-views/occupant-bottom-panel.d.ts
  53. 1 1
      src/types/plugins/muc-views/occupant.d.ts
  54. 1 1
      src/types/plugins/muc-views/occupants.d.ts
  55. 1 1
      src/types/plugins/muc-views/templates/muc-bottom-panel.d.ts
  56. 1 1
      src/types/plugins/muc-views/utils.d.ts
  57. 1 1
      src/types/plugins/notifications/utils.d.ts
  58. 1 1
      src/types/plugins/omemo/device.d.ts
  59. 1 1
      src/types/plugins/omemo/devicelist.d.ts
  60. 1 1
      src/types/plugins/omemo/store.d.ts
  61. 1 1
      src/types/plugins/omemo/utils.d.ts
  62. 0 1
      src/types/plugins/profile/modals/profile.d.ts
  63. 1 1
      src/types/plugins/push/utils.d.ts
  64. 6 6
      src/types/plugins/register/form.d.ts
  65. 1 1
      src/types/plugins/roomslist/model.d.ts
  66. 2 2
      src/types/plugins/roomslist/view.d.ts
  67. 5 5
      src/types/plugins/rosterview/rosterview.d.ts
  68. 2 2
      src/types/plugins/rosterview/utils.d.ts
  69. 7 7
      src/types/shared/autocomplete/autocomplete.d.ts
  70. 2 2
      src/types/shared/autocomplete/component.d.ts
  71. 3 3
      src/types/shared/chat/baseview.d.ts
  72. 2 2
      src/types/shared/chat/emoji-dropdown.d.ts
  73. 1 1
      src/types/shared/chat/emoji-picker-content.d.ts
  74. 5 5
      src/types/shared/chat/emoji-picker.d.ts
  75. 1 1
      src/types/shared/chat/message-body.d.ts
  76. 2 2
      src/types/shared/chat/message.d.ts
  77. 1 1
      src/types/shared/chat/toolbar.d.ts
  78. 2 2
      src/types/shared/chat/utils.d.ts
  79. 1 1
      src/types/shared/components/dropdown.d.ts
  80. 3 3
      src/types/shared/components/dropdownbase.d.ts
  81. 2 2
      src/types/shared/components/element.d.ts
  82. 4 4
      src/types/shared/components/gif.d.ts
  83. 1 1
      src/types/shared/components/image-picker.d.ts
  84. 1 1
      src/types/shared/components/list-filter.d.ts
  85. 1 1
      src/types/shared/components/observable.d.ts
  86. 9 9
      src/types/shared/components/split-resize.d.ts
  87. 4 4
      src/types/shared/directives/image.d.ts
  88. 5 5
      src/types/shared/dom-navigator.d.ts
  89. 8 8
      src/types/shared/gif/index.d.ts
  90. 0 1
      src/types/shared/modals/user-details.d.ts
  91. 1 1
      src/types/shared/texture/component.d.ts
  92. 2 2
      src/types/shared/texture/directive.d.ts
  93. 33 33
      src/types/shared/texture/texture.d.ts
  94. 1 1
      src/types/shared/texture/utils.d.ts
  95. 1 1
      src/types/templates/audio.d.ts
  96. 1 1
      src/types/templates/video.d.ts

+ 2 - 2
src/headless/plugins/blocklist/plugin.js

@@ -28,8 +28,8 @@ converse.plugins.add('converse-blocklist', {
         api.listen.on(
             'getErrorAttributesForMessage',
             /**
-             * @param {import('plugins/chat/types').MessageAttributes} attrs
-             * @param {import('plugins/chat/types').MessageErrorAttributes} new_attrs
+             * @param {import('shared/types').MessageAttributes} attrs
+             * @param {import('shared/types').MessageErrorAttributes} new_attrs
              */
             (attrs, new_attrs) => {
                 if (attrs.errors.find((e) => e.name === 'blocked' && e.xmlns === `${Strophe.NS.BLOCKING}:errors`)) {

+ 5 - 283
src/headless/plugins/chat/message.js

@@ -1,16 +1,8 @@
-import sizzle from 'sizzle';
-import { Strophe, $iq } from 'strophe.js';
-import { Model } from '@converse/skeletor';
+import { Strophe } from 'strophe.js';
 import { getOpenPromise } from '@converse/openpromise';
-import dayjs from 'dayjs';
-import log from '../../log.js';
 import _converse from '../../shared/_converse.js';
 import api from '../../shared/api/index.js';
-import { SUCCESS, FAILURE } from '../../shared/constants.js';
-import ModelWithContact from '../../shared/model-with-contact.js';
-import ModelWithVCard from '../../shared/model-with-vcard';
-import ColorAwareModel from '../../shared/color.js';
-import { getUniqueId } from '../../utils/index.js';
+import BaseMessage from '../../shared/message.js';
 
 /**
  * Represents a (non-MUC) message.
@@ -19,43 +11,17 @@ import { getUniqueId } from '../../utils/index.js';
  * @memberOf _converse
  * @example const msg = new Message({'message': 'hello world!'});
  */
-class Message extends ModelWithVCard(ModelWithContact(ColorAwareModel(Model))) {
-
-    defaults () {
-        return {
-            'msgid': getUniqueId(),
-            'time': new Date().toISOString(),
-            'is_ephemeral': false
-        };
-    }
-
-    /**
-     * @param {Model[]} [models]
-     * @param {object} [options]
-     */
-    constructor (models, options) {
-        super(models, options);
-        this.file = null;
-
-        /** @type {import('./types').MessageAttributes} */
-        this.attributes;
-    }
+class Message extends BaseMessage {
 
     async initialize () {
         super.initialize();
-        if (!this.checkValidity()) return;
-        this.chatbox = this.collection?.chatbox;
 
         this.initialized = getOpenPromise();
-        if (this.get('file')) {
-            this.on('change:put', () => this.uploadFile());
-        }
+
         // If `type` changes from `error` to `chat`, we want to set the contact. See #2733
         this.on('change:type', () => this.setContact());
-        this.on('change:is_ephemeral', () => this.setTimerForEphemeralMessage());
-
         await this.setContact();
-        this.setTimerForEphemeralMessage();
+
         /**
          * Triggered once a {@link Message} has been created and initialized.
          * @event _converse#messageInitialized
@@ -72,111 +38,6 @@ class Message extends ModelWithVCard(ModelWithContact(ColorAwareModel(Model))) {
         }
     }
 
-    /**
-     * Sets an auto-destruct timer for this message, if it's is_ephemeral.
-     * @method _converse.Message#setTimerForEphemeralMessage
-     */
-    setTimerForEphemeralMessage () {
-        if (this.ephemeral_timer) {
-            clearTimeout(this.ephemeral_timer);
-        }
-        const is_ephemeral = this.isEphemeral();
-        if (is_ephemeral) {
-            const timeout = typeof is_ephemeral === "number" ? is_ephemeral : 10000;
-            this.ephemeral_timer = setTimeout(() => this.safeDestroy(), timeout);
-        }
-    }
-
-    checkValidity () {
-        if (Object.keys(this.attributes).length === 3) {
-            // XXX: This is an empty message with only the 3 default values.
-            // This seems to happen when saving a newly created message
-            // fails for some reason.
-            // TODO: This is likely fixable by setting `wait` when
-            // creating messages. See the wait-for-messages branch.
-            this.validationError = 'Empty message';
-            this.safeDestroy();
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Determines whether this messsage may be retracted by the current user.
-     * @method _converse.Messages#mayBeRetracted
-     * @returns { Boolean }
-     */
-    mayBeRetracted () {
-        const is_own_message = this.get('sender') === 'me';
-        const not_canceled = this.get('error_type') !== 'cancel';
-        return is_own_message && not_canceled && ['all', 'own'].includes(api.settings.get('allow_message_retraction'));
-    }
-
-    safeDestroy () {
-        try {
-            this.destroy();
-        } catch (e) {
-            log.warn(`safeDestroy: ${e}`);
-        }
-    }
-
-    /**
-     * Returns a boolean indicating whether this message is ephemeral,
-     * meaning it will get automatically removed after ten seconds.
-     * @returns {boolean}
-     */
-    isEphemeral () {
-        return this.get('is_ephemeral');
-    }
-
-    /**
-     * Returns a boolean indicating whether this message is a XEP-0245 /me command.
-     * @returns {boolean}
-     */
-    isMeCommand () {
-        const text = this.getMessageText();
-        if (!text) {
-            return false;
-        }
-        return text.startsWith('/me ');
-    }
-
-    /**
-     * @returns {boolean}
-     */
-    isRetracted () {
-        return this.get('retracted') || this.get('moderated') === 'retracted';
-    }
-
-    /**
-     * Returns a boolean indicating whether this message is considered a followup
-     * message from the previous one. Followup messages are shown grouped together
-     * under one author heading.
-     * A message is considered a followup of it's predecessor when it's a chat
-     * message from the same author, within 10 minutes.
-     * @returns {boolean}
-     */
-    isFollowup () {
-        const messages = this.collection?.models;
-        if (!messages) {
-            // Happens during tests
-            return false;
-        }
-        const idx = messages.indexOf(this);
-        const prev_model = idx ? messages[idx-1] : null;
-        if (prev_model === null) {
-            return false;
-        }
-        const date = dayjs(this.get('time'));
-        return this.get('from') === prev_model.get('from') &&
-            !this.isRetracted() && !prev_model.isRetracted() &&
-            !this.isMeCommand() && !prev_model.isMeCommand() &&
-            !!this.get('is_encrypted') === !!prev_model.get('is_encrypted') &&
-            this.get('type') === prev_model.get('type') && this.get('type') !== 'info' &&
-            date.isBefore(dayjs(prev_model.get('time')).add(10, 'minutes')) &&
-            (this.get('type') === 'groupchat' ? this.get('occupant_id') === prev_model.get('occupant_id') : true);
-    }
-
     getDisplayName () {
         if (this.contact) {
             return this.contact.getDisplayName();
@@ -186,145 +47,6 @@ class Message extends ModelWithVCard(ModelWithContact(ColorAwareModel(Model))) {
             return this.get('from');
         }
     }
-
-    getMessageText () {
-        if (this.get('is_encrypted')) {
-            const { __ } = _converse;
-            return this.get('plaintext') || this.get('body') || __('Undecryptable OMEMO message');
-        } else if (['groupchat', 'chat', 'normal'].includes(this.get('type'))) {
-            return this.get('body');
-        } else {
-            return this.get('message');
-        }
-    }
-
-    /**
-     * Send out an IQ stanza to request a file upload slot.
-     * https://xmpp.org/extensions/xep-0363.html#request
-     * @private
-     * @method _converse.Message#sendSlotRequestStanza
-     */
-    sendSlotRequestStanza () {
-        if (!this.file) return Promise.reject(new Error('file is undefined'));
-
-        const iq = $iq({
-                'from': _converse.session.get('jid'),
-                'to': this.get('slot_request_url'),
-                'type': 'get'
-            })
-            .c('request', {
-                'xmlns': Strophe.NS.HTTPUPLOAD,
-                'filename': this.file.name,
-                'size': this.file.size,
-                'content-type': this.file.type
-            });
-        return api.sendIQ(iq);
-    }
-
-    /**
-     * @param {Element} stanza
-     */
-    getUploadRequestMetadata (stanza) { // eslint-disable-line class-methods-use-this
-        const headers = sizzle(`slot[xmlns="${Strophe.NS.HTTPUPLOAD}"] put header`, stanza);
-        // https://xmpp.org/extensions/xep-0363.html#request
-        // TODO: Can't set the Cookie header in JavaScipt, instead cookies need
-        // to be manually set via document.cookie, so we're leaving it out here.
-        return {
-            'headers': headers
-                .map(h => ({ 'name': h.getAttribute('name'), 'value': h.textContent }))
-                .filter(h => ['Authorization', 'Expires'].includes(h.name))
-        }
-    }
-
-    async getRequestSlotURL () {
-        const { __ } = _converse;
-        let stanza;
-        try {
-            stanza = await this.sendSlotRequestStanza();
-        } catch (e) {
-            log.error(e);
-            return this.save({
-                'type': 'error',
-                'message': __('Sorry, could not determine upload URL.'),
-                'is_ephemeral': true
-            });
-        }
-        const slot = sizzle(`slot[xmlns="${Strophe.NS.HTTPUPLOAD}"]`, stanza).pop();
-        if (slot) {
-            this.upload_metadata = this.getUploadRequestMetadata(stanza);
-            this.save({
-                'get': slot.querySelector('get').getAttribute('url'),
-                'put': slot.querySelector('put').getAttribute('url')
-            });
-        } else {
-            return this.save({
-                'type': 'error',
-                'message': __('Sorry, could not determine file upload URL.'),
-                'is_ephemeral': true
-            });
-        }
-    }
-
-    uploadFile () {
-        const xhr = new XMLHttpRequest();
-
-        xhr.onreadystatechange = async (event) => {
-            if (xhr.readyState === XMLHttpRequest.DONE) {
-                log.info('Status: ' + xhr.status);
-                if (xhr.status === 200 || xhr.status === 201) {
-                    let attrs = {
-                        'upload': SUCCESS,
-                        'oob_url': this.get('get'),
-                        'message': this.get('get'),
-                        'body': this.get('get'),
-                    };
-                    /**
-                     * *Hook* which allows plugins to change the attributes
-                     * saved on the message once a file has been uploaded.
-                     * @event _converse#afterFileUploaded
-                     */
-                    attrs = await api.hook('afterFileUploaded', this, attrs);
-                    this.save(attrs);
-                } else {
-                    log.error(event);
-                    xhr.onerror(new ProgressEvent(`Response status: ${xhr.status}`));
-                }
-            }
-        };
-
-        xhr.upload.addEventListener(
-            'progress',
-            evt => {
-                if (evt.lengthComputable) {
-                    this.set('progress', evt.loaded / evt.total);
-                }
-            },
-            false
-        );
-
-        xhr.onerror = () => {
-            const { __ } = _converse;
-            let message;
-            if (xhr.responseText) {
-                message = __(
-                    'Sorry, could not succesfully upload your file. Your server’s response: "%1$s"',
-                    xhr.responseText
-                );
-            } else {
-                message = __('Sorry, could not succesfully upload your file.');
-            }
-            this.save({
-                'type': 'error',
-                'upload': FAILURE,
-                'message': message,
-                'is_ephemeral': true
-            });
-        };
-        xhr.open('PUT', this.get('put'), true);
-        xhr.setRequestHeader('Content-type', this.file.type);
-        this.upload_metadata.headers?.forEach(h => xhr.setRequestHeader(h.name, h.value));
-        xhr.send(this.file);
-    }
 }
 
 export default Message;

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

@@ -22,7 +22,7 @@ class ChatBox extends ModelWithVCard(ModelWithMessages(ModelWithContact(ColorAwa
     /**
      * @typedef {import('./message.js').default} Message
      * @typedef {import('../muc/muc.js').default} MUC
-     * @typedef {import('./types').MessageAttributes} MessageAttributes
+     * @typedef {import('../../shared/types').MessageAttributes} MessageAttributes
      * @typedef {import('../../shared/errors').StanzaParseError} StanzaParseError
      */
 

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

@@ -34,7 +34,7 @@ const { Strophe, sizzle } = converse.env;
 /**
  * Parses a passed in message stanza and returns an object of attributes.
  * @param {Element} stanza - The message stanza
- * @returns {Promise<import('./types.ts').MessageAttributes|StanzaParseError>}
+ * @returns {Promise<import('../../shared/types.ts').MessageAttributes|StanzaParseError>}
  */
 export async function parseMessage (stanza) {
     throwErrorIfInvalidForward(stanza);

+ 0 - 64
src/headless/plugins/chat/types.ts

@@ -1,64 +0,0 @@
-import {EncryptionAttrs} from "../../shared/types";
-
-// Represents a XEP-0372 reference
-export type Reference = {
-    begin: number;
-    end: number;
-    type: string;
-    uri: string;
-}
-
-export type MessageErrorAttributes = {
-    is_error: boolean; // Whether an error was received for this message
-    error: string; // The error name
-    errors: { name: string; xmlns: string }[];
-    error_condition: string; // The defined error condition
-    error_text: string; // The error text received from the server
-    error_type: string; // The type of error received from the server
-}
-
-export type MessageAttributes = EncryptionAttrs & MessageErrorAttributes & {
-    body: string; // The contents of the <body> tag of the message stanza
-    chat_state: string; // The XEP-0085 chat state notification contained in this message
-    contact_jid: string; // The JID of the other person or entity
-    editable: boolean; // Is this message editable via XEP-0308?
-    edited: string; // An ISO8601 string recording the time that the message was edited per XEP-0308
-    from: string; // The sender JID
-    message?: string; // Used with info and error messages
-    fullname: string; // The full name of the sender
-    is_archived: boolean; //  Is this message from a XEP-0313 MAM archive?
-    is_carbon: boolean; // Is this message a XEP-0280 Carbon?
-    is_delayed: boolean; // Was delivery of this message was delayed as per XEP-0203?
-    is_encrypted: boolean; //  Is this message XEP-0384  encrypted?
-    is_headline: boolean; // Is this a "headline" message?
-    is_markable: boolean; // Can this message be marked with a XEP-0333 chat marker?
-    is_marker: boolean; // Is this message a XEP-0333 Chat Marker?
-    is_only_emojis: boolean; // Does the message body contain only emojis?
-    is_spoiler: boolean; // Is this a XEP-0382 spoiler message?
-    is_tombstone: boolean; // Is this a XEP-0424 tombstone?
-    is_unstyled: boolean; // Whether XEP-0393 styling hints should be ignored
-    is_valid_receipt_request: boolean; // Does this message request a XEP-0184 receipt (and is not from us or a carbon or archived message)
-    marker: string; // The XEP-0333 Chat Marker value
-    marker_id: string; // The `id` attribute of a XEP-0333 chat marker
-    msgid: string; // The root `id` attribute of the stanza
-    nick: string; // The roster nickname of the sender
-    ogp_for_id?: string; // Used for Open Graph Metadata support for unfurls
-    oob_desc: string; // The description of the XEP-0066 out of band data
-    oob_url: string; // The URL of the XEP-0066 out of band data
-    origin_id: string; // The XEP-0359 Origin ID
-    plaintext: string; // The decrypted text of this message, in case it was encrypted.
-    receipt_id: string; // The `id` attribute of a XEP-0184 <receipt> element
-    received: string; // An ISO8601 string recording the time that the message was received
-    references: Array<Reference>; // A list of objects representing XEP-0372 references
-    replace_id: string; // The `id` attribute of a XEP-0308 <replace> element
-    retracted: string; // An ISO8601 string recording the time that the message was retracted
-    retracted_id: string; // The `id` attribute of a XEP-424 <retracted> element
-    sender: 'me' | 'them'; // Whether the message was sent by the current user or someone else
-    spoiler_hint: string; //  The XEP-0382 spoiler hint
-    stanza_id: string; // The XEP-0359 Stanza ID. Note: the key is actualy `stanza_id ${by_jid}` and there can be multiple.
-    subject: string; // The <subject> element value
-    thread: string; // The <thread> element value
-    time: string; // The time (in ISO8601 format), either given by the XEP-0203 <delay> element, or of receipt.
-    to: string; // The recipient JID
-    type: string; // The type of message
-};

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

@@ -1,7 +1,7 @@
 /**
  * @module:headless-plugins-chat-utils
  * @typedef {import('./model.js').default} ChatBox
- * @typedef {import('./types.ts').MessageAttributes} MessageAttributes
+ * @typedef {import('../../shared/types.ts').MessageAttributes} MessageAttributes
  * @typedef {import('../../shared/errors').StanzaParseError} StanzaParseError
  * @typedef {import('strophe.js').Builder} Builder
  */

+ 6 - 13
src/headless/plugins/muc/message.js

@@ -1,27 +1,20 @@
 import { Strophe } from 'strophe.js';
 import _converse from '../../shared/_converse.js';
 import api from '../../shared/api/index.js';
-import ModelWithVCard from '../../shared/model-with-vcard';
-import Message from '../chat/message.js';
+import BaseMessage from '../../shared/message.js';
 
 
-class MUCMessage extends ModelWithVCard(Message) {
+class MUCMessage extends BaseMessage {
     /**
      * @typedef {import('./occupant').default} MUCOccupant
      */
-    async initialize () { // eslint-disable-line require-await
-        if (!this.checkValidity()) return;
-        this.chatbox = this.collection?.chatbox;
+    initialize () {
+        super.initialize();
 
-        if (this.get('file')) {
-            this.on('change:put', () => this.uploadFile());
-        }
         // If `type` changes from `error` to `groupchat`, we want to set the occupant. See #2733
         this.on('change:type', () => this.setOccupant());
-        this.on('change:is_ephemeral', () => this.setTimerForEphemeralMessage());
-
-        this.setTimerForEphemeralMessage();
         this.setOccupant();
+
         /**
          * Triggered once a { @link MUCMessage} has been created and initialized.
          * @event _converse#chatRoomMessageInitialized
@@ -58,7 +51,7 @@ class MUCMessage extends ModelWithVCard(Message) {
     }
 
     checkValidity () {
-        const result = _converse.exports.Message.prototype.checkValidity.call(this);
+        const result = super.checkValidity();
         !result && this.chatbox.debouncedRejoin();
         return result;
     }

+ 9 - 8
src/headless/plugins/muc/muc.js

@@ -31,10 +31,11 @@ import { getUniqueId, isErrorObject, safeSave } from '../../utils/index.js';
 import { isUniView } from '../../utils/session.js';
 import { parseMUCMessage, parseMUCPresence } from './parsers.js';
 import { sendMarker } from '../../shared/actions.js';
+import BaseMessage from '../../shared/message';
+import ChatBoxBase from '../../shared/chatbox';
+import ColorAwareModel from '../../shared/color';
 import ModelWithMessages from '../../shared/model-with-messages';
 import ModelWithVCard from '../../shared/model-with-vcard';
-import ColorAwareModel from '../../shared/color';
-import ChatBoxBase from '../../shared/chatbox';
 import { shouldCreateGroupchatMessage, isInfoVisible } from './utils.js';
 import MUCSession from './session';
 
@@ -51,7 +52,7 @@ class MUC extends ModelWithVCard(ModelWithMessages(ColorAwareModel(ChatBoxBase))
      * @typedef {import('./occupant.js').default} MUCOccupant
      * @typedef {import('./affiliations/utils.js').NonOutcastAffiliation} NonOutcastAffiliation
      * @typedef {import('./types').MemberListItem} MemberListItem
-     * @typedef {import('../chat/types').MessageAttributes} MessageAttributes
+     * @typedef {import('../../shared/types').MessageAttributes} MessageAttributes
      * @typedef {import('./types').MUCMessageAttributes} MUCMessageAttributes
      * @typedef {import('./types').MUCPresenceAttributes} MUCPresenceAttributes
      * @typedef {module:shared.converse.UserMessage} UserMessage
@@ -804,7 +805,7 @@ class MUC extends ModelWithVCard(ModelWithMessages(ColorAwareModel(ChatBoxBase))
 
     /**
      * Retract one of your messages in this groupchat
-     * @param {MUCMessage} message - The message which we're retracting.
+     * @param {BaseMessage} message - The message which we're retracting.
      */
     async retractOwnMessage(message) {
         const __ = _converse.__;
@@ -2329,11 +2330,11 @@ class MUC extends ModelWithVCard(ModelWithMessages(ColorAwareModel(ChatBoxBase))
      * passed in attributes map.
      * @param {object} attrs - Attributes representing a received
      *  message, as returned by {@link parseMUCMessage}
-     * @returns {Message}
+     * @returns {MUCMessage|BaseMessage}
      */
     getDuplicateMessage (attrs) {
         if (attrs.activities?.length) {
-            return this.messages.findWhere({ 'type': 'mep', 'msgid': attrs.msgid });
+            return this.messages.findWhere({ type: 'mep', msgid: attrs.msgid });
         } else {
             return super.getDuplicateMessage(attrs);
         }
@@ -2804,7 +2805,7 @@ class MUC extends ModelWithVCard(ModelWithMessages(ColorAwareModel(ChatBoxBase))
     /**
      * Returns a boolean to indicate whether the current user
      * was mentioned in a message.
-     * @param {MUCMessage} message - The text message
+     * @param {BaseMessage} message - The text message
      */
     isUserMentioned (message) {
         const nick = this.get('nick');
@@ -2820,7 +2821,7 @@ class MUC extends ModelWithVCard(ModelWithMessages(ColorAwareModel(ChatBoxBase))
     }
 
     /**
-     * @param {MUCMessage} message - The text message
+     * @param {BaseMessage} message - The text message
      */
     incrementUnreadMsgsCounter (message) {
         const settings = {

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

@@ -19,7 +19,7 @@ const { Strophe, stx } = converse.env;
  */
 class MUCOccupant extends ModelWithVCard(ModelWithMessages(ColorAwareModel(Model))) {
     /**
-     * @typedef {import('../chat/types').MessageAttributes} MessageAttributes
+     * @typedef {import('../../shared/types').MessageAttributes} MessageAttributes
      * @typedef {import('../../shared/errors').StanzaParseError} StanzaParseError
      */
 

+ 1 - 1
src/headless/plugins/muc/types.ts

@@ -1,5 +1,5 @@
 import { CHAT_STATES } from '../../shared/constants';
-import { MessageAttributes } from '../chat/types';
+import { MessageAttributes } from '../../shared/types';
 import MUC from './muc';
 
 export type MUCStatusCode =

+ 1 - 1
src/headless/shared/actions.js

@@ -88,7 +88,7 @@ export function sendChatState(jid, chat_state) {
 /**
  * Sends a message stanza to retract a message in this chat
  * @param {string} jid
- * @param {import('../plugins/chat/message').default} message - The message which we're retracting.
+ * @param {import('../shared/message').default} message - The message which we're retracting.
  * @param {string} retraction_id - Unique ID for the retraction message
  */
 export function sendRetractionMessage(jid, message, retraction_id) {

+ 296 - 0
src/headless/shared/message.js

@@ -0,0 +1,296 @@
+import dayjs from "dayjs";
+import sizzle from "sizzle";
+import { Strophe, $iq } from "strophe.js";
+import { Model } from "@converse/skeletor";
+import log from "../log.js";
+import _converse from "../shared/_converse.js";
+import api from "../shared/api/index.js";
+import { SUCCESS, FAILURE } from "../shared/constants.js";
+import ColorAwareModel from "../shared/color.js";
+import ModelWithContact from "../shared/model-with-contact.js";
+import ModelWithVCard from "../shared/model-with-vcard";
+import { getUniqueId } from "../utils/index.js";
+
+/**
+ * @template {import('./types').ModelExtender} T
+ * @param {T} BaseModel
+ */
+class BaseMessage extends ModelWithVCard(ModelWithContact(ColorAwareModel(Model))) {
+    defaults() {
+        return {
+            msgid: getUniqueId(),
+            time: new Date().toISOString(),
+            is_ephemeral: false,
+        };
+    }
+
+    /**
+     * @param {Model[]} [models]
+     * @param {object} [options]
+     */
+    constructor(models, options) {
+        super(models, options);
+        this.file = null;
+
+        /** @type {import('./types').MessageAttributes} */
+        this.attributes;
+    }
+
+    initialize() {
+        super.initialize();
+        if (!this.checkValidity()) return;
+        this.chatbox = this.collection?.chatbox;
+
+        if (this.get('file')) {
+            this.on('change:put', () => this.uploadFile());
+        }
+        this.on('change:is_ephemeral', () => this.setTimerForEphemeralMessage());
+        this.setTimerForEphemeralMessage();
+    }
+
+    checkValidity() {
+        if (Object.keys(this.attributes).length === 3) {
+            // XXX: This is an empty message with only the 3 default values.
+            // This seems to happen when saving a newly created message
+            // fails for some reason.
+            // TODO: This is likely fixable by setting `wait` when
+            // creating messages. See the wait-for-messages branch.
+            this.validationError = "Empty message";
+            this.safeDestroy();
+            return false;
+        }
+        return true;
+    }
+
+    safeDestroy() {
+        try {
+            this.destroy();
+        } catch (e) {
+            log.warn(`safeDestroy: ${e}`);
+        }
+    }
+
+    /**
+     * Sets an auto-destruct timer for this message, if it's is_ephemeral.
+     */
+    setTimerForEphemeralMessage() {
+        if (this.ephemeral_timer) {
+            clearTimeout(this.ephemeral_timer);
+        }
+        const is_ephemeral = this.isEphemeral();
+        if (is_ephemeral) {
+            const timeout = typeof is_ephemeral === "number" ? is_ephemeral : 10000;
+            this.ephemeral_timer = setTimeout(() => this.safeDestroy(), timeout);
+        }
+    }
+
+    /**
+     * Returns a boolean indicating whether this message is ephemeral,
+     * meaning it will get automatically removed after ten seconds.
+     * @returns {boolean}
+     */
+    isEphemeral() {
+        return this.get("is_ephemeral");
+    }
+
+    /**
+     * Returns a boolean indicating whether this message is a XEP-0245 /me command.
+     * @returns {boolean}
+     */
+    isMeCommand() {
+        const text = this.getMessageText();
+        if (!text) {
+            return false;
+        }
+        return text.startsWith("/me ");
+    }
+
+    /**
+     * @returns {boolean}
+     */
+    isRetracted() {
+        return this.get("retracted") || this.get("moderated") === "retracted";
+    }
+
+    /**
+     * Returns a boolean indicating whether this message is considered a followup
+     * message from the previous one. Followup messages are shown grouped together
+     * under one author heading.
+     * A message is considered a followup of it's predecessor when it's a chat
+     * message from the same author, within 10 minutes.
+     * @returns {boolean}
+     */
+    isFollowup() {
+        const messages = this.collection?.models;
+        if (!messages) {
+            // Happens during tests
+            return false;
+        }
+        const idx = messages.indexOf(this);
+        const prev_model = idx ? messages[idx - 1] : null;
+        if (prev_model === null) {
+            return false;
+        }
+        const date = dayjs(this.get("time"));
+        return (
+            this.get("from") === prev_model.get("from") &&
+            !this.isRetracted() &&
+            !prev_model.isRetracted() &&
+            !this.isMeCommand() &&
+            !prev_model.isMeCommand() &&
+            !!this.get("is_encrypted") === !!prev_model.get("is_encrypted") &&
+            this.get("type") === prev_model.get("type") &&
+            this.get("type") !== "info" &&
+            date.isBefore(dayjs(prev_model.get("time")).add(10, "minutes")) &&
+            (this.get("type") === "groupchat" ? this.get("occupant_id") === prev_model.get("occupant_id") : true)
+        );
+    }
+
+    /**
+     * Determines whether this messsage may be retracted by the current user.
+     * @returns { Boolean }
+     */
+    mayBeRetracted() {
+        const is_own_message = this.get("sender") === "me";
+        const not_canceled = this.get("error_type") !== "cancel";
+        return is_own_message && not_canceled && ["all", "own"].includes(api.settings.get("allow_message_retraction"));
+    }
+
+    getMessageText() {
+        if (this.get("is_encrypted")) {
+            const { __ } = _converse;
+            return this.get("plaintext") || this.get("body") || __("Undecryptable OMEMO message");
+        } else if (["groupchat", "chat", "normal"].includes(this.get("type"))) {
+            return this.get("body");
+        } else {
+            return this.get("message");
+        }
+    }
+
+    /**
+     * Send out an IQ stanza to request a file upload slot.
+     * https://xmpp.org/extensions/xep-0363.html#request
+     */
+    sendSlotRequestStanza() {
+        if (!this.file) return Promise.reject(new Error("file is undefined"));
+
+        const iq = $iq({
+            "from": _converse.session.get("jid"),
+            "to": this.get("slot_request_url"),
+            "type": "get",
+        }).c("request", {
+            "xmlns": Strophe.NS.HTTPUPLOAD,
+            "filename": this.file.name,
+            "size": this.file.size,
+            "content-type": this.file.type,
+        });
+        return api.sendIQ(iq);
+    }
+
+    /**
+     * @param {Element} stanza
+     */
+    getUploadRequestMetadata(stanza) {
+        const headers = sizzle(`slot[xmlns="${Strophe.NS.HTTPUPLOAD}"] put header`, stanza);
+        // https://xmpp.org/extensions/xep-0363.html#request
+        // TODO: Can't set the Cookie header in JavaScipt, instead cookies need
+        // to be manually set via document.cookie, so we're leaving it out here.
+        return {
+            headers: headers
+                .map((h) => ({ "name": h.getAttribute("name"), "value": h.textContent }))
+                .filter((h) => ["Authorization", "Expires"].includes(h.name)),
+        };
+    }
+
+    async getRequestSlotURL() {
+        const { __ } = _converse;
+        let stanza;
+        try {
+            stanza = await this.sendSlotRequestStanza();
+        } catch (e) {
+            log.error(e);
+            return this.save({
+                is_ephemeral: true,
+                message: __("Sorry, could not determine upload URL."),
+                type: "error",
+            });
+        }
+        const slot = sizzle(`slot[xmlns="${Strophe.NS.HTTPUPLOAD}"]`, stanza).pop();
+        if (slot) {
+            this.upload_metadata = this.getUploadRequestMetadata(stanza);
+            this.save({
+                get: slot.querySelector("get").getAttribute("url"),
+                put: slot.querySelector("put").getAttribute("url"),
+            });
+        } else {
+            return this.save({
+                is_ephemeral: true,
+                message: __("Sorry, could not determine file upload URL."),
+                type: "error",
+            });
+        }
+    }
+
+    uploadFile() {
+        const xhr = new XMLHttpRequest();
+
+        xhr.onreadystatechange = async (event) => {
+            if (xhr.readyState === XMLHttpRequest.DONE) {
+                log.info("Status: " + xhr.status);
+                if (xhr.status === 200 || xhr.status === 201) {
+                    let attrs = {
+                        body: this.get("get"),
+                        message: this.get("get"),
+                        oob_url: this.get("get"),
+                        upload: SUCCESS,
+                    };
+                    /**
+                     * *Hook* which allows plugins to change the attributes
+                     * saved on the message once a file has been uploaded.
+                     * @event _converse#afterFileUploaded
+                     */
+                    attrs = await api.hook("afterFileUploaded", this, attrs);
+                    this.save(attrs);
+                } else {
+                    log.error(event);
+                    xhr.onerror(new ProgressEvent(`Response status: ${xhr.status}`));
+                }
+            }
+        };
+
+        xhr.upload.addEventListener(
+            "progress",
+            (evt) => {
+                if (evt.lengthComputable) {
+                    this.set("progress", evt.loaded / evt.total);
+                }
+            },
+            false
+        );
+
+        xhr.onerror = () => {
+            const { __ } = _converse;
+            let message;
+            if (xhr.responseText) {
+                message = __(
+                    'Sorry, could not succesfully upload your file. Your server’s response: "%1$s"',
+                    xhr.responseText
+                );
+            } else {
+                message = __("Sorry, could not succesfully upload your file.");
+            }
+            this.save({
+                is_ephemeral: true,
+                message,
+                type: "error",
+                upload: FAILURE,
+            });
+        };
+        xhr.open("PUT", this.get("put"), true);
+        xhr.setRequestHeader("Content-type", this.file.type);
+        this.upload_metadata.headers?.forEach((h) => xhr.setRequestHeader(h.name, h.value));
+        xhr.send(this.file);
+    }
+}
+
+export default BaseMessage;

+ 22 - 23
src/headless/shared/model-with-messages.js

@@ -30,13 +30,12 @@ const { Strophe, stx, u } = converse.env;
  */
 export default function ModelWithMessages(BaseModel) {
     /**
-     * @typedef {import('./errors').StanzaParseError} StanzaParseError
-     * @typedef {import('../plugins/chat/message').default} Message
      * @typedef {import('../plugins/chat/model').default} ChatBox
      * @typedef {import('../plugins/muc/muc').default} MUC
-     * @typedef {import('../plugins/muc/message').default} MUCMessage
-     * @typedef {import('../plugins/chat/types.ts').MessageAttributes} MessageAttributes
      * @typedef {import('../plugins/muc/parsers').MUCMessageAttributes} MUCMessageAttributes
+     * @typedef {import('../shared/types').MessageAttributes} MessageAttributes
+     * @typedef {import('./errors').StanzaParseError} StanzaParseError
+     * @typedef {import('./message').default} BaseMessage
      * @typedef {import('strophe.js').Builder} Builder
      */
 
@@ -162,7 +161,7 @@ export default function ModelWithMessages(BaseModel) {
         }
 
         /**
-         * @param {Message} message
+         * @param {BaseMessage} message
          * @param {MessageAttributes} attrs
          * @returns {object}
          */
@@ -186,7 +185,7 @@ export default function ModelWithMessages(BaseModel) {
         }
 
         /**
-         * @param {Message} message
+         * @param {BaseMessage} message
          * @param {MessageAttributes} attrs
          */
         updateMessage(message, attrs) {
@@ -199,7 +198,7 @@ export default function ModelWithMessages(BaseModel) {
          * represent a XEP-0308 correction and, if so, handles it appropriately.
          * @param {MessageAttributes|MUCMessageAttributes} attrs - Attributes representing a received
          *  message, as returned by {@link parseMessage}
-         * @returns {Promise<Message|void>} Returns the corrected
+         * @returns {Promise<BaseMessage|void>} Returns the corrected
          *  message or `undefined` if not applicable.
          */
         async handleCorrection(attrs) {
@@ -268,7 +267,7 @@ export default function ModelWithMessages(BaseModel) {
         /**
          * Responsible for sending off a text message inside an ongoing chat conversation.
          * @param {Object} [attrs] - A map of attributes to be saved on the message
-         * @returns {Promise<Message>}
+         * @returns {Promise<BaseMessage>}
          * @example
          *  const chat = api.chats.get('buddy1@example.org');
          *  chat.sendMessage({'body': 'hello world'});
@@ -324,7 +323,7 @@ export default function ModelWithMessages(BaseModel) {
              * @type {Object}
              * @param {Object} data
              * @property {(ChatBox|MUC)} data.chatbox
-             * @property {(Message|MUCMessage)} data.message
+             * @property {(BaseMessage)} data.message
              */
             api.trigger('sendMessage', { 'chatbox': this, message });
             return message;
@@ -332,7 +331,7 @@ export default function ModelWithMessages(BaseModel) {
 
         /**
          * Retract one of your messages in this chat
-         * @param {Message} message - The message which we're retracting.
+         * @param {BaseMessage} message - The message which we're retracting.
          */
         retractOwnMessage(message) {
             const retraction_id = u.getUniqueId();
@@ -469,7 +468,7 @@ export default function ModelWithMessages(BaseModel) {
         }
 
         /**
-         * @param {Message} message
+         * @param {BaseMessage} message
          */
         onMessageAdded(message) {
             if (
@@ -482,7 +481,7 @@ export default function ModelWithMessages(BaseModel) {
         }
 
         /**
-         * @param {Message} message
+         * @param {BaseMessage} message
          */
         async onMessageUploadChanged(message) {
             if (message.get('upload') === constants.SUCCESS) {
@@ -622,7 +621,7 @@ export default function ModelWithMessages(BaseModel) {
          * relevant message is only coming in now.
          * @param {object} attrs - Attributes representing a received
          *  message, as returned by {@link parseMessage}
-         * @returns {Message|null}
+         * @returns {BaseMessage|null}
          */
         findDanglingRetraction(attrs) {
             if (!attrs.origin_id || !this.messages.length) {
@@ -649,7 +648,7 @@ export default function ModelWithMessages(BaseModel) {
          * passed in attributes map.
          * @param {object} attrs - Attributes representing a received
          *  message, as returned by {@link parseMessage}
-         * @returns {Message}
+         * @returns {BaseMessage}
          */
         getDuplicateMessage(attrs) {
             const queries = [
@@ -702,7 +701,7 @@ export default function ModelWithMessages(BaseModel) {
 
         /**
          * Given the passed in message object, send a XEP-0333 chat marker.
-         * @param {Message} msg
+         * @param {BaseMessage} msg
          * @param {('received'|'displayed'|'acknowledged')} [type='displayed']
          * @param {boolean} [force=false] - Whether a marker should be sent for the
          *  message, even if it didn't include a `markable` element.
@@ -727,9 +726,9 @@ export default function ModelWithMessages(BaseModel) {
         }
 
         /**
-         * Given a newly received {@link Message} instance,
+         * Given a newly received {@link BaseMessage} instance,
          * update the unread counter if necessary.
-         * @param {Message} message
+         * @param {BaseMessage} message
          */
         handleUnreadMessage(message) {
             if (!message?.get('body')) {
@@ -752,7 +751,7 @@ export default function ModelWithMessages(BaseModel) {
         }
 
         /**
-         * @param {Message} message
+         * @param {BaseMessage} message
          * @param {MessageAttributes} attrs
          */
         async getErrorAttributesForMessage(message, attrs) {
@@ -815,7 +814,7 @@ export default function ModelWithMessages(BaseModel) {
         }
 
         /**
-         * @param {Message} message
+         * @param {BaseMessage} message
          */
         incrementUnreadMsgsCounter(message) {
             const settings = {
@@ -891,9 +890,9 @@ export default function ModelWithMessages(BaseModel) {
         }
 
         /**
-         * Given a {@link Message} return the XML stanza that represents it.
+         * Given a {@link BaseMessage} return the XML stanza that represents it.
          * @method ChatBox#createMessageStanza
-         * @param {Message} message - The message object
+         * @param {BaseMessage} message - The message object
          */
         async createMessageStanza(message) {
             const {
@@ -940,8 +939,8 @@ export default function ModelWithMessages(BaseModel) {
              * @event _converse#createMessageStanza
              * @param {ChatBox|MUC} chat - The chat from
              *      which this message stanza is being sent.
-             * @param {Object} data - Message data
-             * @param {Message|MUCMessage} data.message
+             * @param {Object} data - BaseMessage data
+             * @param {BaseMessage} data.message
              *      The message object from which the stanza is created and which gets persisted to storage.
              * @param {Builder} data.stanza
              *      The stanza that will be sent out, as a Strophe.Builder object.

+ 63 - 0
src/headless/shared/types.ts

@@ -124,3 +124,66 @@ export type ErrorName =
     | 'unexpected-request';
 
 export type ErrorType = 'auth' | 'cancel' | 'continue' | 'modify' | 'wait';
+
+// Represents a XEP-0372 reference
+export type Reference = {
+    begin: number;
+    end: number;
+    type: string;
+    uri: string;
+}
+
+export type MessageErrorAttributes = {
+    is_error: boolean; // Whether an error was received for this message
+    error: string; // The error name
+    errors: { name: string; xmlns: string }[];
+    error_condition: string; // The defined error condition
+    error_text: string; // The error text received from the server
+    error_type: string; // The type of error received from the server
+}
+
+export type MessageAttributes = EncryptionAttrs & MessageErrorAttributes & {
+    body: string; // The contents of the <body> tag of the message stanza
+    chat_state: string; // The XEP-0085 chat state notification contained in this message
+    contact_jid: string; // The JID of the other person or entity
+    editable: boolean; // Is this message editable via XEP-0308?
+    edited: string; // An ISO8601 string recording the time that the message was edited per XEP-0308
+    from: string; // The sender JID
+    message?: string; // Used with info and error messages
+    fullname: string; // The full name of the sender
+    is_archived: boolean; //  Is this message from a XEP-0313 MAM archive?
+    is_carbon: boolean; // Is this message a XEP-0280 Carbon?
+    is_delayed: boolean; // Was delivery of this message was delayed as per XEP-0203?
+    is_encrypted: boolean; //  Is this message XEP-0384  encrypted?
+    is_headline: boolean; // Is this a "headline" message?
+    is_markable: boolean; // Can this message be marked with a XEP-0333 chat marker?
+    is_marker: boolean; // Is this message a XEP-0333 Chat Marker?
+    is_only_emojis: boolean; // Does the message body contain only emojis?
+    is_spoiler: boolean; // Is this a XEP-0382 spoiler message?
+    is_tombstone: boolean; // Is this a XEP-0424 tombstone?
+    is_unstyled: boolean; // Whether XEP-0393 styling hints should be ignored
+    is_valid_receipt_request: boolean; // Does this message request a XEP-0184 receipt (and is not from us or a carbon or archived message)
+    marker: string; // The XEP-0333 Chat Marker value
+    marker_id: string; // The `id` attribute of a XEP-0333 chat marker
+    msgid: string; // The root `id` attribute of the stanza
+    nick: string; // The roster nickname of the sender
+    ogp_for_id?: string; // Used for Open Graph Metadata support for unfurls
+    oob_desc: string; // The description of the XEP-0066 out of band data
+    oob_url: string; // The URL of the XEP-0066 out of band data
+    origin_id: string; // The XEP-0359 Origin ID
+    plaintext: string; // The decrypted text of this message, in case it was encrypted.
+    receipt_id: string; // The `id` attribute of a XEP-0184 <receipt> element
+    received: string; // An ISO8601 string recording the time that the message was received
+    references: Array<Reference>; // A list of objects representing XEP-0372 references
+    replace_id: string; // The `id` attribute of a XEP-0308 <replace> element
+    retracted: string; // An ISO8601 string recording the time that the message was retracted
+    retracted_id: string; // The `id` attribute of a XEP-424 <retracted> element
+    sender: 'me' | 'them'; // Whether the message was sent by the current user or someone else
+    spoiler_hint: string; //  The XEP-0382 spoiler hint
+    stanza_id: string; // The XEP-0359 Stanza ID. Note: the key is actualy `stanza_id ${by_jid}` and there can be multiple.
+    subject: string; // The <subject> element value
+    thread: string; // The <thread> element value
+    time: string; // The time (in ISO8601 format), either given by the XEP-0203 <delay> element, or of receipt.
+    to: string; // The recipient JID
+    type: string; // The type of message
+};

+ 3 - 286
src/headless/types/plugins/chat/message.d.ts

@@ -1,211 +1,4 @@
 export default Message;
-declare const Message_base: {
-    new (...args: any[]): {
-        _vcard: import("../vcard/vcard.js").default;
-        lazy_load_vcard: boolean;
-        initialize(): void;
-        readonly vcard: import("../vcard/vcard.js").default;
-        getVCard(create?: boolean): Promise<import("../vcard/vcard.js").default | null>;
-        cid: any;
-        attributes: {};
-        validationError: string;
-        collection: any;
-        changed: {};
-        browserStorage: Storage;
-        _browserStorage: Storage;
-        readonly idAttribute: string;
-        readonly cidPrefix: string;
-        preinitialize(): void;
-        validate(attrs: object, options?: object): string;
-        toJSON(): any;
-        sync(method: "create" | "update" | "patch" | "delete" | "read", model: Model, options: import("@converse/skeletor/src/types/model.js").Options): any;
-        get(attr: string): any;
-        keys(): string[];
-        values(): any[];
-        pairs(): [string, any][];
-        entries(): [string, any][];
-        invert(): any;
-        pick(...args: any[]): any;
-        omit(...args: any[]): any;
-        isEmpty(): any;
-        has(attr: string): boolean;
-        matches(attrs: import("@converse/skeletor/src/types/model.js").Attributes): boolean;
-        set(key: string | any, val?: string | any, options?: import("@converse/skeletor/src/types/model.js").Options): false | any;
-        _changing: boolean;
-        _previousAttributes: any;
-        id: any;
-        _pending: boolean | import("@converse/skeletor/src/types/model.js").Options;
-        unset(attr: string, options?: import("@converse/skeletor/src/types/model.js").Options): false | any;
-        clear(options: import("@converse/skeletor/src/types/model.js").Options): false | any;
-        hasChanged(attr?: string): any;
-        changedAttributes(diff: any): any;
-        previous(attr?: string): any;
-        previousAttributes(): any;
-        fetch(options?: import("@converse/skeletor/src/types/model.js").Options): any;
-        save(key?: string | import("@converse/skeletor/src/types/model.js").Attributes, val?: boolean | number | string | import("@converse/skeletor/src/types/model.js").Options, options?: import("@converse/skeletor/src/types/model.js").Options): any;
-        destroy(options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
-        url(): any;
-        parse(resp: import("@converse/skeletor/src/types/model.js").Options, options?: import("@converse/skeletor/src/types/model.js").Options): import("@converse/skeletor/src/types/model.js").Options;
-        isNew(): boolean;
-        isValid(options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
-        _validate(attrs: import("@converse/skeletor/src/types/model.js").Attributes, options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
-        on(name: string, callback: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context: any): any;
-        _events: any;
-        _listeners: {};
-        listenTo(obj: any, name: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
-        _listeningTo: {};
-        _listenId: any;
-        off(name: string, callback: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context?: any): any;
-        stopListening(obj?: any, name?: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
-        once(name: string, callback: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context: any): any;
-        listenToOnce(obj: any, name: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
-        trigger(name: string, ...args: any[]): any;
-        constructor: Function;
-        toString(): string;
-        toLocaleString(): string;
-        valueOf(): Object;
-        hasOwnProperty(v: PropertyKey): boolean;
-        isPrototypeOf(v: Object): boolean;
-        propertyIsEnumerable(v: PropertyKey): boolean;
-    };
-} & {
-    new (...args: any[]): {
-        initialize(): void;
-        rosterContactAdded: any;
-        contact: import("../roster/contact.js").default | import("../status/status.js").default;
-        setModelContact(jid: string): Promise<void>;
-        cid: any;
-        attributes: {};
-        validationError: string;
-        collection: any;
-        changed: {};
-        browserStorage: Storage;
-        _browserStorage: Storage;
-        readonly idAttribute: string;
-        readonly cidPrefix: string;
-        preinitialize(): void;
-        validate(attrs: object, options?: object): string;
-        toJSON(): any;
-        sync(method: "create" | "update" | "patch" | "delete" | "read", model: Model, options: import("@converse/skeletor/src/types/model.js").Options): any;
-        get(attr: string): any;
-        keys(): string[];
-        values(): any[];
-        pairs(): [string, any][];
-        entries(): [string, any][];
-        invert(): any;
-        pick(...args: any[]): any;
-        omit(...args: any[]): any;
-        isEmpty(): any;
-        has(attr: string): boolean;
-        matches(attrs: import("@converse/skeletor/src/types/model.js").Attributes): boolean;
-        set(key: string | any, val?: string | any, options?: import("@converse/skeletor/src/types/model.js").Options): false | any;
-        _changing: boolean;
-        _previousAttributes: any;
-        id: any;
-        _pending: boolean | import("@converse/skeletor/src/types/model.js").Options;
-        unset(attr: string, options?: import("@converse/skeletor/src/types/model.js").Options): false | any;
-        clear(options: import("@converse/skeletor/src/types/model.js").Options): false | any;
-        hasChanged(attr?: string): any;
-        changedAttributes(diff: any): any;
-        previous(attr?: string): any;
-        previousAttributes(): any;
-        fetch(options?: import("@converse/skeletor/src/types/model.js").Options): any;
-        save(key?: string | import("@converse/skeletor/src/types/model.js").Attributes, val?: boolean | number | string | import("@converse/skeletor/src/types/model.js").Options, options?: import("@converse/skeletor/src/types/model.js").Options): any;
-        destroy(options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
-        url(): any;
-        parse(resp: import("@converse/skeletor/src/types/model.js").Options, options?: import("@converse/skeletor/src/types/model.js").Options): import("@converse/skeletor/src/types/model.js").Options;
-        isNew(): boolean;
-        isValid(options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
-        _validate(attrs: import("@converse/skeletor/src/types/model.js").Attributes, options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
-        on(name: string, callback: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context: any): any;
-        _events: any;
-        _listeners: {};
-        listenTo(obj: any, name: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
-        _listeningTo: {};
-        _listenId: any;
-        off(name: string, callback: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context?: any): any;
-        stopListening(obj?: any, name?: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
-        once(name: string, callback: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context: any): any;
-        listenToOnce(obj: any, name: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
-        trigger(name: string, ...args: any[]): any;
-        constructor: Function;
-        toString(): string;
-        toLocaleString(): string;
-        valueOf(): Object;
-        hasOwnProperty(v: PropertyKey): boolean;
-        isPrototypeOf(v: Object): boolean;
-        propertyIsEnumerable(v: PropertyKey): boolean;
-    };
-} & {
-    new (...args: any[]): {
-        setColor(): Promise<void>;
-        getIdentifier(): any;
-        getColor(): Promise<string>;
-        getAvatarStyle(append_style?: string): Promise<string>;
-        cid: any;
-        attributes: {};
-        validationError: string;
-        collection: any;
-        changed: {};
-        browserStorage: Storage;
-        _browserStorage: Storage;
-        readonly idAttribute: string;
-        readonly cidPrefix: string;
-        preinitialize(): void;
-        initialize(): void;
-        validate(attrs: object, options?: object): string;
-        toJSON(): any;
-        sync(method: "create" | "update" | "patch" | "delete" | "read", model: Model, options: import("@converse/skeletor/src/types/model.js").Options): any;
-        get(attr: string): any;
-        keys(): string[];
-        values(): any[];
-        pairs(): [string, any][];
-        entries(): [string, any][];
-        invert(): any;
-        pick(...args: any[]): any;
-        omit(...args: any[]): any;
-        isEmpty(): any;
-        has(attr: string): boolean;
-        matches(attrs: import("@converse/skeletor/src/types/model.js").Attributes): boolean;
-        set(key: string | any, val?: string | any, options?: import("@converse/skeletor/src/types/model.js").Options): false | any;
-        _changing: boolean;
-        _previousAttributes: any;
-        id: any;
-        _pending: boolean | import("@converse/skeletor/src/types/model.js").Options;
-        unset(attr: string, options?: import("@converse/skeletor/src/types/model.js").Options): false | any;
-        clear(options: import("@converse/skeletor/src/types/model.js").Options): false | any;
-        hasChanged(attr?: string): any;
-        changedAttributes(diff: any): any;
-        previous(attr?: string): any;
-        previousAttributes(): any;
-        fetch(options?: import("@converse/skeletor/src/types/model.js").Options): any;
-        save(key?: string | import("@converse/skeletor/src/types/model.js").Attributes, val?: boolean | number | string | import("@converse/skeletor/src/types/model.js").Options, options?: import("@converse/skeletor/src/types/model.js").Options): any;
-        destroy(options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
-        url(): any;
-        parse(resp: import("@converse/skeletor/src/types/model.js").Options, options?: import("@converse/skeletor/src/types/model.js").Options): import("@converse/skeletor/src/types/model.js").Options;
-        isNew(): boolean;
-        isValid(options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
-        _validate(attrs: import("@converse/skeletor/src/types/model.js").Attributes, options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
-        on(name: string, callback: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context: any): any;
-        _events: any;
-        _listeners: {};
-        listenTo(obj: any, name: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
-        _listeningTo: {};
-        _listenId: any;
-        off(name: string, callback: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context?: any): any;
-        stopListening(obj?: any, name?: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
-        once(name: string, callback: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context: any): any;
-        listenToOnce(obj: any, name: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
-        trigger(name: string, ...args: any[]): any;
-        constructor: Function;
-        toString(): string;
-        toLocaleString(): string;
-        valueOf(): Object;
-        hasOwnProperty(v: PropertyKey): boolean;
-        isPrototypeOf(v: Object): boolean;
-        propertyIsEnumerable(v: PropertyKey): boolean;
-    };
-} & typeof Model;
 /**
  * Represents a (non-MUC) message.
  * These can be either `chat`, `normal` or `headline` messages.
@@ -213,88 +6,12 @@ declare const Message_base: {
  * @memberOf _converse
  * @example const msg = new Message({'message': 'hello world!'});
  */
-declare class Message extends Message_base {
-    /**
-     * @param {Model[]} [models]
-     * @param {object} [options]
-     */
-    constructor(models?: Model[], options?: object);
-    defaults(): {
-        msgid: string;
-        time: string;
-        is_ephemeral: boolean;
-    };
-    file: any;
-    /** @type {import('./types').MessageAttributes} */
-    attributes: import("./types").MessageAttributes;
+declare class Message extends BaseMessage<any> {
+    constructor(models?: import("@converse/skeletor").Model[], options?: object);
     initialize(): Promise<void>;
-    chatbox: any;
     initialized: any;
     setContact(): Promise<void>;
-    /**
-     * Sets an auto-destruct timer for this message, if it's is_ephemeral.
-     * @method _converse.Message#setTimerForEphemeralMessage
-     */
-    setTimerForEphemeralMessage(): void;
-    ephemeral_timer: NodeJS.Timeout;
-    checkValidity(): boolean;
-    /**
-     * Determines whether this messsage may be retracted by the current user.
-     * @method _converse.Messages#mayBeRetracted
-     * @returns { Boolean }
-     */
-    mayBeRetracted(): boolean;
-    safeDestroy(): void;
-    /**
-     * Returns a boolean indicating whether this message is ephemeral,
-     * meaning it will get automatically removed after ten seconds.
-     * @returns {boolean}
-     */
-    isEphemeral(): boolean;
-    /**
-     * Returns a boolean indicating whether this message is a XEP-0245 /me command.
-     * @returns {boolean}
-     */
-    isMeCommand(): boolean;
-    /**
-     * @returns {boolean}
-     */
-    isRetracted(): boolean;
-    /**
-     * Returns a boolean indicating whether this message is considered a followup
-     * message from the previous one. Followup messages are shown grouped together
-     * under one author heading.
-     * A message is considered a followup of it's predecessor when it's a chat
-     * message from the same author, within 10 minutes.
-     * @returns {boolean}
-     */
-    isFollowup(): boolean;
     getDisplayName(): any;
-    getMessageText(): any;
-    /**
-     * Send out an IQ stanza to request a file upload slot.
-     * https://xmpp.org/extensions/xep-0363.html#request
-     * @private
-     * @method _converse.Message#sendSlotRequestStanza
-     */
-    private sendSlotRequestStanza;
-    /**
-     * @param {Element} stanza
-     */
-    getUploadRequestMetadata(stanza: Element): {
-        headers: {
-            name: string;
-            value: string;
-        }[];
-    };
-    getRequestSlotURL(): Promise<any>;
-    upload_metadata: {
-        headers: {
-            name: string;
-            value: string;
-        }[];
-    };
-    uploadFile(): void;
 }
-import { Model } from '@converse/skeletor';
+import BaseMessage from '../../shared/message.js';
 //# sourceMappingURL=message.d.ts.map

+ 24 - 24
src/headless/types/plugins/chat/model.d.ts

@@ -86,32 +86,32 @@ declare const ChatBox_base: {
         messages: any;
         fetchMessages(): any;
         afterMessagesFetched(): void;
-        onMessage(_attrs_or_error: import("./types").MessageAttributes | Error): Promise<void>;
-        getUpdatedMessageAttributes(message: import("./message.js").default, attrs: import("./types").MessageAttributes): object;
-        updateMessage(message: import("./message.js").default, attrs: import("./types").MessageAttributes): void;
-        handleCorrection(attrs: import("./types").MessageAttributes | import("../muc/types.js").MUCMessageAttributes): Promise<import("./message.js").default | void>;
-        queueMessage(attrs: import("./types").MessageAttributes): any;
+        onMessage(_attrs_or_error: import("../../shared/types").MessageAttributes | Error): Promise<void>;
+        getUpdatedMessageAttributes(message: import("../../shared/message.js").default<any>, attrs: import("../../shared/types").MessageAttributes): object;
+        updateMessage(message: import("../../shared/message.js").default<any>, attrs: import("../../shared/types").MessageAttributes): void;
+        handleCorrection(attrs: import("../../shared/types").MessageAttributes | import("../muc/types.js").MUCMessageAttributes): Promise<import("../../shared/message.js").default<any> | void>;
+        queueMessage(attrs: import("../../shared/types").MessageAttributes): any;
         msg_chain: any;
-        getOutgoingMessageAttributes(_attrs?: import("./types").MessageAttributes): Promise<import("./types").MessageAttributes>;
-        sendMessage(attrs?: any): Promise<import("./message.js").default>;
-        retractOwnMessage(message: import("./message.js").default): void;
+        getOutgoingMessageAttributes(_attrs?: import("../../shared/types").MessageAttributes): Promise<import("../../shared/types").MessageAttributes>;
+        sendMessage(attrs?: any): Promise<import("../../shared/message.js").default<any>>;
+        retractOwnMessage(message: import("../../shared/message.js").default<any>): void;
         sendFiles(files: File[]): Promise<void>;
         setEditable(attrs: any, send_time: string): void;
         setChatState(state: string, options?: object): any;
         chat_state_timeout: NodeJS.Timeout;
-        onMessageAdded(message: import("./message.js").default): void;
-        onMessageUploadChanged(message: import("./message.js").default): Promise<void>;
+        onMessageAdded(message: import("../../shared/message.js").default<any>): void;
+        onMessageUploadChanged(message: import("../../shared/message.js").default<any>): Promise<void>;
         onScrolledChanged(): void;
         pruneHistoryWhenScrolledDown(): void;
-        shouldShowErrorMessage(attrs: import("./types").MessageAttributes): Promise<boolean>;
+        shouldShowErrorMessage(attrs: import("../../shared/types").MessageAttributes): Promise<boolean>;
         clearMessages(): Promise<void>;
         editEarlierMessage(): void;
         editLaterMessage(): any;
         getOldestMessage(): any;
         getMostRecentMessage(): any;
         getMessageReferencedByError(attrs: object): any;
-        findDanglingRetraction(attrs: object): import("./message.js").default | null;
-        getDuplicateMessage(attrs: object): import("./message.js").default;
+        findDanglingRetraction(attrs: object): import("../../shared/message.js").default<any> | null;
+        getDuplicateMessage(attrs: object): import("../../shared/message.js").default<any>;
         getOriginIdQueryAttrs(attrs: object): {
             origin_id: any;
             from: any;
@@ -121,15 +121,15 @@ declare const ChatBox_base: {
             from: any;
             msgid: any;
         };
-        sendMarkerForMessage(msg: import("./message.js").default, type?: ("received" | "displayed" | "acknowledged"), force?: boolean): Promise<void>;
-        handleUnreadMessage(message: import("./message.js").default): void;
-        getErrorAttributesForMessage(message: import("./message.js").default, attrs: import("./types").MessageAttributes): Promise<any>;
+        sendMarkerForMessage(msg: import("../../shared/message.js").default<any>, type?: ("received" | "displayed" | "acknowledged"), force?: boolean): Promise<void>;
+        handleUnreadMessage(message: import("../../shared/message.js").default<any>): void;
+        getErrorAttributesForMessage(message: import("../../shared/message.js").default<any>, attrs: import("../../shared/types").MessageAttributes): Promise<any>;
         handleErrorMessageStanza(stanza: Element): Promise<void>;
-        incrementUnreadMsgsCounter(message: import("./message.js").default): void;
+        incrementUnreadMsgsCounter(message: import("../../shared/message.js").default<any>): void;
         clearUnreadMsgCounter(): void;
-        handleRetraction(attrs: import("./types").MessageAttributes): Promise<boolean>;
-        handleReceipt(attrs: import("./types").MessageAttributes): boolean;
-        createMessageStanza(message: import("./message.js").default): Promise<any>;
+        handleRetraction(attrs: import("../../shared/types").MessageAttributes): Promise<boolean>;
+        handleReceipt(attrs: import("../../shared/types").MessageAttributes): boolean;
+        createMessageStanza(message: import("../../shared/message.js").default<any>): Promise<any>;
         pruneHistory(): void;
         debouncedPruneHistory: import("lodash").DebouncedFunc<() => void>;
         isScrolledUp(): any;
@@ -342,7 +342,7 @@ declare class ChatBox extends ChatBox_base {
     /**
      * @typedef {import('./message.js').default} Message
      * @typedef {import('../muc/muc.js').default} MUC
-     * @typedef {import('./types').MessageAttributes} MessageAttributes
+     * @typedef {import('../../shared/types').MessageAttributes} MessageAttributes
      * @typedef {import('../../shared/errors').StanzaParseError} StanzaParseError
      */
     defaults(): {
@@ -360,7 +360,7 @@ declare class ChatBox extends ChatBox_base {
     /**
      * @param {MessageAttributes|StanzaParseError} attrs_or_error
      */
-    onMessage(attrs_or_error: import("./types").MessageAttributes | import("../../shared/errors").StanzaParseError): Promise<void>;
+    onMessage(attrs_or_error: import("../../shared/types").MessageAttributes | import("../../shared/errors").StanzaParseError): Promise<void>;
     /**
      * @param {import('../roster/presence').default} item
      */
@@ -378,12 +378,12 @@ declare class ChatBox extends ChatBox_base {
     /**
      * @param {MessageAttributes} attrs
      */
-    handleChatMarker(attrs: import("./types").MessageAttributes): boolean;
+    handleChatMarker(attrs: import("../../shared/types").MessageAttributes): boolean;
     /**
      * @param {MessageAttributes} [attrs]
      * @return {Promise<MessageAttributes>}
      */
-    getOutgoingMessageAttributes(attrs?: import("./types").MessageAttributes): Promise<import("./types").MessageAttributes>;
+    getOutgoingMessageAttributes(attrs?: import("../../shared/types").MessageAttributes): Promise<import("../../shared/types").MessageAttributes>;
     canPostMessages(): boolean;
 }
 import ChatBoxBase from '../../shared/chatbox.js';

+ 2 - 2
src/headless/types/plugins/chat/parsers.d.ts

@@ -1,8 +1,8 @@
 /**
  * Parses a passed in message stanza and returns an object of attributes.
  * @param {Element} stanza - The message stanza
- * @returns {Promise<import('./types.ts').MessageAttributes|StanzaParseError>}
+ * @returns {Promise<import('../../shared/types.ts').MessageAttributes|StanzaParseError>}
  */
-export function parseMessage(stanza: Element): Promise<import("./types.ts").MessageAttributes | StanzaParseError>;
+export function parseMessage(stanza: Element): Promise<import("../../shared/types.ts").MessageAttributes | StanzaParseError>;
 import { StanzaParseError } from '../../shared/errors.js';
 //# sourceMappingURL=parsers.d.ts.map

+ 0 - 57
src/headless/types/plugins/chat/types.d.ts

@@ -1,64 +1,7 @@
-import { EncryptionAttrs } from "../../shared/types";
 export type Reference = {
     begin: number;
     end: number;
     type: string;
     uri: string;
 };
-export type MessageErrorAttributes = {
-    is_error: boolean;
-    error: string;
-    errors: {
-        name: string;
-        xmlns: string;
-    }[];
-    error_condition: string;
-    error_text: string;
-    error_type: string;
-};
-export type MessageAttributes = EncryptionAttrs & MessageErrorAttributes & {
-    body: string;
-    chat_state: string;
-    contact_jid: string;
-    editable: boolean;
-    edited: string;
-    from: string;
-    message?: string;
-    fullname: string;
-    is_archived: boolean;
-    is_carbon: boolean;
-    is_delayed: boolean;
-    is_encrypted: boolean;
-    is_headline: boolean;
-    is_markable: boolean;
-    is_marker: boolean;
-    is_only_emojis: boolean;
-    is_spoiler: boolean;
-    is_tombstone: boolean;
-    is_unstyled: boolean;
-    is_valid_receipt_request: boolean;
-    marker: string;
-    marker_id: string;
-    msgid: string;
-    nick: string;
-    ogp_for_id?: string;
-    oob_desc: string;
-    oob_url: string;
-    origin_id: string;
-    plaintext: string;
-    receipt_id: string;
-    received: string;
-    references: Array<Reference>;
-    replace_id: string;
-    retracted: string;
-    retracted_id: string;
-    sender: 'me' | 'them';
-    spoiler_hint: string;
-    stanza_id: string;
-    subject: string;
-    thread: string;
-    time: string;
-    to: string;
-    type: string;
-};
 //# sourceMappingURL=types.d.ts.map

+ 1 - 1
src/headless/types/plugins/chat/utils.d.ts

@@ -19,7 +19,7 @@ export function handleMessageStanza(stanza: Element | Builder): Promise<true | v
  */
 export function enableCarbons(): Promise<void>;
 export type ChatBox = import("./model.js").default;
-export type MessageAttributes = import("./types.ts").MessageAttributes;
+export type MessageAttributes = import("../../shared/types.ts").MessageAttributes;
 export type StanzaParseError = import("../../shared/errors").StanzaParseError;
 export type Builder = import("strophe.js").Builder;
 import { Model } from '@converse/skeletor';

+ 4 - 77
src/headless/types/plugins/muc/message.d.ts

@@ -1,80 +1,8 @@
 export default MUCMessage;
-declare const MUCMessage_base: {
-    new (...args: any[]): {
-        _vcard: import("../vcard/vcard.js").default;
-        lazy_load_vcard: boolean;
-        initialize(): void;
-        readonly vcard: import("../vcard/vcard.js").default;
-        getVCard(create?: boolean): Promise<import("../vcard/vcard.js").default | null>;
-        cid: any;
-        attributes: {};
-        validationError: string;
-        collection: any;
-        changed: {};
-        browserStorage: Storage;
-        _browserStorage: Storage;
-        readonly idAttribute: string;
-        readonly cidPrefix: string;
-        preinitialize(): void;
-        validate(attrs: object, options?: object): string;
-        toJSON(): any;
-        sync(method: "create" | "update" | "patch" | "delete" | "read", model: import("@converse/skeletor").Model, options: import("@converse/skeletor/src/types/model.js").Options): any;
-        get(attr: string): any;
-        keys(): string[];
-        values(): any[];
-        pairs(): [string, any][];
-        entries(): [string, any][];
-        invert(): any;
-        pick(...args: any[]): any;
-        omit(...args: any[]): any;
-        isEmpty(): any;
-        has(attr: string): boolean;
-        matches(attrs: import("@converse/skeletor/src/types/model.js").Attributes): boolean;
-        set(key: string | any, val?: string | any, options?: import("@converse/skeletor/src/types/model.js").Options): false | any;
-        _changing: boolean;
-        _previousAttributes: any;
-        id: any;
-        _pending: boolean | import("@converse/skeletor/src/types/model.js").Options;
-        unset(attr: string, options?: import("@converse/skeletor/src/types/model.js").Options): false | any;
-        clear(options: import("@converse/skeletor/src/types/model.js").Options): false | any;
-        hasChanged(attr?: string): any;
-        changedAttributes(diff: any): any;
-        previous(attr?: string): any;
-        previousAttributes(): any;
-        fetch(options?: import("@converse/skeletor/src/types/model.js").Options): any;
-        save(key?: string | import("@converse/skeletor/src/types/model.js").Attributes, val?: boolean | number | string | import("@converse/skeletor/src/types/model.js").Options, options?: import("@converse/skeletor/src/types/model.js").Options): any;
-        destroy(options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
-        url(): any;
-        parse(resp: import("@converse/skeletor/src/types/model.js").Options, options?: import("@converse/skeletor/src/types/model.js").Options): import("@converse/skeletor/src/types/model.js").Options;
-        isNew(): boolean;
-        isValid(options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
-        _validate(attrs: import("@converse/skeletor/src/types/model.js").Attributes, options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
-        on(name: string, callback: (event: any, model: import("@converse/skeletor").Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context: any): any;
-        _events: any;
-        _listeners: {};
-        listenTo(obj: any, name: string, callback?: (event: any, model: import("@converse/skeletor").Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
-        _listeningTo: {};
-        _listenId: any;
-        off(name: string, callback: (event: any, model: import("@converse/skeletor").Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context?: any): any;
-        stopListening(obj?: any, name?: string, callback?: (event: any, model: import("@converse/skeletor").Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
-        once(name: string, callback: (event: any, model: import("@converse/skeletor").Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context: any): any;
-        listenToOnce(obj: any, name: string, callback?: (event: any, model: import("@converse/skeletor").Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
-        trigger(name: string, ...args: any[]): any;
-        constructor: Function;
-        toString(): string;
-        toLocaleString(): string;
-        valueOf(): Object;
-        hasOwnProperty(v: PropertyKey): boolean;
-        isPrototypeOf(v: Object): boolean;
-        propertyIsEnumerable(v: PropertyKey): boolean;
-    };
-} & typeof Message;
-declare class MUCMessage extends MUCMessage_base {
-    /**
-     * @typedef {import('./occupant').default} MUCOccupant
-     */
-    initialize(): Promise<void>;
+declare class MUCMessage extends BaseMessage<any> {
+    constructor(models?: import("@converse/skeletor").Model[], options?: object);
     get occupants(): any;
+    getDisplayName(): any;
     /**
      * Determines whether this messsage may be moderated,
      * based on configuration settings and server support.
@@ -82,7 +10,6 @@ declare class MUCMessage extends MUCMessage_base {
      * @returns {Promise<boolean>}
      */
     mayBeModerated(): Promise<boolean>;
-    checkValidity(): any;
     onOccupantRemoved(): void;
     /**
      * @param {MUCOccupant} [occupant]
@@ -96,5 +23,5 @@ declare class MUCMessage extends MUCMessage_base {
     setOccupant(occupant?: import("./occupant").default): import("./occupant").default;
     occupant: any;
 }
-import Message from '../chat/message.js';
+import BaseMessage from '../../shared/message.js';
 //# sourceMappingURL=message.d.ts.map

+ 33 - 32
src/headless/types/plugins/muc/muc.d.ts

@@ -86,32 +86,32 @@ declare const MUC_base: {
         messages: any;
         fetchMessages(): any;
         afterMessagesFetched(): void;
-        onMessage(_attrs_or_error: import("../chat/types").MessageAttributes | Error): Promise<void>;
-        getUpdatedMessageAttributes(message: import("../chat/message.js").default, attrs: import("../chat/types").MessageAttributes): object;
-        updateMessage(message: import("../chat/message.js").default, attrs: import("../chat/types").MessageAttributes): void;
-        handleCorrection(attrs: import("../chat/types").MessageAttributes | import("./types").MUCMessageAttributes): Promise<import("../chat/message.js").default | void>;
-        queueMessage(attrs: import("../chat/types").MessageAttributes): any;
+        onMessage(_attrs_or_error: import("../../shared/types").MessageAttributes | Error): Promise<void>;
+        getUpdatedMessageAttributes(message: BaseMessage<any>, attrs: import("../../shared/types").MessageAttributes): object;
+        updateMessage(message: BaseMessage<any>, attrs: import("../../shared/types").MessageAttributes): void;
+        handleCorrection(attrs: import("../../shared/types").MessageAttributes | import("./types").MUCMessageAttributes): Promise<BaseMessage<any> | void>;
+        queueMessage(attrs: import("../../shared/types").MessageAttributes): any;
         msg_chain: any;
-        getOutgoingMessageAttributes(_attrs?: import("../chat/types").MessageAttributes): Promise<import("../chat/types").MessageAttributes>;
-        sendMessage(attrs?: any): Promise<import("../chat/message.js").default>;
-        retractOwnMessage(message: import("../chat/message.js").default): void;
+        getOutgoingMessageAttributes(_attrs?: import("../../shared/types").MessageAttributes): Promise<import("../../shared/types").MessageAttributes>;
+        sendMessage(attrs?: any): Promise<BaseMessage<any>>;
+        retractOwnMessage(message: BaseMessage<any>): void;
         sendFiles(files: File[]): Promise<void>;
         setEditable(attrs: any, send_time: string): void;
         setChatState(state: string, options?: object): any;
         chat_state_timeout: NodeJS.Timeout;
-        onMessageAdded(message: import("../chat/message.js").default): void;
-        onMessageUploadChanged(message: import("../chat/message.js").default): Promise<void>;
+        onMessageAdded(message: BaseMessage<any>): void;
+        onMessageUploadChanged(message: BaseMessage<any>): Promise<void>;
         onScrolledChanged(): void;
         pruneHistoryWhenScrolledDown(): void;
-        shouldShowErrorMessage(attrs: import("../chat/types").MessageAttributes): Promise<boolean>;
+        shouldShowErrorMessage(attrs: import("../../shared/types").MessageAttributes): Promise<boolean>;
         clearMessages(): Promise<void>;
         editEarlierMessage(): void;
         editLaterMessage(): any;
         getOldestMessage(): any;
         getMostRecentMessage(): any;
         getMessageReferencedByError(attrs: object): any;
-        findDanglingRetraction(attrs: object): import("../chat/message.js").default | null;
-        getDuplicateMessage(attrs: object): import("../chat/message.js").default;
+        findDanglingRetraction(attrs: object): BaseMessage<any> | null;
+        getDuplicateMessage(attrs: object): BaseMessage<any>;
         getOriginIdQueryAttrs(attrs: object): {
             origin_id: any;
             from: any;
@@ -121,15 +121,15 @@ declare const MUC_base: {
             from: any;
             msgid: any;
         };
-        sendMarkerForMessage(msg: import("../chat/message.js").default, type?: ("received" | "displayed" | "acknowledged"), force?: boolean): Promise<void>;
-        handleUnreadMessage(message: import("../chat/message.js").default): void;
-        getErrorAttributesForMessage(message: import("../chat/message.js").default, attrs: import("../chat/types").MessageAttributes): Promise<any>;
+        sendMarkerForMessage(msg: BaseMessage<any>, type?: ("received" | "displayed" | "acknowledged"), force?: boolean): Promise<void>;
+        handleUnreadMessage(message: BaseMessage<any>): void;
+        getErrorAttributesForMessage(message: BaseMessage<any>, attrs: import("../../shared/types").MessageAttributes): Promise<any>;
         handleErrorMessageStanza(stanza: Element): Promise<void>;
-        incrementUnreadMsgsCounter(message: import("../chat/message.js").default): void;
+        incrementUnreadMsgsCounter(message: BaseMessage<any>): void;
         clearUnreadMsgCounter(): void;
-        handleRetraction(attrs: import("../chat/types").MessageAttributes): Promise<boolean>;
-        handleReceipt(attrs: import("../chat/types").MessageAttributes): boolean;
-        createMessageStanza(message: import("../chat/message.js").default): Promise<any>;
+        handleRetraction(attrs: import("../../shared/types").MessageAttributes): Promise<boolean>;
+        handleReceipt(attrs: import("../../shared/types").MessageAttributes): boolean;
+        createMessageStanza(message: BaseMessage<any>): Promise<any>;
         pruneHistory(): void;
         debouncedPruneHistory: import("lodash").DebouncedFunc<() => void>;
         isScrolledUp(): any;
@@ -277,7 +277,7 @@ declare class MUC extends MUC_base {
      * @typedef {import('./occupant.js').default} MUCOccupant
      * @typedef {import('./affiliations/utils.js').NonOutcastAffiliation} NonOutcastAffiliation
      * @typedef {import('./types').MemberListItem} MemberListItem
-     * @typedef {import('../chat/types').MessageAttributes} MessageAttributes
+     * @typedef {import('../../shared/types').MessageAttributes} MessageAttributes
      * @typedef {import('./types').MUCMessageAttributes} MUCMessageAttributes
      * @typedef {import('./types').MUCPresenceAttributes} MUCPresenceAttributes
      * @typedef {module:shared.converse.UserMessage} UserMessage
@@ -429,9 +429,9 @@ declare class MUC extends MUC_base {
     sendTimedMessage(message: import("strophe.js").Builder | Element): Promise<Element> | Promise<TimeoutError>;
     /**
      * Retract one of your messages in this groupchat
-     * @param {MUCMessage} message - The message which we're retracting.
+     * @param {BaseMessage} message - The message which we're retracting.
      */
-    retractOwnMessage(message: import("./message.js").default): Promise<void>;
+    retractOwnMessage(message: BaseMessage<any>): Promise<void>;
     /**
      * Retract someone else's message in this groupchat.
      * @param {MUCMessage} message - The message which we're retracting.
@@ -498,7 +498,7 @@ declare class MUC extends MUC_base {
     /**
      * @param {MessageAttributes} [attrs] - A map of attributes to be saved on the message
      */
-    getOutgoingMessageAttributes(attrs?: import("../chat/types").MessageAttributes): Promise<import("../chat/types").MessageAttributes>;
+    getOutgoingMessageAttributes(attrs?: import("../../shared/types").MessageAttributes): Promise<import("../../shared/types").MessageAttributes>;
     /**
      * Utility method to construct the JID for the current user as occupant of the groupchat.
      * @returns {string} - The groupchat JID with the user's nickname added at the end.
@@ -804,12 +804,12 @@ declare class MUC extends MUC_base {
      * @param {MessageAttributes} attrs
      * @returns {boolean}
      */
-    handleMUCPrivateMessage(attrs: import("../chat/types").MessageAttributes): boolean;
+    handleMUCPrivateMessage(attrs: import("../../shared/types").MessageAttributes): boolean;
     /**
      * @param {MessageAttributes} attrs
      * @returns {boolean}
      */
-    handleMetadataFastening(attrs: import("../chat/types").MessageAttributes): boolean;
+    handleMetadataFastening(attrs: import("../../shared/types").MessageAttributes): boolean;
     /**
      * Given {@link MessageAttributes} look for XEP-0316 Room Notifications and create info
      * messages for them.
@@ -822,9 +822,9 @@ declare class MUC extends MUC_base {
      * passed in attributes map.
      * @param {object} attrs - Attributes representing a received
      *  message, as returned by {@link parseMUCMessage}
-     * @returns {Message}
+     * @returns {MUCMessage|BaseMessage}
      */
-    getDuplicateMessage(attrs: object): import("../chat/message.js").default;
+    getDuplicateMessage(attrs: object): import("./message.js").default | BaseMessage<any>;
     /**
      * Handler for all MUC messages sent to this groupchat. This method
      * shouldn't be called directly, instead {@link MUC#queueMessage}
@@ -911,16 +911,17 @@ declare class MUC extends MUC_base {
     /**
      * Returns a boolean to indicate whether the current user
      * was mentioned in a message.
-     * @param {MUCMessage} message - The text message
+     * @param {BaseMessage} message - The text message
      */
-    isUserMentioned(message: import("./message.js").default): any;
+    isUserMentioned(message: BaseMessage<any>): any;
     /**
-     * @param {MUCMessage} message - The text message
+     * @param {BaseMessage} message - The text message
      */
-    incrementUnreadMsgsCounter(message: import("./message.js").default): void;
+    incrementUnreadMsgsCounter(message: BaseMessage<any>): void;
     clearUnreadMsgCounter(): Promise<void>;
 }
 import { Model } from '@converse/skeletor';
+import BaseMessage from '../../shared/message';
 import ChatBoxBase from '../../shared/chatbox';
 import MUCSession from './session';
 import { TimeoutError } from '../../shared/errors.js';

+ 26 - 22
src/headless/types/plugins/muc/occupant.d.ts

@@ -86,32 +86,32 @@ declare const MUCOccupant_base: {
         messages: any;
         fetchMessages(): any;
         afterMessagesFetched(): void;
-        onMessage(_attrs_or_error: import("../chat/types").MessageAttributes | Error): Promise<void>;
-        getUpdatedMessageAttributes(message: import("../chat/message").default, attrs: import("../chat/types").MessageAttributes): object;
-        updateMessage(message: import("../chat/message").default, attrs: import("../chat/types").MessageAttributes): void;
-        handleCorrection(attrs: import("../chat/types").MessageAttributes | import("./types").MUCMessageAttributes): Promise<import("../chat/message").default | void>;
-        queueMessage(attrs: import("../chat/types").MessageAttributes): any;
+        onMessage(_attrs_or_error: import("../../shared/types").MessageAttributes | Error): Promise<void>;
+        getUpdatedMessageAttributes(message: import("../../shared/message").default<any>, attrs: import("../../shared/types").MessageAttributes): object;
+        updateMessage(message: import("../../shared/message").default<any>, attrs: import("../../shared/types").MessageAttributes): void;
+        handleCorrection(attrs: import("../../shared/types").MessageAttributes | import("./types").MUCMessageAttributes): Promise<import("../../shared/message").default<any> | void>;
+        queueMessage(attrs: import("../../shared/types").MessageAttributes): any;
         msg_chain: any;
-        getOutgoingMessageAttributes(_attrs?: import("../chat/types").MessageAttributes): Promise<import("../chat/types").MessageAttributes>;
-        sendMessage(attrs?: any): Promise<import("../chat/message").default>;
-        retractOwnMessage(message: import("../chat/message").default): void;
+        getOutgoingMessageAttributes(_attrs?: import("../../shared/types").MessageAttributes): Promise<import("../../shared/types").MessageAttributes>;
+        sendMessage(attrs?: any): Promise<import("../../shared/message").default<any>>;
+        retractOwnMessage(message: import("../../shared/message").default<any>): void;
         sendFiles(files: File[]): Promise<void>;
         setEditable(attrs: any, send_time: string): void;
         setChatState(state: string, options?: object): any;
         chat_state_timeout: NodeJS.Timeout;
-        onMessageAdded(message: import("../chat/message").default): void;
-        onMessageUploadChanged(message: import("../chat/message").default): Promise<void>;
+        onMessageAdded(message: import("../../shared/message").default<any>): void;
+        onMessageUploadChanged(message: import("../../shared/message").default<any>): Promise<void>;
         onScrolledChanged(): void;
         pruneHistoryWhenScrolledDown(): void;
-        shouldShowErrorMessage(attrs: import("../chat/types").MessageAttributes): Promise<boolean>;
+        shouldShowErrorMessage(attrs: import("../../shared/types").MessageAttributes): Promise<boolean>;
         clearMessages(): Promise<void>;
         editEarlierMessage(): void;
         editLaterMessage(): any;
         getOldestMessage(): any;
         getMostRecentMessage(): any;
         getMessageReferencedByError(attrs: object): any;
-        findDanglingRetraction(attrs: object): import("../chat/message").default | null;
-        getDuplicateMessage(attrs: object): import("../chat/message").default;
+        findDanglingRetraction(attrs: object): import("../../shared/message").default<any> | null;
+        getDuplicateMessage(attrs: object): import("../../shared/message").default<any>;
         getOriginIdQueryAttrs(attrs: object): {
             origin_id: any;
             from: any;
@@ -121,15 +121,15 @@ declare const MUCOccupant_base: {
             from: any;
             msgid: any;
         };
-        sendMarkerForMessage(msg: import("../chat/message").default, type?: ("received" | "displayed" | "acknowledged"), force?: boolean): Promise<void>;
-        handleUnreadMessage(message: import("../chat/message").default): void;
-        getErrorAttributesForMessage(message: import("../chat/message").default, attrs: import("../chat/types").MessageAttributes): Promise<any>;
+        sendMarkerForMessage(msg: import("../../shared/message").default<any>, type?: ("received" | "displayed" | "acknowledged"), force?: boolean): Promise<void>;
+        handleUnreadMessage(message: import("../../shared/message").default<any>): void;
+        getErrorAttributesForMessage(message: import("../../shared/message").default<any>, attrs: import("../../shared/types").MessageAttributes): Promise<any>;
         handleErrorMessageStanza(stanza: Element): Promise<void>;
-        incrementUnreadMsgsCounter(message: import("../chat/message").default): void;
+        incrementUnreadMsgsCounter(message: import("../../shared/message").default<any>): void;
         clearUnreadMsgCounter(): void;
-        handleRetraction(attrs: import("../chat/types").MessageAttributes): Promise<boolean>;
-        handleReceipt(attrs: import("../chat/types").MessageAttributes): boolean;
-        createMessageStanza(message: import("../chat/message").default): Promise<any>;
+        handleRetraction(attrs: import("../../shared/types").MessageAttributes): Promise<boolean>;
+        handleReceipt(attrs: import("../../shared/types").MessageAttributes): boolean;
+        createMessageStanza(message: import("../../shared/message").default<any>): Promise<any>;
         pruneHistory(): void;
         debouncedPruneHistory: import("lodash").DebouncedFunc<() => void>;
         isScrolledUp(): any;
@@ -271,7 +271,7 @@ declare const MUCOccupant_base: {
  */
 declare class MUCOccupant extends MUCOccupant_base {
     /**
-     * @typedef {import('../chat/types').MessageAttributes} MessageAttributes
+     * @typedef {import('../../shared/types').MessageAttributes} MessageAttributes
      * @typedef {import('../../shared/errors').StanzaParseError} StanzaParseError
      */
     initialize(): Promise<void>;
@@ -290,7 +290,7 @@ declare class MUCOccupant extends MUCOccupant_base {
      * This method houldn't be called directly, instead {@link MUC#queueMessage} should be called.
      * @param {MessageAttributes|StanzaParseError} attrs_or_error
      */
-    onMessage(attrs_or_error: import("../chat/types").MessageAttributes | import("../../shared/errors").StanzaParseError): Promise<void>;
+    onMessage(attrs_or_error: import("../../shared/types").MessageAttributes | import("../../shared/errors").StanzaParseError): Promise<void>;
     /**
      * Return roles which may be assigned to this occupant
      * @returns {typeof ROLES} - An array of assignable roles
@@ -304,6 +304,10 @@ declare class MUCOccupant extends MUCOccupant_base {
     isMember(): boolean;
     isModerator(): boolean;
     isSelf(): any;
+    /**
+     * @param {import('../chat/message').default} message - The message object
+     */
+    createMessageStanza(message: import("../chat/message").default): Promise<any>;
 }
 import { Model } from "@converse/skeletor";
 import MUCMessages from "./messages.js";

+ 1 - 1
src/headless/types/plugins/muc/types.d.ts

@@ -1,5 +1,5 @@
 import { CHAT_STATES } from '../../shared/constants';
-import { MessageAttributes } from '../chat/types';
+import { MessageAttributes } from '../../shared/types';
 import MUC from './muc';
 export type MUCStatusCode = '100' | '101' | '102' | '103' | '104' | '110' | '170' | '171' | '172' | '173' | '174' | '201' | '210' | '301' | '303' | '307' | '321' | '322' | '332' | '333';
 export type DefaultMUCAttributes = {

+ 2 - 2
src/headless/types/plugins/vcard/utils.d.ts

@@ -11,9 +11,9 @@ export function onOccupantAvatarChanged(occupant: MUCOccupant): void;
 /**
  * @param {Model|MUCOccupant|MUCMessage} model
  * @param {boolean} [create=true]
- * @returns {Promise<VCard>}
+ * @returns {Promise<VCard|null>}
  */
-export function getVCardForModel(model: Model | MUCOccupant | MUCMessage, create?: boolean): Promise<VCard>;
+export function getVCardForModel(model: Model | MUCOccupant | MUCMessage, create?: boolean): Promise<VCard | null>;
 /**
  * @param {MUCOccupant} occupant
  * @param {boolean} [create=true]

+ 2 - 2
src/headless/types/shared/actions.d.ts

@@ -29,8 +29,8 @@ export function sendChatState(jid: string, chat_state: string): void;
 /**
  * Sends a message stanza to retract a message in this chat
  * @param {string} jid
- * @param {import('../plugins/chat/message').default} message - The message which we're retracting.
+ * @param {import('../shared/message').default} message - The message which we're retracting.
  * @param {string} retraction_id - Unique ID for the retraction message
  */
-export function sendRetractionMessage(jid: string, message: import("../plugins/chat/message").default, retraction_id: string): any;
+export function sendRetractionMessage(jid: string, message: import("../shared/message").default<any>, retraction_id: string): any;
 //# sourceMappingURL=actions.d.ts.map

+ 20 - 20
src/headless/types/shared/chatbox.d.ts

@@ -16,32 +16,32 @@ declare const ChatBoxBase_base: {
         messages: any;
         fetchMessages(): any;
         afterMessagesFetched(): void;
-        onMessage(_attrs_or_error: import("../plugins/chat/types.js").MessageAttributes | Error): Promise<void>;
-        getUpdatedMessageAttributes(message: import("../index.js").Message, attrs: import("../plugins/chat/types.js").MessageAttributes): object;
-        updateMessage(message: import("../index.js").Message, attrs: import("../plugins/chat/types.js").MessageAttributes): void;
-        handleCorrection(attrs: import("../plugins/chat/types.js").MessageAttributes | import("../plugins/muc/types.js").MUCMessageAttributes): Promise<import("../index.js").Message | void>;
-        queueMessage(attrs: import("../plugins/chat/types.js").MessageAttributes): any;
+        onMessage(_attrs_or_error: import("./types.js").MessageAttributes | Error): Promise<void>;
+        getUpdatedMessageAttributes(message: import("./message.js").default<any>, attrs: import("./types.js").MessageAttributes): object;
+        updateMessage(message: import("./message.js").default<any>, attrs: import("./types.js").MessageAttributes): void;
+        handleCorrection(attrs: import("./types.js").MessageAttributes | import("../plugins/muc/types.js").MUCMessageAttributes): Promise<import("./message.js").default<any> | void>;
+        queueMessage(attrs: import("./types.js").MessageAttributes): any;
         msg_chain: any;
-        getOutgoingMessageAttributes(_attrs?: import("../plugins/chat/types.js").MessageAttributes): Promise<import("../plugins/chat/types.js").MessageAttributes>;
-        sendMessage(attrs?: any): Promise<import("../index.js").Message>;
-        retractOwnMessage(message: import("../index.js").Message): void;
+        getOutgoingMessageAttributes(_attrs?: import("./types.js").MessageAttributes): Promise<import("./types.js").MessageAttributes>;
+        sendMessage(attrs?: any): Promise<import("./message.js").default<any>>;
+        retractOwnMessage(message: import("./message.js").default<any>): void;
         sendFiles(files: File[]): Promise<void>;
         setEditable(attrs: any, send_time: string): void;
         setChatState(state: string, options?: object): any;
         chat_state_timeout: NodeJS.Timeout;
-        onMessageAdded(message: import("../index.js").Message): void;
-        onMessageUploadChanged(message: import("../index.js").Message): Promise<void>;
+        onMessageAdded(message: import("./message.js").default<any>): void;
+        onMessageUploadChanged(message: import("./message.js").default<any>): Promise<void>;
         onScrolledChanged(): void;
         pruneHistoryWhenScrolledDown(): void;
-        shouldShowErrorMessage(attrs: import("../plugins/chat/types.js").MessageAttributes): Promise<boolean>;
+        shouldShowErrorMessage(attrs: import("./types.js").MessageAttributes): Promise<boolean>;
         clearMessages(): Promise<void>;
         editEarlierMessage(): void;
         editLaterMessage(): any;
         getOldestMessage(): any;
         getMostRecentMessage(): any;
         getMessageReferencedByError(attrs: object): any;
-        findDanglingRetraction(attrs: object): import("../index.js").Message | null;
-        getDuplicateMessage(attrs: object): import("../index.js").Message;
+        findDanglingRetraction(attrs: object): import("./message.js").default<any> | null;
+        getDuplicateMessage(attrs: object): import("./message.js").default<any>;
         getOriginIdQueryAttrs(attrs: object): {
             origin_id: any;
             from: any;
@@ -51,15 +51,15 @@ declare const ChatBoxBase_base: {
             from: any;
             msgid: any;
         };
-        sendMarkerForMessage(msg: import("../index.js").Message, type?: ("received" | "displayed" | "acknowledged"), force?: boolean): Promise<void>;
-        handleUnreadMessage(message: import("../index.js").Message): void;
-        getErrorAttributesForMessage(message: import("../index.js").Message, attrs: import("../plugins/chat/types.js").MessageAttributes): Promise<any>;
+        sendMarkerForMessage(msg: import("./message.js").default<any>, type?: ("received" | "displayed" | "acknowledged"), force?: boolean): Promise<void>;
+        handleUnreadMessage(message: import("./message.js").default<any>): void;
+        getErrorAttributesForMessage(message: import("./message.js").default<any>, attrs: import("./types.js").MessageAttributes): Promise<any>;
         handleErrorMessageStanza(stanza: Element): Promise<void>;
-        incrementUnreadMsgsCounter(message: import("../index.js").Message): void;
+        incrementUnreadMsgsCounter(message: import("./message.js").default<any>): void;
         clearUnreadMsgCounter(): void;
-        handleRetraction(attrs: import("../plugins/chat/types.js").MessageAttributes): Promise<boolean>;
-        handleReceipt(attrs: import("../plugins/chat/types.js").MessageAttributes): boolean;
-        createMessageStanza(message: import("../index.js").Message): Promise<any>;
+        handleRetraction(attrs: import("./types.js").MessageAttributes): Promise<boolean>;
+        handleReceipt(attrs: import("./types.js").MessageAttributes): boolean;
+        createMessageStanza(message: import("./message.js").default<any>): Promise<any>;
         pruneHistory(): void;
         debouncedPruneHistory: import("lodash").DebouncedFunc<() => void>;
         isScrolledUp(): any;

+ 290 - 0
src/headless/types/shared/message.d.ts

@@ -0,0 +1,290 @@
+export default BaseMessage;
+declare const BaseMessage_base: {
+    new (...args: any[]): {
+        _vcard: import("../index.js").VCard;
+        lazy_load_vcard: boolean;
+        initialize(): void;
+        readonly vcard: import("../index.js").VCard;
+        getVCard(create?: boolean): Promise<import("../index.js").VCard | null>;
+        cid: any;
+        attributes: {};
+        validationError: string;
+        collection: any;
+        changed: {};
+        browserStorage: Storage;
+        _browserStorage: Storage;
+        readonly idAttribute: string;
+        readonly cidPrefix: string;
+        preinitialize(): void;
+        validate(attrs: object, options?: object): string;
+        toJSON(): any;
+        sync(method: "create" | "update" | "patch" | "delete" | "read", model: Model, options: import("@converse/skeletor/src/types/model.js").Options): any;
+        get(attr: string): any;
+        keys(): string[];
+        values(): any[];
+        pairs(): [string, any][];
+        entries(): [string, any][];
+        invert(): any;
+        pick(...args: any[]): any;
+        omit(...args: any[]): any;
+        isEmpty(): any;
+        has(attr: string): boolean;
+        matches(attrs: import("@converse/skeletor/src/types/model.js").Attributes): boolean;
+        set(key: string | any, val?: string | any, options?: import("@converse/skeletor/src/types/model.js").Options): false | any;
+        _changing: boolean;
+        _previousAttributes: any;
+        id: any;
+        _pending: boolean | import("@converse/skeletor/src/types/model.js").Options;
+        unset(attr: string, options?: import("@converse/skeletor/src/types/model.js").Options): false | any;
+        clear(options: import("@converse/skeletor/src/types/model.js").Options): false | any;
+        hasChanged(attr?: string): any;
+        changedAttributes(diff: any): any;
+        previous(attr?: string): any;
+        previousAttributes(): any;
+        fetch(options?: import("@converse/skeletor/src/types/model.js").Options): any;
+        save(key?: string | import("@converse/skeletor/src/types/model.js").Attributes, val?: boolean | number | string | import("@converse/skeletor/src/types/model.js").Options, options?: import("@converse/skeletor/src/types/model.js").Options): any;
+        destroy(options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
+        url(): any;
+        parse(resp: import("@converse/skeletor/src/types/model.js").Options, options?: import("@converse/skeletor/src/types/model.js").Options): import("@converse/skeletor/src/types/model.js").Options;
+        isNew(): boolean;
+        isValid(options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
+        _validate(attrs: import("@converse/skeletor/src/types/model.js").Attributes, options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
+        on(name: string, callback: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context: any): any;
+        _events: any;
+        _listeners: {};
+        listenTo(obj: any, name: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
+        _listeningTo: {};
+        _listenId: any;
+        off(name: string, callback: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context?: any): any;
+        stopListening(obj?: any, name?: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
+        once(name: string, callback: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context: any): any;
+        listenToOnce(obj: any, name: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
+        trigger(name: string, ...args: any[]): any;
+        constructor: Function;
+        toString(): string;
+        toLocaleString(): string;
+        valueOf(): Object;
+        hasOwnProperty(v: PropertyKey): boolean;
+        isPrototypeOf(v: Object): boolean;
+        propertyIsEnumerable(v: PropertyKey): boolean;
+    };
+} & {
+    new (...args: any[]): {
+        initialize(): void;
+        rosterContactAdded: any;
+        contact: import("../index.js").RosterContact | import("../index.js").XMPPStatus;
+        setModelContact(jid: string): Promise<void>;
+        cid: any;
+        attributes: {};
+        validationError: string;
+        collection: any;
+        changed: {};
+        browserStorage: Storage;
+        _browserStorage: Storage;
+        readonly idAttribute: string;
+        readonly cidPrefix: string;
+        preinitialize(): void;
+        validate(attrs: object, options?: object): string;
+        toJSON(): any;
+        sync(method: "create" | "update" | "patch" | "delete" | "read", model: Model, options: import("@converse/skeletor/src/types/model.js").Options): any;
+        get(attr: string): any;
+        keys(): string[];
+        values(): any[];
+        pairs(): [string, any][];
+        entries(): [string, any][];
+        invert(): any;
+        pick(...args: any[]): any;
+        omit(...args: any[]): any;
+        isEmpty(): any;
+        has(attr: string): boolean;
+        matches(attrs: import("@converse/skeletor/src/types/model.js").Attributes): boolean;
+        set(key: string | any, val?: string | any, options?: import("@converse/skeletor/src/types/model.js").Options): false | any;
+        _changing: boolean;
+        _previousAttributes: any;
+        id: any;
+        _pending: boolean | import("@converse/skeletor/src/types/model.js").Options;
+        unset(attr: string, options?: import("@converse/skeletor/src/types/model.js").Options): false | any;
+        clear(options: import("@converse/skeletor/src/types/model.js").Options): false | any;
+        hasChanged(attr?: string): any;
+        changedAttributes(diff: any): any;
+        previous(attr?: string): any;
+        previousAttributes(): any;
+        fetch(options?: import("@converse/skeletor/src/types/model.js").Options): any;
+        save(key?: string | import("@converse/skeletor/src/types/model.js").Attributes, val?: boolean | number | string | import("@converse/skeletor/src/types/model.js").Options, options?: import("@converse/skeletor/src/types/model.js").Options): any;
+        destroy(options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
+        url(): any;
+        parse(resp: import("@converse/skeletor/src/types/model.js").Options, options?: import("@converse/skeletor/src/types/model.js").Options): import("@converse/skeletor/src/types/model.js").Options;
+        isNew(): boolean;
+        isValid(options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
+        _validate(attrs: import("@converse/skeletor/src/types/model.js").Attributes, options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
+        on(name: string, callback: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context: any): any;
+        _events: any;
+        _listeners: {};
+        listenTo(obj: any, name: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
+        _listeningTo: {};
+        _listenId: any;
+        off(name: string, callback: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context?: any): any;
+        stopListening(obj?: any, name?: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
+        once(name: string, callback: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context: any): any;
+        listenToOnce(obj: any, name: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
+        trigger(name: string, ...args: any[]): any;
+        constructor: Function;
+        toString(): string;
+        toLocaleString(): string;
+        valueOf(): Object;
+        hasOwnProperty(v: PropertyKey): boolean;
+        isPrototypeOf(v: Object): boolean;
+        propertyIsEnumerable(v: PropertyKey): boolean;
+    };
+} & {
+    new (...args: any[]): {
+        setColor(): Promise<void>;
+        getIdentifier(): any;
+        getColor(): Promise<string>;
+        getAvatarStyle(append_style?: string): Promise<string>;
+        cid: any;
+        attributes: {};
+        validationError: string;
+        collection: any;
+        changed: {};
+        browserStorage: Storage;
+        _browserStorage: Storage;
+        readonly idAttribute: string;
+        readonly cidPrefix: string;
+        preinitialize(): void;
+        initialize(): void;
+        validate(attrs: object, options?: object): string;
+        toJSON(): any;
+        sync(method: "create" | "update" | "patch" | "delete" | "read", model: Model, options: import("@converse/skeletor/src/types/model.js").Options): any;
+        get(attr: string): any;
+        keys(): string[];
+        values(): any[];
+        pairs(): [string, any][];
+        entries(): [string, any][];
+        invert(): any;
+        pick(...args: any[]): any;
+        omit(...args: any[]): any;
+        isEmpty(): any;
+        has(attr: string): boolean;
+        matches(attrs: import("@converse/skeletor/src/types/model.js").Attributes): boolean;
+        set(key: string | any, val?: string | any, options?: import("@converse/skeletor/src/types/model.js").Options): false | any;
+        _changing: boolean;
+        _previousAttributes: any;
+        id: any;
+        _pending: boolean | import("@converse/skeletor/src/types/model.js").Options;
+        unset(attr: string, options?: import("@converse/skeletor/src/types/model.js").Options): false | any;
+        clear(options: import("@converse/skeletor/src/types/model.js").Options): false | any;
+        hasChanged(attr?: string): any;
+        changedAttributes(diff: any): any;
+        previous(attr?: string): any;
+        previousAttributes(): any;
+        fetch(options?: import("@converse/skeletor/src/types/model.js").Options): any;
+        save(key?: string | import("@converse/skeletor/src/types/model.js").Attributes, val?: boolean | number | string | import("@converse/skeletor/src/types/model.js").Options, options?: import("@converse/skeletor/src/types/model.js").Options): any;
+        destroy(options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
+        url(): any;
+        parse(resp: import("@converse/skeletor/src/types/model.js").Options, options?: import("@converse/skeletor/src/types/model.js").Options): import("@converse/skeletor/src/types/model.js").Options;
+        isNew(): boolean;
+        isValid(options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
+        _validate(attrs: import("@converse/skeletor/src/types/model.js").Attributes, options?: import("@converse/skeletor/src/types/model.js").Options): boolean;
+        on(name: string, callback: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context: any): any;
+        _events: any;
+        _listeners: {};
+        listenTo(obj: any, name: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
+        _listeningTo: {};
+        _listenId: any;
+        off(name: string, callback: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context?: any): any;
+        stopListening(obj?: any, name?: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
+        once(name: string, callback: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context: any): any;
+        listenToOnce(obj: any, name: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
+        trigger(name: string, ...args: any[]): any;
+        constructor: Function;
+        toString(): string;
+        toLocaleString(): string;
+        valueOf(): Object;
+        hasOwnProperty(v: PropertyKey): boolean;
+        isPrototypeOf(v: Object): boolean;
+        propertyIsEnumerable(v: PropertyKey): boolean;
+    };
+} & typeof Model;
+/**
+ * @template {import('./types').ModelExtender} T
+ * @param {T} BaseModel
+ */
+declare class BaseMessage<T extends import("./types").ModelExtender> extends BaseMessage_base {
+    /**
+     * @param {Model[]} [models]
+     * @param {object} [options]
+     */
+    constructor(models?: Model[], options?: object);
+    defaults(): {
+        msgid: string;
+        time: string;
+        is_ephemeral: boolean;
+    };
+    file: any;
+    /** @type {import('./types').MessageAttributes} */
+    attributes: import("./types").MessageAttributes;
+    initialize(): void;
+    chatbox: any;
+    checkValidity(): boolean;
+    safeDestroy(): void;
+    /**
+     * Sets an auto-destruct timer for this message, if it's is_ephemeral.
+     */
+    setTimerForEphemeralMessage(): void;
+    ephemeral_timer: NodeJS.Timeout;
+    /**
+     * Returns a boolean indicating whether this message is ephemeral,
+     * meaning it will get automatically removed after ten seconds.
+     * @returns {boolean}
+     */
+    isEphemeral(): boolean;
+    /**
+     * Returns a boolean indicating whether this message is a XEP-0245 /me command.
+     * @returns {boolean}
+     */
+    isMeCommand(): boolean;
+    /**
+     * @returns {boolean}
+     */
+    isRetracted(): boolean;
+    /**
+     * Returns a boolean indicating whether this message is considered a followup
+     * message from the previous one. Followup messages are shown grouped together
+     * under one author heading.
+     * A message is considered a followup of it's predecessor when it's a chat
+     * message from the same author, within 10 minutes.
+     * @returns {boolean}
+     */
+    isFollowup(): boolean;
+    /**
+     * Determines whether this messsage may be retracted by the current user.
+     * @returns { Boolean }
+     */
+    mayBeRetracted(): boolean;
+    getMessageText(): any;
+    /**
+     * Send out an IQ stanza to request a file upload slot.
+     * https://xmpp.org/extensions/xep-0363.html#request
+     */
+    sendSlotRequestStanza(): any;
+    /**
+     * @param {Element} stanza
+     */
+    getUploadRequestMetadata(stanza: Element): {
+        headers: {
+            name: string;
+            value: string;
+        }[];
+    };
+    getRequestSlotURL(): Promise<any>;
+    upload_metadata: {
+        headers: {
+            name: string;
+            value: string;
+        }[];
+    };
+    uploadFile(): void;
+}
+import { Model } from "@converse/skeletor";
+//# sourceMappingURL=message.d.ts.map

+ 37 - 37
src/headless/types/shared/model-with-messages.d.ts

@@ -40,52 +40,52 @@ export default function ModelWithMessages<T extends import("./types").ModelExten
         /**
          * @param {MessageAttributes|Error} _attrs_or_error
          */
-        onMessage(_attrs_or_error: import("../plugins/chat/types.ts").MessageAttributes | Error): Promise<void>;
+        onMessage(_attrs_or_error: import("./types").MessageAttributes | Error): Promise<void>;
         /**
-         * @param {Message} message
+         * @param {BaseMessage} message
          * @param {MessageAttributes} attrs
          * @returns {object}
          */
-        getUpdatedMessageAttributes(message: import("../plugins/chat/message").default, attrs: import("../plugins/chat/types.ts").MessageAttributes): object;
+        getUpdatedMessageAttributes(message: import("./message").default<any>, attrs: import("./types").MessageAttributes): object;
         /**
-         * @param {Message} message
+         * @param {BaseMessage} message
          * @param {MessageAttributes} attrs
          */
-        updateMessage(message: import("../plugins/chat/message").default, attrs: import("../plugins/chat/types.ts").MessageAttributes): void;
+        updateMessage(message: import("./message").default<any>, attrs: import("./types").MessageAttributes): void;
         /**
          * Determines whether the given attributes of an incoming message
          * represent a XEP-0308 correction and, if so, handles it appropriately.
          * @param {MessageAttributes|MUCMessageAttributes} attrs - Attributes representing a received
          *  message, as returned by {@link parseMessage}
-         * @returns {Promise<Message|void>} Returns the corrected
+         * @returns {Promise<BaseMessage|void>} Returns the corrected
          *  message or `undefined` if not applicable.
          */
-        handleCorrection(attrs: import("../plugins/chat/types.ts").MessageAttributes | import("../plugins/muc/types.js").MUCMessageAttributes): Promise<import("../plugins/chat/message").default | void>;
+        handleCorrection(attrs: import("./types").MessageAttributes | import("../plugins/muc/types.js").MUCMessageAttributes): Promise<import("./message").default<any> | void>;
         /**
          * Queue an incoming `chat` message stanza for processing.
          * @param {MessageAttributes} attrs - A promise which resolves to the message attributes
          */
-        queueMessage(attrs: import("../plugins/chat/types.ts").MessageAttributes): any;
+        queueMessage(attrs: import("./types").MessageAttributes): any;
         msg_chain: any;
         /**
          * @param {MessageAttributes} [_attrs]
          * @return {Promise<MessageAttributes>}
          */
-        getOutgoingMessageAttributes(_attrs?: import("../plugins/chat/types.ts").MessageAttributes): Promise<import("../plugins/chat/types.ts").MessageAttributes>;
+        getOutgoingMessageAttributes(_attrs?: import("./types").MessageAttributes): Promise<import("./types").MessageAttributes>;
         /**
          * Responsible for sending off a text message inside an ongoing chat conversation.
          * @param {Object} [attrs] - A map of attributes to be saved on the message
-         * @returns {Promise<Message>}
+         * @returns {Promise<BaseMessage>}
          * @example
          *  const chat = api.chats.get('buddy1@example.org');
          *  chat.sendMessage({'body': 'hello world'});
          */
-        sendMessage(attrs?: any): Promise<import("../plugins/chat/message").default>;
+        sendMessage(attrs?: any): Promise<import("./message").default<any>>;
         /**
          * Retract one of your messages in this chat
-         * @param {Message} message - The message which we're retracting.
+         * @param {BaseMessage} message - The message which we're retracting.
          */
-        retractOwnMessage(message: import("../plugins/chat/message").default): void;
+        retractOwnMessage(message: import("./message").default<any>): void;
         /**
          * @param {File[]} files'
          */
@@ -112,20 +112,20 @@ export default function ModelWithMessages<T extends import("./types").ModelExten
         setChatState(state: string, options?: object): any;
         chat_state_timeout: NodeJS.Timeout;
         /**
-         * @param {Message} message
+         * @param {BaseMessage} message
          */
-        onMessageAdded(message: import("../plugins/chat/message").default): void;
+        onMessageAdded(message: import("./message").default<any>): void;
         /**
-         * @param {Message} message
+         * @param {BaseMessage} message
          */
-        onMessageUploadChanged(message: import("../plugins/chat/message").default): Promise<void>;
+        onMessageUploadChanged(message: import("./message").default<any>): Promise<void>;
         onScrolledChanged(): void;
         pruneHistoryWhenScrolledDown(): void;
         /**
          * @param {MessageAttributes} attrs
          * @returns {Promise<boolean>}
          */
-        shouldShowErrorMessage(attrs: import("../plugins/chat/types.ts").MessageAttributes): Promise<boolean>;
+        shouldShowErrorMessage(attrs: import("./types").MessageAttributes): Promise<boolean>;
         clearMessages(): Promise<void>;
         editEarlierMessage(): void;
         editLaterMessage(): any;
@@ -144,17 +144,17 @@ export default function ModelWithMessages<T extends import("./types").ModelExten
          * relevant message is only coming in now.
          * @param {object} attrs - Attributes representing a received
          *  message, as returned by {@link parseMessage}
-         * @returns {Message|null}
+         * @returns {BaseMessage|null}
          */
-        findDanglingRetraction(attrs: object): import("../plugins/chat/message").default | null;
+        findDanglingRetraction(attrs: object): import("./message").default<any> | null;
         /**
          * Returns an already cached message (if it exists) based on the
          * passed in attributes map.
          * @param {object} attrs - Attributes representing a received
          *  message, as returned by {@link parseMessage}
-         * @returns {Message}
+         * @returns {BaseMessage}
          */
-        getDuplicateMessage(attrs: object): import("../plugins/chat/message").default;
+        getDuplicateMessage(attrs: object): import("./message").default<any>;
         /**
          * @param {object} attrs - Attributes representing a received
          */
@@ -175,31 +175,31 @@ export default function ModelWithMessages<T extends import("./types").ModelExten
         };
         /**
          * Given the passed in message object, send a XEP-0333 chat marker.
-         * @param {Message} msg
+         * @param {BaseMessage} msg
          * @param {('received'|'displayed'|'acknowledged')} [type='displayed']
          * @param {boolean} [force=false] - Whether a marker should be sent for the
          *  message, even if it didn't include a `markable` element.
          */
-        sendMarkerForMessage(msg: import("../plugins/chat/message").default, type?: ("received" | "displayed" | "acknowledged"), force?: boolean): Promise<void>;
+        sendMarkerForMessage(msg: import("./message").default<any>, type?: ("received" | "displayed" | "acknowledged"), force?: boolean): Promise<void>;
         /**
-         * Given a newly received {@link Message} instance,
+         * Given a newly received {@link BaseMessage} instance,
          * update the unread counter if necessary.
-         * @param {Message} message
+         * @param {BaseMessage} message
          */
-        handleUnreadMessage(message: import("../plugins/chat/message").default): void;
+        handleUnreadMessage(message: import("./message").default<any>): void;
         /**
-         * @param {Message} message
+         * @param {BaseMessage} message
          * @param {MessageAttributes} attrs
          */
-        getErrorAttributesForMessage(message: import("../plugins/chat/message").default, attrs: import("../plugins/chat/types.ts").MessageAttributes): Promise<any>;
+        getErrorAttributesForMessage(message: import("./message").default<any>, attrs: import("./types").MessageAttributes): Promise<any>;
         /**
          * @param {Element} stanza
          */
         handleErrorMessageStanza(stanza: Element): Promise<void>;
         /**
-         * @param {Message} message
+         * @param {BaseMessage} message
          */
-        incrementUnreadMsgsCounter(message: import("../plugins/chat/message").default): void;
+        incrementUnreadMsgsCounter(message: import("./message").default<any>): void;
         clearUnreadMsgCounter(): void;
         /**
          * Handles message retraction based on the passed in attributes.
@@ -208,17 +208,17 @@ export default function ModelWithMessages<T extends import("./types").ModelExten
          * @returns {Promise<Boolean>} Returns `true` or `false` depending on
          *  whether a message was retracted or not.
          */
-        handleRetraction(attrs: import("../plugins/chat/types.ts").MessageAttributes): Promise<boolean>;
+        handleRetraction(attrs: import("./types").MessageAttributes): Promise<boolean>;
         /**
          * @param {MessageAttributes} attrs
          */
-        handleReceipt(attrs: import("../plugins/chat/types.ts").MessageAttributes): boolean;
+        handleReceipt(attrs: import("./types").MessageAttributes): boolean;
         /**
-         * Given a {@link Message} return the XML stanza that represents it.
+         * Given a {@link BaseMessage} return the XML stanza that represents it.
          * @method ChatBox#createMessageStanza
-         * @param {Message} message - The message object
+         * @param {BaseMessage} message - The message object
          */
-        createMessageStanza(message: import("../plugins/chat/message").default): Promise<any>;
+        createMessageStanza(message: import("./message").default<any>): Promise<any>;
         /**
          * Prunes the message history to ensure it does not exceed the maximum
          * number of messages specified in the settings.
@@ -282,7 +282,7 @@ export default function ModelWithMessages<T extends import("./types").ModelExten
         _listeningTo: {};
         _listenId: any;
         off(name: string, callback: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context?: any): any;
-        stopListening(obj?: any, name?: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
+        stopListening(obj?: any, name?: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor" /** @param {...any} args */).Collection, options: Record<string, any>) => any): any;
         once(name: string, callback: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any, context: any): any;
         listenToOnce(obj: any, name: string, callback?: (event: any, model: Model, collection: import("@converse/skeletor").Collection, options: Record<string, any>) => any): any;
         trigger(name: string, ...args: any[]): any;

+ 62 - 0
src/headless/types/shared/types.d.ts

@@ -71,5 +71,67 @@ export type XEP372Reference = {
 export type ErrorExtra = Record<string, string>;
 export type ErrorName = 'bad-request' | 'conflict' | 'feature-not-implemented' | 'forbidden' | 'gone' | 'internal-server-error' | 'item-not-found' | 'jid-malformed' | 'not-acceptable' | 'not-allowed' | 'not-authorized' | 'payment-required' | 'recipient-unavailable' | 'redirect' | 'registration-required' | 'remote-server-not-found' | 'remote-server-timeout' | 'resource-constraint' | 'service-unavailable' | 'subscription-required' | 'undefined-condition' | 'unexpected-request';
 export type ErrorType = 'auth' | 'cancel' | 'continue' | 'modify' | 'wait';
+export type Reference = {
+    begin: number;
+    end: number;
+    type: string;
+    uri: string;
+};
+export type MessageErrorAttributes = {
+    is_error: boolean;
+    error: string;
+    errors: {
+        name: string;
+        xmlns: string;
+    }[];
+    error_condition: string;
+    error_text: string;
+    error_type: string;
+};
+export type MessageAttributes = EncryptionAttrs & MessageErrorAttributes & {
+    body: string;
+    chat_state: string;
+    contact_jid: string;
+    editable: boolean;
+    edited: string;
+    from: string;
+    message?: string;
+    fullname: string;
+    is_archived: boolean;
+    is_carbon: boolean;
+    is_delayed: boolean;
+    is_encrypted: boolean;
+    is_headline: boolean;
+    is_markable: boolean;
+    is_marker: boolean;
+    is_only_emojis: boolean;
+    is_spoiler: boolean;
+    is_tombstone: boolean;
+    is_unstyled: boolean;
+    is_valid_receipt_request: boolean;
+    marker: string;
+    marker_id: string;
+    msgid: string;
+    nick: string;
+    ogp_for_id?: string;
+    oob_desc: string;
+    oob_url: string;
+    origin_id: string;
+    plaintext: string;
+    receipt_id: string;
+    received: string;
+    references: Array<Reference>;
+    replace_id: string;
+    retracted: string;
+    retracted_id: string;
+    sender: 'me' | 'them';
+    spoiler_hint: string;
+    stanza_id: string;
+    subject: string;
+    thread: string;
+    time: string;
+    to: string;
+    type: string;
+};
 export {};
 //# sourceMappingURL=types.d.ts.map

+ 3 - 3
src/plugins/mam-views/tests/mam.js

@@ -471,7 +471,7 @@ describe("Message Archive Management", function () {
                 await u.waitUntil(() => view.model.getDuplicateMessage.calls.count());
                 expect(view.model.getDuplicateMessage.calls.count()).toBe(1);
                 const result = view.model.getDuplicateMessage.calls.all()[0].returnValue
-                expect(result instanceof _converse.Message).toBe(true);
+                expect(result instanceof _converse.exports.MUCMessage).toBe(true);
                 expect(view.querySelectorAll('.chat-msg').length).toBe(1);
 
                 await u.waitUntil(() => view.model.updateMessage.calls.count());
@@ -514,7 +514,7 @@ describe("Message Archive Management", function () {
                 await u.waitUntil(() => view.model.getDuplicateMessage.calls.count());
                 expect(view.model.getDuplicateMessage.calls.count()).toBe(1);
                 const result = await view.model.getDuplicateMessage.calls.all()[0].returnValue
-                expect(result instanceof _converse.Message).toBe(true);
+                expect(result instanceof _converse.exports.MUCMessage).toBe(true);
                 expect(view.querySelectorAll('.chat-msg').length).toBe(1);
             }));
 
@@ -563,7 +563,7 @@ describe("Message Archive Management", function () {
                 await u.waitUntil(() => view.model.getDuplicateMessage.calls.count());
                 expect(view.model.getDuplicateMessage.calls.count()).toBe(1);
                 const result = await view.model.getDuplicateMessage.calls.all()[0].returnValue
-                expect(result instanceof _converse.Message).toBe(true);
+                expect(result instanceof _converse.exports.MUCMessage).toBe(true);
                 expect(view.querySelectorAll('.chat-msg').length).toBe(1);
             }))
         });

+ 1 - 1
src/plugins/muc-views/tests/mam.js

@@ -126,7 +126,7 @@ describe("A MAM archived message", function () {
         _converse.handleMAMResult(model, { 'messages': [stanza.tree()] });
         await u.waitUntil(() => model.getDuplicateMessage.calls.count() === 2);
         result = await model.getDuplicateMessage.calls.all()[1].returnValue;
-        expect(result instanceof _converse.Message).toBe(true);
+        expect(result instanceof _converse.exports.MUCMessage).toBe(true);
         expect(model.messages.length).toBe(1);
         await u.waitUntil(() => model.updateMessage.calls.count());
     }));

+ 1 - 1
src/plugins/muc-views/tests/muc-messages.js

@@ -145,7 +145,7 @@ describe("A Groupchat Message", function () {
         _converse.api.connection.get()._dataRecv(mock.createRequest(stanza));
         await u.waitUntil(() => view.model.getDuplicateMessage.calls.count());
         result = await view.model.getDuplicateMessage.calls.all()[0].returnValue;
-        expect(result instanceof _converse.Message).toBe(true);
+        expect(result instanceof _converse.exports.MUCMessage).toBe(true);
         expect(view.model.messages.length).toBe(1);
         await u.waitUntil(() => view.model.updateMessage.calls.count());
     }));

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

@@ -1,6 +1,6 @@
 /**
  * @typedef {module:plugins-omemo-index.WindowWithLibsignal} WindowWithLibsignal
- * @typedef {import('@converse/headless/plugins/chat/types.ts').MessageAttributes} MessageAttributes
+ * @typedef {import('@converse/headless/shared/types').MessageAttributes} MessageAttributes
  * @typedef {import('@converse/headless/plugins/muc/types').MUCMessageAttributes} MUCMessageAttributes
  * @typedef {import('@converse/headless').ChatBox} ChatBox
  */

+ 1 - 1
src/types/plugins/adhoc-views/adhoc-commands.d.ts

@@ -32,7 +32,7 @@ export default class AdHocCommands extends CustomElement {
      * @param {SubmitEvent} ev
      */
     fetchCommands(ev: SubmitEvent): Promise<void>;
-    alert_type: string | undefined;
+    alert_type: string;
     alert: any;
     /**
      * @param {MouseEvent} ev

+ 2 - 2
src/types/plugins/bookmark-views/components/bookmarks-list.d.ts

@@ -1,7 +1,7 @@
 export default class BookmarksView extends CustomElement {
     initialize(): Promise<void>;
-    liveFilter: import("lodash").DebouncedFunc<(ev: any) => false | Model> | undefined;
-    model: Model | undefined;
+    liveFilter: import("lodash").DebouncedFunc<(ev: any) => false | Model>;
+    model: Model;
     render(): import("lit").TemplateResult<1>;
     /**
      * @param {Event} ev

+ 2 - 2
src/types/plugins/chatview/message-form.d.ts

@@ -6,7 +6,7 @@ export default class MessageForm extends CustomElement {
     };
     model: any;
     initialize(): Promise<void>;
-    handleEmojiSelection: (({ detail }: CustomEvent) => void) | undefined;
+    handleEmojiSelection: ({ detail }: CustomEvent) => void;
     render(): import("lit").TemplateResult<1>;
     /**
      * Insert a particular string value into the textarea of this chat box.
@@ -18,7 +18,7 @@ export default class MessageForm extends CustomElement {
      * @param { number } [position] - The end index of the string to be
      *  replaced with the new value.
      */
-    insertIntoTextArea(value: string, replace?: string | boolean | undefined, correcting?: boolean, position?: number | undefined, separator?: string): void;
+    insertIntoTextArea(value: string, replace?: (boolean | string), correcting?: boolean, position?: number, separator?: string): void;
     onMessageCorrecting(message: any): void;
     onEscapePressed(ev: any): void;
     onPaste(ev: any): void;

+ 1 - 1
src/types/plugins/controlbox/controlbox.d.ts

@@ -11,7 +11,7 @@ declare class ControlBoxView extends CustomElement {
     setModel(): void;
     model: any;
     render(): import("lit").TemplateResult<1> | "";
-    close(ev: any): this | undefined;
+    close(ev: any): this;
     afterShown(): this;
 }
 import { CustomElement } from 'shared/components/element.js';

+ 2 - 2
src/types/plugins/controlbox/loginform.d.ts

@@ -1,7 +1,7 @@
 export default LoginForm;
 declare class LoginForm extends CustomElement {
     initialize(): void;
-    handler: (() => void) | undefined;
+    handler: () => void;
     connectedCallback(): void;
     render(): import("lit").TemplateResult<1>;
     firstUpdated(): void;
@@ -17,7 +17,7 @@ declare class LoginForm extends CustomElement {
     /**
      * @param {string} [jid]
      */
-    connect(jid?: string | undefined): void;
+    connect(jid?: string): void;
 }
 import { CustomElement } from 'shared/components/element.js';
 //# sourceMappingURL=loginform.d.ts.map

+ 2 - 2
src/types/plugins/controlbox/model.d.ts

@@ -10,7 +10,7 @@ declare class ControlBox extends Model {
     defaults(): {
         bookmarked: boolean;
         box_id: string;
-        chat_state: undefined;
+        chat_state: any;
         closed: boolean;
         num_unread: number;
         time_opened: any;
@@ -21,7 +21,7 @@ declare class ControlBox extends Model {
     /**
      * @param {boolean} [force]
      */
-    maybeShow(force?: boolean | undefined): any;
+    maybeShow(force?: boolean): any;
     onReconnection(): void;
 }
 import { Model } from '@converse/skeletor';

+ 1 - 1
src/types/plugins/controlbox/utils.d.ts

@@ -2,7 +2,7 @@ export function addControlBox(): any;
 /**
  * @param {Event} [ev]
  */
-export function showControlBox(ev?: Event | undefined): void;
+export function showControlBox(ev?: Event): void;
 /**
  * @param {string} jid
  */

+ 4 - 4
src/types/plugins/dragresize/utils.d.ts

@@ -15,8 +15,8 @@ export function initializeDragResize(model: import("@converse/headless/types/sha
  * @returns {string}
  */
 export function getResizingDirection(): string;
-export function onStartVerticalResize(ev: any, trigger?: boolean): true | undefined;
-export function onStartHorizontalResize(ev: any, trigger?: boolean): true | undefined;
+export function onStartVerticalResize(ev: any, trigger?: boolean): boolean;
+export function onStartHorizontalResize(ev: any, trigger?: boolean): boolean;
 export function onStartDiagonalResize(ev: any): void;
 /**
  * Applies some resistance to `value` around the `default_value`.
@@ -27,8 +27,8 @@ export function onStartDiagonalResize(ev: any): void;
  * @returns { number }
  */
 export function applyDragResistance(value: number, default_value: number): number;
-export function onMouseMove(ev: any): true | undefined;
-export function onMouseUp(ev: any): true | undefined;
+export function onMouseMove(ev: any): boolean;
+export function onMouseUp(ev: any): boolean;
 export type ResizingData = {
     chatbox: HTMLElement;
     direction: string;

+ 1 - 1
src/types/plugins/headlines-view/feed-list.d.ts

@@ -8,7 +8,7 @@ export class HeadlinesFeedsList extends CustomElement {
     initialize(): void;
     model: any;
     render(): import("lit").TemplateResult<1>;
-    renderIfHeadline(model: any): false | void;
+    renderIfHeadline(model: any): void;
     openHeadline(ev: any): Promise<void>;
 }
 import { CustomElement } from 'shared/components/element.js';

+ 1 - 1
src/types/plugins/headlines-view/view.d.ts

@@ -6,7 +6,7 @@ declare class HeadlinesFeedView extends BaseChatView {
      * @param {Event} ev
      */
     close(ev: Event): Promise<this>;
-    getNotifications(): never[];
+    getNotifications(): any[];
     afterShown(): void;
 }
 import BaseChatView from 'shared/chat/baseview.js';

+ 1 - 1
src/types/plugins/minimize/utils.d.ts

@@ -9,7 +9,7 @@ export function initializeChat(chat: ChatBox | MUC): void;
  * to create space.
  * @param {ChatView|MUCView|ControlBoxView|HeadlinesFeedView} [newchat]
  */
-export function trimChats(newchat?: import("plugins/chatview/chat").default | import("plugins/muc-views/muc").default | import("plugins/controlbox/controlbox").default | import("plugins/headlines-view/view").default | undefined): void;
+export function trimChats(newchat?: ChatView | MUCView | ControlBoxView | HeadlinesFeedView): void;
 export function addMinimizeButtonToChat(view: any, buttons: any): any[];
 export function addMinimizeButtonToMUC(view: any, buttons: any): any[];
 export function maximize(ev: any, chatbox: any): void;

+ 2 - 2
src/types/plugins/minimize/view.d.ts

@@ -3,11 +3,11 @@ export default class MinimizedChats extends CustomElement {
     model: any;
     render(): import("lit").TemplateResult<1>;
     initToggle(): Promise<void>;
-    minchats: MinimizedChatsToggle | undefined;
+    minchats: MinimizedChatsToggle;
     /**
      * @param {Event} [ev]
      */
-    toggle(ev?: Event | undefined): void;
+    toggle(ev?: Event): void;
 }
 import { CustomElement } from 'shared/components/element';
 import MinimizedChatsToggle from './toggle.js';

+ 1 - 1
src/types/plugins/modal/api.d.ts

@@ -9,7 +9,7 @@ declare namespace modal_api {
          * @param {Object} [properties] - Optional properties that will be set on a newly created modal instance.
          * @param {Event} [ev] - The DOM event that causes the modal to be shown.
          */
-        function show(name: string | any, properties?: any, ev?: Event | undefined): any;
+        function show(name: string | any, properties?: any, ev?: Event): any;
         /**
          * Return a modal with the passed-in identifier, if it exists.
          * @param { String } id

+ 2 - 3
src/types/plugins/modal/modal.d.ts

@@ -13,7 +13,6 @@ declare class BaseModal extends CustomElement {
      */
     constructor(options: any);
     model: any;
-    ariaHidden: string;
     initialized: any;
     get modal(): Modal;
     initialize(): void;
@@ -33,8 +32,8 @@ declare class BaseModal extends CustomElement {
     /**
      * @param {Event} [ev]
      */
-    switchTab(ev?: Event | undefined): void;
-    tab: string | null | undefined;
+    switchTab(ev?: Event): void;
+    tab: string;
     close(): void;
     insertIntoDOM(): void;
     /**

+ 0 - 1
src/types/plugins/muc-views/bottom-panel.d.ts

@@ -1,5 +1,4 @@
 export default class MUCBottomPanel extends BottomPanel {
-    render(): import("lit").TemplateResult<1> | "" | undefined;
     renderIfOwnOccupant(o: any): void;
 }
 import BottomPanel from 'plugins/chatview/bottom-panel.js';

+ 2 - 2
src/types/plugins/muc-views/message-form.d.ts

@@ -1,8 +1,8 @@
 export default class MUCMessageForm extends MessageForm {
     shouldAutoComplete(): boolean;
     initMentionAutoComplete(): void;
-    mention_auto_complete: AutoComplete | undefined;
-    auto_completing: boolean | undefined;
+    mention_auto_complete: AutoComplete;
+    auto_completing: boolean;
     getAutoCompleteList(): any;
     /**
      * @param {Event} ev

+ 1 - 1
src/types/plugins/muc-views/modals/muc-list.d.ts

@@ -13,7 +13,7 @@ export default class MUCListModal extends BaseModal {
      * @method _converse.ChatRoomView#onRoomsFound
      * @param {HTMLElement} [iq]
      */
-    onRoomsFound(iq?: HTMLElement | undefined): boolean;
+    onRoomsFound(iq?: HTMLElement): boolean;
     /**
      * Send an IQ stanza to the server asking for all groupchats
      * @private

+ 1 - 2
src/types/plugins/muc-views/modtools.d.ts

@@ -45,7 +45,6 @@ export default class ModeratorTools extends CustomElement {
     tab: string;
     affiliation: any;
     affiliations_filter: string;
-    role: string;
     roles_filter: string;
     updated(changed: any): void;
     initialize(): Promise<void>;
@@ -54,7 +53,7 @@ export default class ModeratorTools extends CustomElement {
     render(): import("lit").TemplateResult<1> | "";
     switchTab(ev: any): void;
     onSearchAffiliationChange(): Promise<void>;
-    loading_users_with_affiliation: boolean | undefined;
+    loading_users_with_affiliation: boolean;
     users_with_affiliation: any;
     onSearchRoleChange(): Promise<void>;
     users_with_role: any;

+ 1 - 1
src/types/plugins/muc-views/occupant-bottom-panel.d.ts

@@ -9,7 +9,7 @@ export default class OccupantBottomPanel extends BottomPanel {
         };
     };
     muc: any;
-    canPostMessages(): any;
+    canPostMessages(): boolean;
     openChat(): any;
     invite(): any;
 }

+ 1 - 1
src/types/plugins/muc-views/occupant.d.ts

@@ -19,7 +19,7 @@ export default class MUCOccupant extends CustomElement {
     openChat(jid: string): void;
     closeSidebar(): void;
     /** @param {MouseEvent} [ev] */
-    showOccupantModal(ev?: MouseEvent | undefined): void;
+    showOccupantModal(ev?: MouseEvent): void;
     getVcard(): any;
     addToContacts(): void;
     /**

+ 1 - 1
src/types/plugins/muc-views/occupants.d.ts

@@ -6,7 +6,7 @@ export default class MUCOccupants extends CustomElement {
     };
     jid: any;
     initialize(): void;
-    filter: RosterFilter | undefined;
+    filter: RosterFilter;
     model: any;
     render(): import("lit").TemplateResult<1>;
     /**

+ 1 - 1
src/types/plugins/muc-views/templates/muc-bottom-panel.d.ts

@@ -1,3 +1,3 @@
-declare function _default(el: import("../bottom-panel").default): import("lit").TemplateResult<1> | "" | undefined;
+declare function _default(el: import("../bottom-panel").default): import("lit").TemplateResult<1> | "";
 export default _default;
 //# sourceMappingURL=muc-bottom-panel.d.ts.map

+ 1 - 1
src/types/plugins/muc-views/utils.d.ts

@@ -36,7 +36,7 @@ export function getAutoCompleteList(): Promise<any[]>;
  * @param {MUC} muc
  * @param {string} [affiliation]
  */
-export function showModeratorToolsModal(muc: MUC, affiliation?: string | undefined): void;
+export function showModeratorToolsModal(muc: MUC, affiliation?: string): void;
 export function showOccupantModal(ev: any, occupant: any): void;
 export function parseMessageForMUCCommands(data: any, handled: any): any;
 export type MUC = import("@converse/headless/types/plugins/muc/muc.js").default;

+ 1 - 1
src/types/plugins/notifications/utils.d.ts

@@ -15,7 +15,7 @@ export function showFeedbackNotification(data: any): void;
  * Event handler for the on('message') event. Will call methods
  * to play sounds and show HTML5 notifications.
  */
-export function handleMessageNotification(data: any): Promise<false | undefined>;
+export function handleMessageNotification(data: any): Promise<boolean>;
 export function handleFeedback(data: any): void;
 /**
  * Event handler for on('contactPresenceChanged').

+ 1 - 1
src/types/plugins/omemo/device.d.ts

@@ -17,7 +17,7 @@ declare class Device extends Model {
             signature: any;
         };
         prekeys: any;
-    } | null>;
+    }>;
     /**
      * Fetch and save the bundle information associated with
      * this device, if the information is not cached already.

+ 1 - 1
src/types/plugins/omemo/devicelist.d.ts

@@ -10,7 +10,7 @@ declare class DeviceList extends Model {
     devices: any;
     onDevicesFound(collection: any): Promise<void>;
     fetchDevices(): Promise<any>;
-    _devices_promise: Promise<any> | undefined;
+    _devices_promise: Promise<any>;
     getOwnDeviceId(): Promise<any>;
     publishCurrentDevice(device_ids: any): Promise<any>;
     fetchDevicesFromServer(): Promise<any[]>;

+ 1 - 1
src/types/plugins/omemo/store.d.ts

@@ -53,7 +53,7 @@ declare class OMEMOStore extends Model {
      */
     generateBundle(): Promise<void>;
     fetchSession(): Promise<any>;
-    _setup_promise: Promise<any> | undefined;
+    _setup_promise: Promise<any>;
 }
 import { Model } from '@converse/skeletor';
 //# sourceMappingURL=store.d.ts.map

+ 1 - 1
src/types/plugins/omemo/utils.d.ts

@@ -55,7 +55,7 @@ export namespace omemo {
     export { formatFingerprint };
 }
 export type WindowWithLibsignal = any;
-export type MessageAttributes = import("@converse/headless/plugins/chat/types.ts").MessageAttributes;
+export type MessageAttributes = import("@converse/headless/shared/types").MessageAttributes;
 export type MUCMessageAttributes = import("@converse/headless/plugins/muc/types").MUCMessageAttributes;
 export type ChatBox = import("@converse/headless").ChatBox;
 import { IQError } from 'shared/errors.js';

+ 0 - 1
src/types/plugins/profile/modals/profile.d.ts

@@ -1,5 +1,4 @@
 export default class ProfileModal extends BaseModal {
-    tab: string;
     renderModal(): import("lit").TemplateResult<1>;
     getModalTitle(): any;
     /**

+ 1 - 1
src/types/plugins/push/utils.d.ts

@@ -1,6 +1,6 @@
 /**
  * @param {string} [domain]
  */
-export function enablePush(domain?: string | undefined): Promise<void>;
+export function enablePush(domain?: string): Promise<void>;
 export function onChatBoxAdded(model: any): void;
 //# sourceMappingURL=utils.d.ts.map

+ 6 - 6
src/types/plugins/register/form.d.ts

@@ -27,7 +27,7 @@ declare class RegistrationForm extends CustomElement {
     setErrorMessage: (m: string) => void;
     setFeedbackMessage: (m: string) => void;
     initialize(): void;
-    status: number | undefined;
+    status: number;
     render(): import("lit").TemplateResult<1>;
     /**
      * @param {string} message
@@ -40,14 +40,14 @@ declare class RegistrationForm extends CustomElement {
      * requesting the registration fields.
      */
     registerHooks(): void;
-    _registering: boolean | undefined;
+    _registering: boolean;
     /**
      * Send an IQ stanza to the XMPP server asking for the registration fields.
      * @method _converse.RegistrationForm#getRegistrationFields
      * @param {Request} req - The current request
      * @param {Function} callback - The callback function
      */
-    getRegistrationFields(req: import("strophe.js").Request, callback: Function): boolean | undefined;
+    getRegistrationFields(req: import("strophe.js").Request, callback: Function): boolean;
     /**
      * Handler for {@link _converse.RegistrationForm#getRegistrationFields}
      * @method _converse.RegistrationForm#onRegistrationFields
@@ -71,7 +71,7 @@ declare class RegistrationForm extends CustomElement {
      * @param {string} domain_name - XMPP server domain
      * @param {string|null} [service_url]
      */
-    fetchRegistrationForm(domain_name: string, service_url?: string | null | undefined): boolean;
+    fetchRegistrationForm(domain_name: string, service_url?: string | null): boolean;
     /**
      * Callback function called by Strophe whenever the connection status changes.
      * Passed to Strophe specifically during a registration attempt.
@@ -90,7 +90,7 @@ declare class RegistrationForm extends CustomElement {
      * @param {Element} stanza - The IQ stanza received from the XMPP server.
      */
     renderRegistrationForm(stanza: Element): void;
-    form_fields: any[] | undefined;
+    form_fields: any[];
     /**
      * Report back to the user any error messages received from the
      * XMPP server after attempted registration.
@@ -123,7 +123,7 @@ declare class RegistrationForm extends CustomElement {
      */
     setFieldsFromLegacy(query: Element): void;
     instructions: any;
-    form_type: string | undefined;
+    form_type: string;
     /**
      * @param {Element} xform
      */

+ 1 - 1
src/types/plugins/roomslist/model.d.ts

@@ -3,7 +3,7 @@ declare class RoomsListModel extends Model {
     defaults(): {
         muc_domain: any;
         toggle_state: "opened";
-        collapsed_domains: never[];
+        collapsed_domains: any[];
     };
     /**
      * @param {string} jid

+ 2 - 2
src/types/plugins/roomslist/view.d.ts

@@ -1,6 +1,6 @@
 export class RoomsList extends CustomElement {
     initialize(): void;
-    model: RoomsListModel | undefined;
+    model: RoomsListModel;
     render(): import("lit").TemplateResult<1>;
     /** @param {Model} model */
     renderIfChatRoom(model: Model): void;
@@ -11,7 +11,7 @@ export class RoomsList extends CustomElement {
     /** @param {Event} ev */
     closeRoom(ev: Event): Promise<void>;
     /** @param {Event} [ev] */
-    toggleRoomsList(ev?: Event | undefined): void;
+    toggleRoomsList(ev?: Event): void;
     /**
      * @param {Event} ev
      * @param {string} domain

+ 5 - 5
src/types/plugins/rosterview/rosterview.d.ts

@@ -5,19 +5,19 @@
  */
 export default class RosterView extends CustomElement {
     initialize(): Promise<void>;
-    model: Model | undefined;
+    model: Model;
     render(): import("lit").TemplateResult<1>;
     /** @param {MouseEvent} ev */
     showAddContactModal(ev: MouseEvent): void;
     /** @param {MouseEvent} ev */
     showNewChatModal(ev: MouseEvent): void;
     /** @param {MouseEvent} [ev] */
-    syncContacts(ev?: MouseEvent | undefined): Promise<void>;
-    syncing_contacts: boolean | undefined;
+    syncContacts(ev?: MouseEvent): Promise<void>;
+    syncing_contacts: boolean;
     /** @param {MouseEvent} [ev] */
-    toggleRoster(ev?: MouseEvent | undefined): void;
+    toggleRoster(ev?: MouseEvent): void;
     /** @param {MouseEvent} [ev] */
-    toggleFilter(ev?: MouseEvent | undefined): void;
+    toggleFilter(ev?: MouseEvent): void;
 }
 import { CustomElement } from 'shared/components/element.js';
 import { Model } from '@converse/skeletor';

+ 2 - 2
src/types/plugins/rosterview/utils.d.ts

@@ -3,7 +3,7 @@
  * @param {boolean} [unauthorize]
  * @returns {Promise<boolean>}
  */
-export function removeContact(contact: RosterContact, unauthorize?: boolean | undefined): Promise<boolean>;
+export function removeContact(contact: RosterContact, unauthorize?: boolean): Promise<boolean>;
 /**
  * @param {RosterContact} contact
  * @returns {Promise<boolean>}
@@ -58,7 +58,7 @@ export function contactsComparator(contact1: RosterContact | XMPPStatus, contact
  * @param {string} a
  * @param {string} b
  */
-export function groupsComparator(a: string, b: string): 0 | 1 | -1 | undefined;
+export function groupsComparator(a: string, b: string): 0 | 1 | -1;
 export function getGroupsAutoCompleteList(): any[];
 export function getJIDsAutoCompleteList(): any[];
 /**

+ 7 - 7
src/types/shared/autocomplete/autocomplete.d.ts

@@ -21,7 +21,7 @@ export class AutoComplete extends AutoComplete_base {
     is_opened: boolean;
     auto_evaluate: boolean;
     match_current_word: boolean;
-    sort: ((a: any, b: any) => number) | null;
+    sort: (a: any, b: any) => number;
     filter: (text: any, input: any) => boolean;
     ac_triggers: any[];
     include_triggers: any[];
@@ -30,10 +30,10 @@ export class AutoComplete extends AutoComplete_base {
     auto_first: boolean;
     data: (a: any, _v: any) => any;
     item: (text: any, input: any) => HTMLLIElement;
-    container: Element | HTMLElement | null;
+    container: Element | HTMLElement;
     input: HTMLInputElement;
-    ul: Element | null;
-    status: Element | null;
+    ul: Element;
+    status: Element;
     index: number;
     set list(list: any);
     get list(): any;
@@ -53,14 +53,14 @@ export class AutoComplete extends AutoComplete_base {
      */
     goto(i: number, scroll?: boolean): void;
     select(selected: any): void;
-    auto_completing: boolean | undefined;
+    auto_completing: boolean;
     onMouseOver(ev: any): void;
     onMouseDown(ev: any): void;
-    onKeyDown(ev: any): true | undefined;
+    onKeyDown(ev: any): boolean;
     /**
      * @param {KeyboardEvent} [ev]
      */
-    evaluate(ev?: KeyboardEvent | undefined): Promise<void>;
+    evaluate(ev?: KeyboardEvent): Promise<void>;
 }
 export default AutoComplete;
 //# sourceMappingURL=autocomplete.d.ts.map

+ 2 - 2
src/types/shared/autocomplete/component.d.ts

@@ -113,8 +113,8 @@ export default class AutoCompleteComponent extends CustomElement {
     value: string;
     render(): import("lit").TemplateResult<1>;
     firstUpdated(): void;
-    auto_complete: AutoComplete | undefined;
-    auto_completing: boolean | undefined;
+    auto_complete: AutoComplete;
+    auto_completing: boolean;
     /** @param {KeyboardEvent} ev */
     onKeyDown(ev: KeyboardEvent): void;
     /** @param {KeyboardEvent} ev */

+ 3 - 3
src/types/shared/chat/baseview.d.ts

@@ -10,8 +10,8 @@ export default class BaseChatView extends CustomElement {
     close(ev: any): any;
     maybeFocus(): void;
     focus(): this;
-    getBottomPanel(): Element | null;
-    getMessageForm(): Element | null;
+    getBottomPanel(): Element;
+    getMessageForm(): Element;
     /**
      * Scrolls the chat down.
      *
@@ -19,7 +19,7 @@ export default class BaseChatView extends CustomElement {
      * whether the user scrolled up manually or not.
      * @param { Event } [ev] - An optional event that is the cause for needing to scroll down.
      */
-    scrollDown(ev?: Event | undefined): void;
+    scrollDown(ev?: Event): void;
     onWindowStateChanged(): void;
 }
 export type Model = import("@converse/skeletor").Model;

+ 2 - 2
src/types/shared/chat/emoji-dropdown.d.ts

@@ -11,10 +11,10 @@ export default class EmojiDropdown extends DropdownBase {
         };
     };
     render_emojis: boolean;
-    state: EmojiPicker | null;
+    state: EmojiPicker;
     model: any;
     initModel(): Promise<void>;
-    init_promise: Promise<void> | undefined;
+    init_promise: Promise<void>;
     connectedCallback(): void;
     onShown(): Promise<void>;
 }

+ 1 - 1
src/types/shared/chat/emoji-picker-content.d.ts

@@ -20,7 +20,7 @@ export default class EmojiPickerContent extends CustomElement {
     render(): import("lit").TemplateResult<1>;
     firstUpdated(): void;
     initIntersectionObserver(): void;
-    observer: IntersectionObserver | undefined;
+    observer: IntersectionObserver;
     setCategoryOnVisibilityChange(entries: any): void;
     /**
      * @param {MouseEvent} ev

+ 5 - 5
src/types/shared/chat/emoji-picker.d.ts

@@ -29,7 +29,7 @@ export default class EmojiPicker extends CustomElement {
     _search_results: any[];
     debouncedFilter: import("lodash").DebouncedFunc<(input: HTMLInputElement) => any>;
     initialize(): void;
-    dropdown: Element | null | undefined;
+    dropdown: Element;
     firstUpdated(changed: any): void;
     set search_results(value: any[]);
     get search_results(): any[];
@@ -39,10 +39,10 @@ export default class EmojiPicker extends CustomElement {
     current_category: any;
     current_skintone: any;
     setScrollPosition(): void;
-    preserve_scroll: boolean | undefined;
-    updateSearchResults(changed: any): any[] | undefined;
+    preserve_scroll: boolean;
+    updateSearchResults(changed: any): any[];
     registerEvents(): void;
-    onGlobalKeyDown: ((ev: any) => void) | undefined;
+    onGlobalKeyDown: (ev: any) => void;
     connectedCallback(): void;
     onDropdownHide(): void;
     /**
@@ -74,7 +74,7 @@ export default class EmojiPicker extends CustomElement {
      */
     getTonedShortname(shortname: string): string;
     initArrowNavigation(): void;
-    navigator: DOMNavigator | undefined;
+    navigator: DOMNavigator;
     disableArrowNavigation(): void;
     /**
      * @param {KeyboardEvent} ev

+ 1 - 1
src/types/shared/chat/message-body.d.ts

@@ -21,7 +21,7 @@ export default class MessageBody extends CustomElement {
     onImgLoad(): void;
     render(): import("lit/directive").DirectiveResult<{
         new (_partInfo: import("lit/directive").PartInfo): {
-            render(text: string, offset: number, options: object, callback?: Function | undefined): import("lit").TemplateResult<1>;
+            render(text: string, offset: number, options: object, callback?: Function): import("lit").TemplateResult<1>;
             readonly _$isConnected: boolean;
             update(_part: import("lit").Part, props: Array<unknown>): unknown;
         };

+ 2 - 2
src/types/shared/chat/message.d.ts

@@ -17,10 +17,10 @@ export default class Message extends CustomElement {
     renderInfoMessage(): import("lit").TemplateResult<1>;
     renderFileProgress(): import("lit").TemplateResult<1> | "";
     renderChatMessage(): import("lit").TemplateResult<1>;
-    shouldShowAvatar(): any;
+    shouldShowAvatar(): boolean;
     onUnfurlAnimationEnd(): void;
     onRetryClicked(): Promise<void>;
-    show_spinner: boolean | undefined;
+    show_spinner: boolean;
     hasMentions(): any;
     getOccupantAffiliation(): any;
     getOccupantRole(): any;

+ 1 - 1
src/types/shared/chat/toolbar.d.ts

@@ -40,7 +40,7 @@ export class ChatToolbar extends CustomElement {
      * @param {boolean} is_supported
      */
     getHTTPUploadButton(is_supported: boolean): import("lit").TemplateResult<1> | "";
-    getSpoilerButton(): import("lit").TemplateResult<1> | undefined;
+    getSpoilerButton(): import("lit").TemplateResult<1>;
     /** @param {MouseEvent} ev */
     toggleFileUpload(ev: MouseEvent): void;
     /** @param {InputEvent} ev */

+ 2 - 2
src/types/shared/chat/utils.d.ts

@@ -86,8 +86,8 @@ export function shortnamesToEmojis(str: string, options?: {
  */
 export const markScrolled: import("lodash").DebouncedFunc<(ev: Event) => void>;
 export type EmojiMarkupOptions = {
-    unicode_only?: boolean | undefined;
-    add_title_wrapper?: boolean | undefined;
+    unicode_only?: boolean;
+    add_title_wrapper?: boolean;
 };
 export type HeadingButtonAttributes = import("plugins/chatview/types").HeadingButtonAttributes;
 export type ChatView = import("../../plugins/chatview/chat.js").default;

+ 1 - 1
src/types/shared/components/dropdown.d.ts

@@ -13,7 +13,7 @@ export default class Dropdown extends DropdownBase {
     firstUpdated(): void;
     onHidden(): void;
     initArrowNavigation(): void;
-    navigator: DOMNavigator | undefined;
+    navigator: DOMNavigator;
     enableArrowNavigation(ev: any): void;
     handleKeyUp(ev: any): void;
 }

+ 3 - 3
src/types/shared/components/dropdownbase.d.ts

@@ -1,8 +1,8 @@
 export default class DropdownBase extends CustomElement {
     firstUpdated(changed: any): void;
-    menu: Element | null | undefined;
-    button: HTMLButtonElement | null | undefined;
-    dropdown: BootstrapDropdown | undefined;
+    menu: Element;
+    button: HTMLButtonElement;
+    dropdown: BootstrapDropdown;
 }
 import { CustomElement } from './element.js';
 import { Dropdown as BootstrapDropdown } from 'bootstrap';

+ 2 - 2
src/types/shared/components/element.d.ts

@@ -13,8 +13,8 @@ declare const CustomElement_base: (new (...args: any[]) => {
 }) & typeof LitElement;
 export class CustomElement extends CustomElement_base {
     createRenderRoot(): this;
-    initialize(): null;
-    connectedCallback(): null;
+    initialize(): any;
+    connectedCallback(): any;
 }
 import { LitElement } from 'lit';
 export {};

+ 4 - 4
src/types/shared/components/gif.d.ts

@@ -22,12 +22,12 @@ export default class ConverseGIFElement extends CustomElement {
     fallback: string;
     progress_color: any;
     initGIF(): void;
-    supergif: ConverseGif | undefined;
+    supergif: ConverseGif;
     updated(changed: any): void;
-    render(): string | import("utils/html.js").TemplateResult | undefined;
-    renderErrorFallback(): string | import("utils/html.js").TemplateResult | undefined;
+    render(): string | import("utils/html.js").TemplateResult;
+    renderErrorFallback(): string | import("utils/html.js").TemplateResult;
     setHover(): void;
-    hover_timeout: NodeJS.Timeout | undefined;
+    hover_timeout: NodeJS.Timeout;
     unsetHover(): void;
     onControlsClicked(ev: any): void;
 }

+ 1 - 1
src/types/shared/components/image-picker.d.ts

@@ -14,7 +14,7 @@ export default class ImagePicker extends CustomElement {
     width: any;
     height: any;
     data: Model;
-    nonce: string | null | undefined;
+    nonce: string;
     render(): import("lit").TemplateResult<1>;
     /**
      * @param {Event} ev

+ 1 - 1
src/types/shared/components/list-filter.d.ts

@@ -21,7 +21,7 @@ export default class ListFilter extends CustomElement {
     template: any;
     promise: Promise<void>;
     initialize(): void;
-    liveFilter: import("lodash").DebouncedFunc<(ev: any) => any> | undefined;
+    liveFilter: import("lodash").DebouncedFunc<(ev: any) => any>;
     render(): any;
     dispatchUpdateEvent(): void;
     /**

+ 1 - 1
src/types/shared/components/observable.d.ts

@@ -18,7 +18,7 @@ export class ObservableElement extends CustomElement {
     observableRatio: number;
     observableDelay: number;
     initIntersectionObserver(): void;
-    intersectionObserver: IntersectionObserver | undefined;
+    intersectionObserver: IntersectionObserver;
     /**
      * @param {IntersectionObserverEntry[]} entries
      */

+ 9 - 9
src/types/shared/components/split-resize.d.ts

@@ -27,7 +27,7 @@ export default class SplitResize extends CustomElement {
          * 5. Actually size the pair elements, insert gutters and attach event listeners.
          */
         move: (this: Window, ev: Event) => any;
-    } | null;
+    };
     render(): import("lit").TemplateResult<1>;
     /**
      * @param {Map<string, any>} changed
@@ -203,18 +203,18 @@ export default class SplitResize extends CustomElement {
      * @param {HTMLElement[]} els
      */
     setupSplit(els: HTMLElement[], options?: {}): void;
-    parent: HTMLElement | null | undefined;
-    minSizes: any[] | undefined;
+    parent: HTMLElement;
+    minSizes: any[];
     gutterSize: any;
     gutterAlign: any;
     dragInterval: any;
     direction: any;
     cursor: any;
-    dimension: string | undefined;
-    clientAxis: string | undefined;
-    position: string | undefined;
-    positionEnd: string | undefined;
-    clientSize: string | undefined;
+    dimension: string;
+    clientAxis: string;
+    position: string;
+    positionEnd: string;
+    clientSize: string;
     elements: {
         element: HTMLElement;
         size: any;
@@ -222,7 +222,7 @@ export default class SplitResize extends CustomElement {
         maxSize: any;
         snapOffset: any;
         i: number;
-    }[] | undefined;
+    }[];
     /**
      * @param {HTMLElement[]} els
      * @param {HTMLElement} el

+ 4 - 4
src/types/shared/directives/image.d.ts

@@ -7,7 +7,7 @@
  * @param { Function } onLoad - A callback function to be called once the image has loaded.
  * @param { Function } onClick - A callback function to be called once the image has been clicked.
  */
-export const renderImage: (src: string, href?: string | undefined, onLoad?: Function | undefined, onClick?: Function | undefined) => import("lit/async-directive.js").DirectiveResult<typeof ImageDirective>;
+export const renderImage: (src: string, href?: string, onLoad?: Function, onClick?: Function) => import("lit/async-directive.js").DirectiveResult<typeof ImageDirective>;
 declare class ImageDirective extends AsyncDirective {
     /**
      * @param {string} src - The source URL of the image.
@@ -16,7 +16,7 @@ declare class ImageDirective extends AsyncDirective {
      * @param {Function} [onClick] - Callback function to be called once the image has been clicked.
      * @returns {import('lit').TemplateResult}
      */
-    render(src: string, href?: string | undefined, onLoad?: Function | undefined, onClick?: Function | undefined): import("lit").TemplateResult;
+    render(src: string, href?: string, onLoad?: Function, onClick?: Function): import("lit").TemplateResult;
     /**
      * @param {string} src - The source URL of the image.
      * @param {string} [href] - The optional hyperlink for the image.
@@ -24,7 +24,7 @@ declare class ImageDirective extends AsyncDirective {
      * @param {Function} [onClick] - Callback function to be called once the image has been clicked.
      * @returns {import('lit').TemplateResult}
      */
-    renderImage(src: string, href?: string | undefined, onLoad?: Function | undefined, onClick?: Function | undefined): import("lit").TemplateResult;
+    renderImage(src: string, href?: string, onLoad?: Function, onClick?: Function): import("lit").TemplateResult;
     /**
      * Handles errors that occur during image loading.
      * @param {string} src - The source URL of the image that failed to load.
@@ -32,7 +32,7 @@ declare class ImageDirective extends AsyncDirective {
      * @param {Function} [onLoad] - Callback function to be called once the image has loaded.
      * @param {Function} [onClick] - Callback function to be called once the image has been clicked.
      */
-    onError(src: string, href?: string | undefined, onLoad?: Function | undefined, onClick?: Function | undefined): void;
+    onError(src: string, href?: string, onLoad?: Function, onClick?: Function): void;
 }
 import { AsyncDirective } from 'lit/async-directive.js';
 export {};

+ 5 - 5
src/types/shared/dom-navigator.d.ts

@@ -59,14 +59,14 @@ declare class DOMNavigator {
      */
     init(): void;
     selected: any;
-    keydownHandler: ((event: any) => void) | null | undefined;
-    elements: {} | undefined;
-    keys: {} | undefined;
+    keydownHandler: (event: any) => void;
+    elements: {};
+    keys: {};
     /**
      * Enable this navigator.
      */
     enable(): void;
-    enabled: boolean | undefined;
+    enabled: boolean;
     /**
      * Disable this navigator.
      */
@@ -85,7 +85,7 @@ declare class DOMNavigator {
      * @param {HTMLElement} el The DOM element to select.
      * @param {string} [direction] The direction.
      */
-    select(el: HTMLElement, direction?: string | undefined): void;
+    select(el: HTMLElement, direction?: string): void;
     /**
      * Remove the current selection
      */

+ 8 - 8
src/types/shared/gif/index.d.ts

@@ -17,21 +17,21 @@ export default class ConverseGif {
     constructor(el: import("lit").LitElement, opts: any);
     options: any;
     el: import("lit").LitElement;
-    gif_el: HTMLImageElement | null;
-    canvas: HTMLCanvasElement | null;
-    ctx: CanvasRenderingContext2D | null;
+    gif_el: HTMLImageElement;
+    canvas: HTMLCanvasElement;
+    ctx: CanvasRenderingContext2D;
     offscreenCanvas: HTMLCanvasElement;
     patchCanvas: HTMLCanvasElement;
     ctx_scaled: boolean;
     frames: any[];
-    load_error: boolean | null;
+    load_error: boolean;
     playing: any;
     frame_idx: number;
     iteration_count: number;
     start: any;
     hovering: any;
-    frameImageData: ImageData | null;
-    disposal_restore_from_idx: number | null;
+    frameImageData: ImageData;
+    disposal_restore_from_idx: number;
     initialize(): Promise<void>;
     initPlayer(): void;
     /**
@@ -83,7 +83,7 @@ export default class ConverseGif {
     } | {
         width: number;
         height: number;
-    } | undefined;
+    };
     lsd: {
         backgroundColorIndex: number;
         gct: {
@@ -95,7 +95,7 @@ export default class ConverseGif {
         height: number;
         width: number;
         pixelAspectRatio: number;
-    } | undefined;
+    };
     drawError(): void;
     showError(): void;
     manageDisposal(i: any): void;

+ 0 - 1
src/types/shared/modals/user-details.d.ts

@@ -1,6 +1,5 @@
 export default class UserDetailsModal extends BaseModal {
     constructor(options: any);
-    tab: string;
     addListeners(): void;
     /**
      * @param {Map<string, any>} changed

+ 1 - 1
src/types/shared/texture/component.d.ts

@@ -57,7 +57,7 @@ export default class Texture extends LitElement {
     show_me_message: boolean;
     render(): import("lit/directive.js").DirectiveResult<{
         new (_partInfo: import("lit/directive.js").PartInfo): {
-            render(text: string, offset: number, options: object, callback?: Function | undefined): import("lit").TemplateResult<1>;
+            render(text: string, offset: number, options: object, callback?: Function): import("lit").TemplateResult<1>;
             readonly _$isConnected: boolean;
             update(_part: import("lit").Part, props: Array<unknown>): unknown;
         };

+ 2 - 2
src/types/shared/texture/directive.d.ts

@@ -1,5 +1,5 @@
 export default renderTexture;
-declare const renderTexture: (text: string, offset: number, options: any, callback?: Function | undefined) => import("lit/directive.js").DirectiveResult<typeof TextureDirective>;
+declare const renderTexture: (text: string, offset: number, options: any, callback?: Function) => import("lit/directive.js").DirectiveResult<typeof TextureDirective>;
 declare class TextureDirective extends Directive {
     /**
      * @param {string} text
@@ -7,7 +7,7 @@ declare class TextureDirective extends Directive {
      * @param {object} options
      * @param {Function} [callback]
      */
-    render(text: string, offset: number, options: object, callback?: Function | undefined): import("lit").TemplateResult<1>;
+    render(text: string, offset: number, options: object, callback?: Function): import("lit").TemplateResult<1>;
 }
 import { Directive } from 'lit/directive.js';
 //# sourceMappingURL=directive.d.ts.map

+ 33 - 33
src/types/shared/texture/texture.d.ts

@@ -57,44 +57,44 @@ export class Texture extends String {
      * @typedef {module:headless-shared-parsers.MediaURLMetadata} MediaURLMetadata
      */
     constructor(text: string, offset?: number, options?: {
-        nick?: string | undefined;
-        render_styling?: boolean | undefined;
-        embed_audio?: boolean | undefined;
-        embed_videos?: boolean | undefined;
-        mentions?: any[] | undefined;
-        media_urls?: any[] | undefined;
-        show_images?: boolean | undefined;
-        show_me_message?: boolean | undefined;
-        onImgClick?: Function | undefined;
-        onImgLoad?: Function | undefined;
-        hide_media_urls?: boolean | undefined;
-    } | undefined);
-    embed_audio: boolean | undefined;
-    embed_videos: boolean | undefined;
+        nick?: string;
+        render_styling?: boolean;
+        embed_audio?: boolean;
+        embed_videos?: boolean;
+        mentions?: any[];
+        media_urls?: any[];
+        show_images?: boolean;
+        show_me_message?: boolean;
+        onImgClick?: Function;
+        onImgLoad?: Function;
+        hide_media_urls?: boolean;
+    });
+    embed_audio: boolean;
+    embed_videos: boolean;
     mentions: any[];
-    media_urls: any[] | undefined;
-    nick: string | undefined;
+    media_urls: any[];
+    nick: string;
     offset: number;
-    onImgClick: Function | undefined;
-    onImgLoad: Function | undefined;
+    onImgClick: Function;
+    onImgLoad: Function;
     options: {
-        nick?: string | undefined;
-        render_styling?: boolean | undefined;
-        embed_audio?: boolean | undefined;
-        embed_videos?: boolean | undefined;
-        mentions?: any[] | undefined;
-        media_urls?: any[] | undefined;
-        show_images?: boolean | undefined;
-        show_me_message?: boolean | undefined;
-        onImgClick?: Function | undefined;
-        onImgLoad?: Function | undefined;
-        hide_media_urls?: boolean | undefined;
+        nick?: string;
+        render_styling?: boolean;
+        embed_audio?: boolean;
+        embed_videos?: boolean;
+        mentions?: any[];
+        media_urls?: any[];
+        show_images?: boolean;
+        show_me_message?: boolean;
+        onImgClick?: Function;
+        onImgLoad?: Function;
+        hide_media_urls?: boolean;
     };
     payload: any[];
     references: any[];
-    render_styling: boolean | undefined;
-    show_images: boolean | undefined;
-    hide_media_urls: boolean | undefined;
+    render_styling: boolean;
+    show_images: boolean;
+    hide_media_urls: boolean;
     /**
      * @param {string} url - The URL to be checked
      * @param {'audio'|'image'|'video'} type - The type of media
@@ -173,6 +173,6 @@ export class Texture extends String {
      * instances to be rendered to the DOM.
      * @method Texture#marshall
      */
-    marshall(): string;
+    marshall(): any[];
 }
 //# sourceMappingURL=texture.d.ts.map

+ 1 - 1
src/types/shared/texture/utils.d.ts

@@ -28,7 +28,7 @@ export function tplMention(o: any): import("lit").TemplateResult<1>;
  * @param {number} i
  */
 export function getDirectiveAndLength(text: import("./texture").Texture, i: number): {
-    d: string | null;
+    d: string;
     length: number;
 } | {
     d?: undefined;

+ 1 - 1
src/types/templates/audio.d.ts

@@ -1,3 +1,3 @@
-declare function _default(url: string, hide_url?: boolean | undefined, title?: string | undefined): import("lit").TemplateResult<1>;
+declare function _default(url: string, hide_url?: boolean, title?: string): import("lit").TemplateResult<1>;
 export default _default;
 //# sourceMappingURL=audio.d.ts.map

+ 1 - 1
src/types/templates/video.d.ts

@@ -1,3 +1,3 @@
-declare function _default(url: string, hide_url?: boolean | undefined): import("lit").TemplateResult<1>;
+declare function _default(url: string, hide_url?: boolean): import("lit").TemplateResult<1>;
 export default _default;
 //# sourceMappingURL=video.d.ts.map