Просмотр исходного кода

Stop the MUC from extending the 1:1 ChatBox

JC Brand 10 месяцев назад
Родитель
Сommit
978db1fe9d

+ 14 - 6
src/headless/plugins/muc/muc.js

@@ -11,7 +11,6 @@ import p from '../../utils/parse-helpers';
 import _converse from '../../shared/_converse.js';
 import api from '../../shared/api/index.js';
 import converse from '../../shared/api/public.js';
-import ChatBox from '../chat/model.js';
 import {
     ROOMSTATUS,
     OWNER_COMMANDS,
@@ -30,6 +29,9 @@ 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 ModelWithMessages from '../../shared/model-with-messages';
+import ColorAwareModel from '../../shared/color';
+import ChatBoxBase from '../../shared/chatbox';
 import { shouldCreateGroupchatMessage, isInfoVisible } from './utils.js';
 import MUCSession from './session';
 
@@ -38,8 +40,9 @@ const { u } = converse.env;
 /**
  * Represents a groupchat conversation.
  */
-class MUC extends ChatBox {
+class MUC extends ModelWithMessages(ColorAwareModel(ChatBoxBase)) {
     /**
+     * @typedef {import('../vcard/vcard').default} VCard
      * @typedef {import('../chat/message.js').default} Message
      * @typedef {import('./message.js').default} MUCMessage
      * @typedef {import('./occupant.js').default} MUCOccupant
@@ -79,13 +82,19 @@ class MUC extends ChatBox {
     }
 
     async initialize () {
+        super.initialize();
+
+        /**
+         * @public
+         * @type {VCard}
+         */
+        this.vcard = null;
+
         this.initialized = getOpenPromise();
 
         this.debouncedRejoin = debounce(this.rejoin, 250);
         this.set('box_id', `box-${this.get('jid')}`);
-        this.initNotifications();
-        this.initMessages();
-        this.initUI();
+
         this.initOccupants();
         this.initDiscoModels(); // sendChatState depends on this.features
         this.registerHandlers();
@@ -93,7 +102,6 @@ class MUC extends ChatBox {
         this.on('change:chat_state', this.sendChatState, this);
         this.on('change:hidden', this.onHiddenChange, this);
         this.on('destroy', this.removeHandlers, this);
-        this.ui.on('change:scrolled', this.onScrolledChanged, this);
 
         await this.restoreSession();
         this.session.on('change:connection_status', this.onConnectionStatusChanged, this);

+ 1 - 0
src/headless/shared/model-with-messages.js

@@ -44,6 +44,7 @@ export default function ModelWithMessages(BaseModel) {
         /** @param {...any} args */
         constructor(...args) {
             super(args[0], args[1]);
+            this.disable_mam = false;
         }
 
         async initialize() {

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

@@ -1,12 +1,14 @@
 export default ChatBox;
 declare const ChatBox_base: {
     new (...args: any[]): {
+        disable_mam: boolean;
         initialize(): Promise<void>;
         initNotifications(): void;
         notifications: import("@converse/skeletor").Model;
         initUI(): void;
         ui: import("@converse/skeletor").Model;
         getDisplayName(): string;
+        canPostMessages(): boolean;
         createMessage(attrs: any, options: any): Promise<any>;
         getMessagesCacheKey(): string;
         getMessagesCollection(): any;
@@ -15,19 +17,24 @@ declare const ChatBox_base: {
         messages: any;
         fetchMessages(): any;
         afterMessagesFetched(): void;
-        onMessage(_promise: Promise<import("./parsers.js").MessageAttributes>): Promise<void>;
-        getUpdatedMessageAttributes(message: import("./message.js").default, attrs: import("./parsers.js").MessageAttributes): object;
-        updateMessage(message: import("./message.js").default, attrs: import("./parsers.js").MessageAttributes): void;
-        handleCorrection(attrs: import("./parsers.js").MessageAttributes | import("../muc/parsers.js").MUCMessageAttributes): Promise<import("./message.js").default | void>;
-        queueMessage(attrs: Promise<import("./parsers.js").MessageAttributes>): any;
+        onMessage(_promise: Promise<import("./parsers").MessageAttributes>): Promise<void>;
+        getUpdatedMessageAttributes(message: import("./message.js").default, attrs: import("./parsers").MessageAttributes): object;
+        updateMessage(message: import("./message.js").default, attrs: import("./parsers").MessageAttributes): void;
+        handleCorrection(attrs: import("./parsers").MessageAttributes | import("../muc/parsers.js").MUCMessageAttributes): Promise<import("./message.js").default | void>;
+        queueMessage(attrs: Promise<import("./parsers").MessageAttributes>): any;
         msg_chain: any;
-        getOutgoingMessageAttributes(_attrs?: import("./parsers.js").MessageAttributes): Promise<import("./parsers.js").MessageAttributes>;
+        getOutgoingMessageAttributes(_attrs?: import("./parsers").MessageAttributes): Promise<import("./parsers").MessageAttributes>;
         sendMessage(attrs?: any): Promise<import("./message.js").default>;
+        retractOwnMessage(message: import("./message.js").default): 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>;
         onScrolledChanged(): void;
         pruneHistoryWhenScrolledDown(): void;
+        shouldShowErrorMessage(attrs: import("./parsers").MessageAttributes): Promise<boolean>;
         clearMessages(): Promise<void>;
         editEarlierMessage(): void;
         editLaterMessage(): any;
@@ -47,10 +54,11 @@ declare const ChatBox_base: {
         };
         sendMarkerForMessage(msg: import("./message.js").default, type?: ("received" | "displayed" | "acknowledged"), force?: boolean): void;
         handleUnreadMessage(message: import("./message.js").default): void;
+        handleErrorMessageStanza(stanza: Element): Promise<void>;
         incrementUnreadMsgsCounter(message: import("./message.js").default): void;
         clearUnreadMsgCounter(): void;
-        handleRetraction(attrs: import("./parsers.js").MessageAttributes): Promise<boolean>;
-        handleReceipt(attrs: import("./parsers.js").MessageAttributes): boolean;
+        handleRetraction(attrs: import("./parsers").MessageAttributes): Promise<boolean>;
+        handleReceipt(attrs: import("./parsers").MessageAttributes): boolean;
         createMessageStanza(message: import("./message.js").default): Promise<any>;
         pruneHistory(): void;
         debouncedPruneHistory: import("lodash").DebouncedFunc<() => void>;
@@ -277,64 +285,33 @@ declare class ChatBox extends ChatBox_base {
         time_sent: string;
         type: string;
     };
-    disable_mam: boolean;
     initialize(): Promise<void>;
     initialized: any;
     presence: any;
-    /**
-     * @param {Element} stanza
-     */
-    handleErrorMessageStanza(stanza: Element): Promise<void>;
     /**
      * @param {Promise<MessageAttributes|StanzaParseError>} attrs_promise
      */
-    onMessage(attrs_promise: Promise<import("./parsers.js").MessageAttributes | import("../../shared/parsers").StanzaParseError>): Promise<void>;
+    onMessage(attrs_promise: Promise<import("./parsers").MessageAttributes | import("../../shared/parsers").StanzaParseError>): Promise<void>;
     onPresenceChanged(item: any): void;
     close(): Promise<void>;
-    /**
-     * Mutator for setting the chat state of this chat session.
-     * Handles clearing of any chat state notification timeouts and
-     * setting new ones if necessary.
-     * Timeouts are set when the  state being set is COMPOSING or PAUSED.
-     * After the timeout, COMPOSING will become PAUSED and PAUSED will become INACTIVE.
-     * See XEP-0085 Chat State Notifications.
-     * @param {string} state - The chat state (consts ACTIVE, COMPOSING, PAUSED, INACTIVE, GONE)
-     * @param {object} [options]
-     */
-    setChatState(state: string, options?: object): this;
-    chat_state_timeout: NodeJS.Timeout;
     /**
      * @returns {string}
      */
     getDisplayName(): string;
-    /**
-     * @param {MessageAttributes} attrs
-     * @returns {Promise<boolean>}
-     */
-    shouldShowErrorMessage(attrs: import("./parsers.js").MessageAttributes): Promise<boolean>;
     /**
      * @param {string} jid1
      * @param {string} jid2
      */
     isSameUser(jid1: string, jid2: string): any;
-    /**
-     * Retract one of your messages in this chat
-     * @param {Message} message - The message which we're retracting.
-     */
-    retractOwnMessage(message: import("./message.js").default): void;
     /**
      * @param {MessageAttributes} attrs
      */
-    handleChatMarker(attrs: import("./parsers.js").MessageAttributes): boolean;
+    handleChatMarker(attrs: import("./parsers").MessageAttributes): boolean;
     /**
      * @param {MessageAttributes} [attrs]
      * @return {Promise<MessageAttributes>}
      */
-    getOutgoingMessageAttributes(attrs?: import("./parsers.js").MessageAttributes): Promise<import("./parsers.js").MessageAttributes>;
-    /**
-     * @param {File[]} files
-     */
-    sendFiles(files: File[]): Promise<void>;
+    getOutgoingMessageAttributes(attrs?: import("./parsers").MessageAttributes): Promise<import("./parsers").MessageAttributes>;
     canPostMessages(): boolean;
 }
 import ChatBoxBase from '../../shared/chatbox.js';

+ 0 - 2
src/headless/types/plugins/headlines/feed.d.ts

@@ -12,9 +12,7 @@ export default class HeadlinesFeed extends ChatBoxBase {
         time_sent: any;
         type: string;
     };
-    disable_mam: boolean;
     initialize(): Promise<void>;
-    canPostMessages(): boolean;
 }
 import ChatBoxBase from '../../shared/chatbox.js';
 //# sourceMappingURL=feed.d.ts.map

+ 217 - 6
src/headless/types/plugins/muc/muc.d.ts

@@ -1,9 +1,208 @@
 export default MUC;
+declare const MUC_base: {
+    new (...args: any[]): {
+        disable_mam: boolean;
+        initialize(): Promise<void>;
+        initNotifications(): void;
+        notifications: Model;
+        initUI(): void;
+        ui: Model;
+        getDisplayName(): string;
+        canPostMessages(): boolean;
+        createMessage(attrs: any, options: any): Promise<any>;
+        getMessagesCacheKey(): string;
+        getMessagesCollection(): any;
+        getNotificationsText(): any;
+        initMessages(): void;
+        messages: any;
+        fetchMessages(): any;
+        afterMessagesFetched(): void;
+        onMessage(_promise: Promise<import("../chat/parsers").MessageAttributes>): Promise<void>;
+        getUpdatedMessageAttributes(message: import("../chat/message.js").default, attrs: import("../chat/parsers").MessageAttributes): object;
+        updateMessage(message: import("../chat/message.js").default, attrs: import("../chat/parsers").MessageAttributes): void;
+        handleCorrection(attrs: import("../chat/parsers").MessageAttributes | import("./parsers.js").MUCMessageAttributes): Promise<import("../chat/message.js").default | void>;
+        queueMessage(attrs: Promise<import("../chat/parsers").MessageAttributes>): any;
+        msg_chain: any;
+        getOutgoingMessageAttributes(_attrs?: import("../chat/parsers").MessageAttributes): Promise<import("../chat/parsers").MessageAttributes>;
+        sendMessage(attrs?: any): Promise<import("../chat/message.js").default>;
+        retractOwnMessage(message: import("../chat/message.js").default): 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>;
+        onScrolledChanged(): void;
+        pruneHistoryWhenScrolledDown(): void;
+        shouldShowErrorMessage(attrs: import("../chat/parsers").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;
+        getOriginIdQueryAttrs(attrs: object): {
+            origin_id: any;
+            from: any;
+        };
+        getStanzaIdQueryAttrs(attrs: object): {}[];
+        getMessageBodyQueryAttrs(attrs: object): {
+            from: any;
+            msgid: any;
+        };
+        sendMarkerForMessage(msg: import("../chat/message.js").default, type?: ("received" | "displayed" | "acknowledged"), force?: boolean): void;
+        handleUnreadMessage(message: import("../chat/message.js").default): void;
+        handleErrorMessageStanza(stanza: Element): Promise<void>;
+        incrementUnreadMsgsCounter(message: import("../chat/message.js").default): void;
+        clearUnreadMsgCounter(): void;
+        handleRetraction(attrs: import("../chat/parsers").MessageAttributes): Promise<boolean>;
+        handleReceipt(attrs: import("../chat/parsers").MessageAttributes): boolean;
+        createMessageStanza(message: import("../chat/message.js").default): Promise<any>;
+        pruneHistory(): void;
+        debouncedPruneHistory: import("lodash").DebouncedFunc<() => void>;
+        isScrolledUp(): any;
+        isHidden(): boolean;
+        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").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").Attributes): boolean;
+        set(key: string | any, val?: string | any, options?: import("@converse/skeletor/src/types/model").Options): false | any;
+        _changing: boolean;
+        _previousAttributes: any;
+        id: any;
+        _pending: boolean | import("@converse/skeletor/src/types/model").Options;
+        unset(attr: string, options?: import("@converse/skeletor/src/types/model").Options): false | any;
+        clear(options: import("@converse/skeletor/src/types/model").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").Options): any;
+        save(key?: string | import("@converse/skeletor/src/types/model").Attributes, val?: boolean | number | string | import("@converse/skeletor/src/types/model").Options, options?: import("@converse/skeletor/src/types/model").Options): any;
+        destroy(options?: import("@converse/skeletor/src/types/model").Options): boolean;
+        url(): any;
+        parse(resp: import("@converse/skeletor/src/types/model").Options, options?: import("@converse/skeletor/src/types/model").Options): import("@converse/skeletor/src/types/model").Options;
+        isNew(): boolean;
+        isValid(options?: import("@converse/skeletor/src/types/model").Options): boolean;
+        _validate(attrs: import("@converse/skeletor/src/types/model").Attributes, options?: import("@converse/skeletor/src/types/model").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").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").Attributes): boolean;
+        set(key: string | any, val?: string | any, options?: import("@converse/skeletor/src/types/model").Options): false | any;
+        _changing: boolean;
+        _previousAttributes: any;
+        id: any;
+        _pending: boolean | import("@converse/skeletor/src/types/model").Options;
+        unset(attr: string, options?: import("@converse/skeletor/src/types/model").Options): false | any;
+        clear(options: import("@converse/skeletor/src/types/model").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").Options): any;
+        save(key?: string | import("@converse/skeletor/src/types/model").Attributes, val?: boolean | number | string | import("@converse/skeletor/src/types/model").Options, options?: import("@converse/skeletor/src/types/model").Options): any;
+        destroy(options?: import("@converse/skeletor/src/types/model").Options): boolean;
+        url(): any;
+        parse(resp: import("@converse/skeletor/src/types/model").Options, options?: import("@converse/skeletor/src/types/model").Options): import("@converse/skeletor/src/types/model").Options;
+        isNew(): boolean;
+        isValid(options?: import("@converse/skeletor/src/types/model").Options): boolean;
+        _validate(attrs: import("@converse/skeletor/src/types/model").Attributes, options?: import("@converse/skeletor/src/types/model").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 ChatBoxBase;
 /**
  * Represents a groupchat conversation.
  */
-declare class MUC extends ChatBox {
+declare class MUC extends MUC_base {
     /**
+     * @typedef {import('../vcard/vcard').default} VCard
+     * @typedef {import('../chat/message.js').default} Message
      * @typedef {import('./message.js').default} MUCMessage
      * @typedef {import('./occupant.js').default} MUCOccupant
      * @typedef {import('./affiliations/utils.js').NonOutcastAffiliation} NonOutcastAffiliation
@@ -29,6 +228,13 @@ declare class MUC extends ChatBox {
         time_sent: string;
         type: string;
     };
+    initialize(): Promise<void>;
+    /**
+     * @public
+     * @type {VCard}
+     */
+    public vcard: import("../vcard/vcard").default;
+    initialized: any;
     debouncedRejoin: import("lodash").DebouncedFunc<() => Promise<this>>;
     isEntered(): boolean;
     /**
@@ -112,6 +318,10 @@ declare class MUC extends ChatBox {
      * @param {Element} stanza
      */
     handleAffiliationChangedMessage(stanza: Element): void;
+    /**
+     * @param {Element} stanza
+     */
+    handleErrorMessageStanza(stanza: Element): Promise<void>;
     /**
      * Handles incoming message stanzas from the service that hosts this MUC
      * @param {Element} stanza
@@ -189,8 +399,9 @@ declare class MUC extends ChatBox {
      */
     close(ev?: {
         name: string;
-    }): Promise<any>;
+    }): Promise<void>;
     canModerateMessages(): any;
+    canPostMessages(): boolean;
     /**
      * Return an array of unique nicknames based on all occupants and messages in this MUC.
      * @returns {String[]}
@@ -533,9 +744,9 @@ declare class MUC extends ChatBox {
      * passed in attributes map.
      * @param {object} attrs - Attributes representing a received
      *  message, as returned by {@link parseMUCMessage}
-     * @returns {MUCMessage}
+     * @returns {Message}
      */
-    getDuplicateMessage(attrs: object): import("./message.js").default;
+    getDuplicateMessage(attrs: object): import("../chat/message.js").default;
     /**
      * Handler for all MUC messages sent to this groupchat. This method
      * shouldn't be called directly, instead {@link MUC#queueMessage}
@@ -624,8 +835,8 @@ declare class MUC extends ChatBox {
     incrementUnreadMsgsCounter(message: import("./message.js").default): void;
     clearUnreadMsgCounter(): void;
 }
-import ChatBox from '../chat/model.js';
-import MUCSession from './session';
 import { Model } from '@converse/skeletor';
+import ChatBoxBase from '../../shared/chatbox';
+import MUCSession from './session';
 import { TimeoutError } from '../../shared/errors.js';
 //# sourceMappingURL=muc.d.ts.map

+ 8 - 0
src/headless/types/plugins/muc/occupant.d.ts

@@ -1,12 +1,14 @@
 export default MUCOccupant;
 declare const MUCOccupant_base: {
     new (...args: any[]): {
+        disable_mam: boolean;
         initialize(): Promise<void>;
         initNotifications(): void;
         notifications: Model;
         initUI(): void;
         ui: Model;
         getDisplayName(): string;
+        canPostMessages(): boolean;
         createMessage(attrs: any, options: any): Promise<any>;
         getMessagesCacheKey(): string;
         getMessagesCollection(): any;
@@ -23,11 +25,16 @@ declare const MUCOccupant_base: {
         msg_chain: any;
         getOutgoingMessageAttributes(_attrs?: import("../chat/parsers").MessageAttributes): Promise<import("../chat/parsers").MessageAttributes>;
         sendMessage(attrs?: any): Promise<import("../chat").Message>;
+        retractOwnMessage(message: import("../chat").Message): 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): void;
         onMessageUploadChanged(message: import("../chat").Message): Promise<void>;
         onScrolledChanged(): void;
         pruneHistoryWhenScrolledDown(): void;
+        shouldShowErrorMessage(attrs: import("../chat/parsers").MessageAttributes): Promise<boolean>;
         clearMessages(): Promise<void>;
         editEarlierMessage(): void;
         editLaterMessage(): any;
@@ -47,6 +54,7 @@ declare const MUCOccupant_base: {
         };
         sendMarkerForMessage(msg: import("../chat").Message, type?: ("received" | "displayed" | "acknowledged"), force?: boolean): void;
         handleUnreadMessage(message: import("../chat").Message): void;
+        handleErrorMessageStanza(stanza: Element): Promise<void>;
         incrementUnreadMsgsCounter(message: import("../chat").Message): void;
         clearUnreadMsgCounter(): void;
         handleRetraction(attrs: import("../chat/parsers").MessageAttributes): Promise<boolean>;

+ 8 - 0
src/headless/types/shared/chatbox.d.ts

@@ -1,11 +1,13 @@
 declare const ChatBoxBase_base: {
     new (...args: any[]): {
+        disable_mam: boolean;
         initialize(): Promise<void>;
         initNotifications(): void;
         notifications: Model;
         initUI(): void;
         ui: Model;
         getDisplayName(): string;
+        canPostMessages(): boolean;
         createMessage(attrs: any, options: any): Promise<any>;
         getMessagesCacheKey(): string;
         getMessagesCollection(): any;
@@ -22,11 +24,16 @@ declare const ChatBoxBase_base: {
         msg_chain: any;
         getOutgoingMessageAttributes(_attrs?: import("../plugins/chat/parsers.js").MessageAttributes): Promise<import("../plugins/chat/parsers.js").MessageAttributes>;
         sendMessage(attrs?: any): Promise<import("../index.js").Message>;
+        retractOwnMessage(message: import("../index.js").Message): 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>;
         onScrolledChanged(): void;
         pruneHistoryWhenScrolledDown(): void;
+        shouldShowErrorMessage(attrs: import("../plugins/chat/parsers.js").MessageAttributes): Promise<boolean>;
         clearMessages(): Promise<void>;
         editEarlierMessage(): void;
         editLaterMessage(): any;
@@ -46,6 +53,7 @@ declare const ChatBoxBase_base: {
         };
         sendMarkerForMessage(msg: import("../index.js").Message, type?: ("received" | "displayed" | "acknowledged"), force?: boolean): void;
         handleUnreadMessage(message: import("../index.js").Message): void;
+        handleErrorMessageStanza(stanza: Element): Promise<void>;
         incrementUnreadMsgsCounter(message: import("../index.js").Message): void;
         clearUnreadMsgCounter(): void;
         handleRetraction(attrs: import("../plugins/chat/parsers.js").MessageAttributes): Promise<boolean>;

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

@@ -1,9 +1,17 @@
 /**
+ * Adds a messages collection to a model and various methods related to sending
+ * and receiving chat messages.
+ *
+ * This model should be UX-agnostic, except when it comes to the rendering of
+ * messages. So there's no assumption of uniformity with regards to UI elements
+ * represented by this object.
+ *
  * @template {import('./types').ModelExtender} T
  * @param {T} BaseModel
  */
 export default function ModelWithMessages<T extends import("./types").ModelExtender>(BaseModel: T): {
     new (...args: any[]): {
+        disable_mam: boolean;
         initialize(): Promise<void>;
         initNotifications(): void;
         notifications: Model;
@@ -13,6 +21,7 @@ export default function ModelWithMessages<T extends import("./types").ModelExten
          * @returns {string}
          */
         getDisplayName(): string;
+        canPostMessages(): boolean;
         /**
          * Queue the creation of a message, to make sure that we don't run
          * into a race condition whereby we're creating a new message
@@ -72,6 +81,15 @@ export default function ModelWithMessages<T extends import("./types").ModelExten
          *  chat.sendMessage({'body': 'hello world'});
          */
         sendMessage(attrs?: any): Promise<import("../plugins/chat/message").default>;
+        /**
+         * Retract one of your messages in this chat
+         * @param {Message} message - The message which we're retracting.
+         */
+        retractOwnMessage(message: import("../plugins/chat/message").default): void;
+        /**
+         * @param {File[]} files
+         */
+        sendFiles(files: File[]): Promise<void>;
         /**
          * Responsible for setting the editable attribute of messages.
          * If api.settings.get('allow_message_corrections') is "last", then only the last
@@ -81,6 +99,18 @@ export default function ModelWithMessages<T extends import("./types").ModelExten
          * @param {String} send_time - time when the message was sent
          */
         setEditable(attrs: any, send_time: string): void;
+        /**
+         * Mutator for setting the chat state of this chat session.
+         * Handles clearing of any chat state notification timeouts and
+         * setting new ones if necessary.
+         * Timeouts are set when the  state being set is COMPOSING or PAUSED.
+         * After the timeout, COMPOSING will become PAUSED and PAUSED will become INACTIVE.
+         * See XEP-0085 Chat State Notifications.
+         * @param {string} state - The chat state (consts ACTIVE, COMPOSING, PAUSED, INACTIVE, GONE)
+         * @param {object} [options]
+         */
+        setChatState(state: string, options?: object): any;
+        chat_state_timeout: NodeJS.Timeout;
         /**
          * @param {Message} message
          */
@@ -91,6 +121,11 @@ export default function ModelWithMessages<T extends import("./types").ModelExten
         onMessageUploadChanged(message: import("../plugins/chat/message").default): Promise<void>;
         onScrolledChanged(): void;
         pruneHistoryWhenScrolledDown(): void;
+        /**
+         * @param {MessageAttributes} attrs
+         * @returns {Promise<boolean>}
+         */
+        shouldShowErrorMessage(attrs: import("../plugins/chat/parsers").MessageAttributes): Promise<boolean>;
         clearMessages(): Promise<void>;
         editEarlierMessage(): void;
         editLaterMessage(): any;
@@ -152,6 +187,10 @@ export default function ModelWithMessages<T extends import("./types").ModelExten
          * @param {Message} message
          */
         handleUnreadMessage(message: import("../plugins/chat/message").default): void;
+        /**
+         * @param {Element} stanza
+         */
+        handleErrorMessageStanza(stanza: Element): Promise<void>;
         /**
          * @param {Message} message
          */

+ 1 - 2
src/types/plugins/minimize/index.d.ts

@@ -1,3 +1,2 @@
-export type MUC = import("@converse/headless").MUC;
-export type ChatBox = import("@converse/headless").ChatBox;
+export {};
 //# sourceMappingURL=index.d.ts.map

+ 3 - 4
src/types/plugins/minimize/utils.d.ts

@@ -1,5 +1,5 @@
 /**
- * @param { ChatBox|MUC } chat
+ * @param {ChatBox|MUC} chat
  */
 export function initializeChat(chat: ChatBox | MUC): void;
 /**
@@ -7,8 +7,7 @@ export function initializeChat(chat: ChatBox | MUC): void;
  * It checks whether there is enough space on the page to show
  * another chat box. Otherwise it minimizes the oldest chat box
  * to create space.
- * @method _converse.ChatBoxViews#trimChats
- * @param { ChatView|MUCView|ControlBoxView|HeadlinesFeedView } [newchat]
+ * @param {ChatView|MUCView|ControlBoxView|HeadlinesFeedView} [newchat]
  */
 export function trimChats(newchat?: ChatView | MUCView | ControlBoxView | HeadlinesFeedView): void;
 export function addMinimizeButtonToChat(view: any, buttons: any): any[];
@@ -16,7 +15,7 @@ export function addMinimizeButtonToMUC(view: any, buttons: any): any[];
 export function maximize(ev: any, chatbox: any): void;
 export function minimize(ev: any, model: any): void;
 /**
- * @param { ChatBox|MUC } model
+ * @param {ChatBox|MUC} model
  */
 export function onMinimizedChanged(model: ChatBox | MUC): void;
 export type MUC = import("@converse/headless").MUC;

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

@@ -1,13 +1,13 @@
 export function getHeadingDropdownItem(promise_or_data: any): Promise<import("lit").TemplateResult<1> | "">;
 export function getHeadingStandaloneButton(promise_or_data: any): Promise<import("lit").TemplateResult<1>>;
 /**
- * @param {Promise} promise
+ * @param {Promise<Array<object>>} promise
  */
-export function getStandaloneButtons(promise: Promise<any>): Promise<any>;
+export function getStandaloneButtons(promise: Promise<Array<object>>): Promise<import("lit/directive.js").DirectiveResult<typeof import("lit/directives/until.js").UntilDirective>[]>;
 /**
- * @param {Promise} promise
+ * @param {Promise<Array<object>>} promise
  */
-export function getDropdownButtons(promise: Promise<any>): Promise<import("lit").TemplateResult<1> | "">;
+export function getDropdownButtons(promise: Promise<Array<object>>): Promise<import("lit").TemplateResult<1> | "">;
 export function onScrolledDown(model: any): void;
 /**
  * Given a message object, returns a TemplateResult indicating a new day if