Browse Source

new config option: allow_message_corrections

Christoph Scholz 5 years ago
parent
commit
1c7c25091f

+ 2 - 0
CHANGES.md

@@ -8,6 +8,8 @@
 - Bugfix: process stanzas from mam one-by-one in order to correctly process message
   receipts
 - #1714 Bugfix: Don't notify the user in case we're receiving a message delivery receipt only
+- add config option [allow_message_corrections](https://conversejs.org/docs/html/configuration.html#allow_message_corrections)
+  which, if set to `last`, limits editing of sent messages to the last message sent
 
 ## 5.0.3 (2019-09-13)
 

+ 11 - 0
docs/source/configuration.rst

@@ -780,6 +780,17 @@ keepalive
 
 Determines whether Converse will attempt to keep you logged in across page loads.
 
+.. _`allow_message_corrections`:
+
+allow_message_corrections
+-------------------------
+
+* Default:  ``'all'``
+
+Configures the last message correction (LMC) feature of Converse. By default you can edit all of your own
+messages. Setting this to ``'last'`` will limit this feature to the message sent most recently as suggested by
+`XEP-0308: Last Message Correction <https://xmpp.org/extensions/xep-0308.html>`_.
+Setting it to anything else (including ``false``) will disable the ability to correct sent messages.
 
 .. _`locales`:
 

+ 1 - 1
src/converse-chatview.js

@@ -988,7 +988,7 @@ converse.plugins.add('converse-chatview', {
                     while (idx > 0) {
                         idx -= 1;
                         const candidate = this.model.messages.at(idx);
-                        if (candidate.get('sender') === 'me' && candidate.get('message')) {
+                        if (candidate.get('editable')) {
                             message = candidate;
                             break;
                         }

+ 1 - 1
src/converse-message-view.js

@@ -154,7 +154,7 @@ converse.plugins.add('converse-message-view', {
                     return this.renderFileUploadProgresBar();
                 }
                 const isValidChange = prop => Object.prototype.hasOwnProperty.call(this.model.changed, prop);
-                if (['correcting', 'message', 'type', 'upload', 'received'].filter(isValidChange).length) {
+                if (['correcting', 'message', 'type', 'upload', 'received', 'editable'].filter(isValidChange).length) {
                     await this.debouncedRender();
                 }
                 if (edited) {

+ 34 - 0
src/headless/converse-chatboxes.js

@@ -41,6 +41,7 @@ converse.plugins.add('converse-chatboxes', {
             'auto_join_private_chats': [],
             'clear_messages_on_reconnection': false,
             'filter_by_resource': false,
+            'allow_message_corrections': 'all',
             'send_chat_state_notifications': true
         });
         _converse.api.promises.add([
@@ -285,6 +286,7 @@ converse.plugins.add('converse-chatboxes', {
                     'message_type': 'chat',
                     'nickname': undefined,
                     'num_unread': 0,
+                    'time_sent': (new Date(0)).toISOString(),
                     'time_opened': this.get('time_opened') || (new Date()).getTime(),
                     'type': _converse.PRIVATE_CHAT_TYPE,
                     'url': ''
@@ -765,6 +767,36 @@ converse.plugins.add('converse-chatboxes', {
                 }
             },
 
+            /**
+             * Responsible for setting the editable attribute of messages.
+             * If _converse.allow_message_corrections is "last", then only the last
+             * message sent from me will be editable. If set to "all" all messages
+             * will be editable. Otherwise no messages will be editable.
+             * @method _converse.ChatBox#setEditable
+             * @memberOf _converse.ChatBox
+             * @param { Object } attrs An object containing message attributes.
+             * @param { String } send_time - time when the message was sent
+             */
+            setEditable (attrs, send_time, stanza) {
+                if (stanza && u.isHeadlineMessage(_converse, stanza)) {
+                    return;
+                }
+                if (u.isEmptyMessage(attrs) || attrs.sender !== 'me') {
+                    return;
+                }
+                if (_converse.allow_message_corrections === 'all') {
+                    attrs.editable = true;
+                } else if ((_converse.allow_message_corrections === 'last') &&
+                           (send_time > this.get('time_sent'))) {
+                    this.set({'time_sent': send_time});
+                    const msg = this.messages.findWhere({'editable': true});
+                    if (msg) {
+                        msg.save({'editable': false});
+                    }
+                    attrs.editable = true;
+                }
+            },
+
             /**
              * Responsible for sending off a text message inside an ongoing chat conversation.
              * @method _converse.ChatBox#sendMessage
@@ -793,6 +825,7 @@ converse.plugins.add('converse-chatboxes', {
                         'received': undefined
                     });
                 } else {
+                    this.setEditable(attrs, (new Date()).toISOString());
                     message = this.messages.create(attrs);
                 }
                 _converse.api.send(this.createMessageStanza(message));
@@ -1258,6 +1291,7 @@ converse.plugins.add('converse-chatboxes', {
                             !chatbox.handleChatMarker(stanza, from_jid, is_carbon, is_roster_contact, is_mam)) {
 
                         const attrs = await chatbox.getMessageAttributesFromStanza(stanza, original_stanza);
+                        chatbox.setEditable(attrs, attrs.time, stanza);
                         if (attrs['chat_state'] || !u.isEmptyMessage(attrs)) {
                             const msg = chatbox.correctMessage(attrs) || chatbox.messages.create(attrs);
                             chatbox.incrementUnreadMsgCounter(msg);

+ 2 - 0
src/headless/converse-muc.js

@@ -399,6 +399,7 @@ converse.plugins.add('converse-muc', {
                     'name': '',
                     'num_unread': 0,
                     'roomconfig': {},
+                    'time_sent': (new Date(0)).toISOString(),
                     'time_opened': this.get('time_opened') || (new Date()).getTime(),
                     'type': _converse.CHATROOMS_TYPE
                 }
@@ -1578,6 +1579,7 @@ converse.plugins.add('converse-muc', {
                     return _converse.api.trigger('message', {'stanza': original_stanza});
                 }
                 const attrs = await this.getMessageAttributesFromStanza(stanza, original_stanza);
+                this.setEditable(attrs, attrs.time);
                 if (attrs.nick &&
                         !this.subjectChangeHandled(attrs) &&
                         !this.ignorableCSN(attrs) &&

+ 1 - 1
src/templates/message.html

@@ -31,7 +31,7 @@
             </div>
             {[ if (o.received && !o.is_me_message && !o.is_groupchat_message) { ]} <span class="fa fa-check chat-msg__receipt"></span> {[ } ]}
             {[ if (o.edited) { ]} <i title="{{{o.__('This message has been edited')}}}" class="fa fa-edit chat-msg__edit-modal"></i> {[ } ]}
-            {[ if (o.type !== 'headline' && o.sender === 'me') { ]}
+            {[ if (o.editable) { ]}
                 <div class="chat-msg__actions">
                     <button class="chat-msg__action chat-msg__action-edit fa fa-pencil-alt" title="{{{o.__('Edit this message')}}}"></button>
                 </div>