ソースを参照

Allow any earlier message to be edited.

updates #421
JC Brand 7 年 前
コミット
b4d2007972
3 ファイル変更149 行追加33 行削除
  1. 50 16
      dist/converse.js
  2. 56 0
      spec/messages.js
  3. 43 17
      src/converse-chatview.js

+ 50 - 16
dist/converse.js

@@ -70210,9 +70210,9 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
           if (ev.keyCode === KEY.ENTER) {
             this.onFormSubmitted(ev);
           } else if (ev.keyCode === KEY.UP_ARROW && !ev.target.selectionEnd) {
-            this.editPreviousMessage();
+            this.editEarlierMessage();
           } else if (ev.keyCode === KEY.DOWN_ARROW && ev.target.selectionEnd === ev.target.value.length) {
-            this.cancelMessageCorrection();
+            this.editLaterMessage();
           } else if (ev.keyCode !== KEY.FORWARD_SLASH && this.model.get('chat_state') !== _converse.COMPOSING) {
             // Set chat state to composing if keyCode is not a forward-slash
             // (which would imply an internal command and not a message).
@@ -70220,19 +70220,53 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
           }
         },
 
-        cancelMessageCorrection() {
-          this.insertIntoTextArea('', true);
-          this.model.messages.where('correcting').forEach(msg => msg.save('correcting', false));
+        editLaterMessage() {
+          let message;
+          let idx = this.model.messages.findLastIndex('correcting');
+
+          if (idx >= 0) {
+            this.model.messages.at(idx).save('correcting', false);
+
+            while (idx < this.model.messages.length - 1) {
+              idx += 1;
+
+              if (this.model.messages.at(idx).get('message')) {
+                message = this.model.messages.at(idx);
+                break;
+              }
+            }
+          }
+
+          if (message) {
+            this.insertIntoTextArea(message.get('message'), true);
+            message.save('correcting', true);
+          } else {
+            this.insertIntoTextArea('', true);
+          }
         },
 
-        editPreviousMessage() {
-          const msg = _.findLast(this.model.messages.models, msg => msg.get('message'));
+        editEarlierMessage() {
+          let message;
+          let idx = this.model.messages.findLastIndex('correcting');
+
+          if (idx >= 0) {
+            this.model.messages.at(idx).save('correcting', false);
+
+            while (idx > 0) {
+              idx -= 1;
+
+              if (this.model.messages.at(idx).get('message')) {
+                message = this.model.messages.at(idx);
+                break;
+              }
+            }
+          }
 
-          if (msg) {
-            this.insertIntoTextArea(msg.get('message'), true); // We don't set "correcting" the Backbone-way, because
-            // we don't want it to persist to storage.
+          message = message || _.findLast(this.model.messages.models, msg => msg.get('message'));
 
-            msg.save('correcting', true);
+          if (message) {
+            this.insertIntoTextArea(message.get('message'), true);
+            message.save('correcting', true);
           }
         },
 
@@ -70260,21 +70294,21 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
         },
 
         insertIntoTextArea(value, replace = false) {
-          const textbox_el = this.el.querySelector('.chat-textarea');
+          const textarea = this.el.querySelector('.chat-textarea');
 
           if (replace) {
-            textbox_el.value = value;
+            textarea.value = value;
           } else {
-            let existing = textbox_el.value;
+            let existing = textarea.value;
 
             if (existing && existing[existing.length - 1] !== ' ') {
               existing = existing + ' ';
             }
 
-            textbox_el.value = existing + value + ' ';
+            textarea.value = existing + value + ' ';
           }
 
-          textbox_el.focus();
+          textarea.focus();
         },
 
         createEmojiPicker() {

+ 56 - 0
spec/messages.js

@@ -106,6 +106,62 @@
             expect(view.model.messages.at(0).get('correcting')).toBe(false);
             expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
             expect(u.hasClass('correcting', view.el.querySelector('.chat-msg'))).toBe(false);
+
+            textarea.value = 'It is the east, and Juliet is the one.';
+            view.keyPressed({
+                target: textarea,
+                preventDefault: _.noop,
+                keyCode: 13 // Enter
+            });
+            expect(view.el.querySelectorAll('.chat-msg').length).toBe(2);
+
+            textarea.value =  'Arise, fair sun, and kill the envious moon';
+            view.keyPressed({
+                target: textarea,
+                preventDefault: _.noop,
+                keyCode: 13 // Enter
+            });
+            expect(view.el.querySelectorAll('.chat-msg').length).toBe(3);
+
+            view.keyPressed({
+                target: textarea,
+                keyCode: 38 // Up arrow
+            });
+            expect(textarea.value).toBe('Arise, fair sun, and kill the envious moon');
+            expect(view.model.messages.at(0).get('correcting')).toBeFalsy();
+            expect(view.model.messages.at(1).get('correcting')).toBeFalsy();
+            expect(view.model.messages.at(2).get('correcting')).toBe(true);
+
+            textarea.selectionEnd = 0; // Happens by pressing up,
+                                       // but for some reason not in tests, so we set it manually.
+            view.keyPressed({
+                target: textarea,
+                keyCode: 38 // Up arrow
+            });
+            expect(textarea.value).toBe('It is the east, and Juliet is the one.');
+            expect(view.model.messages.at(0).get('correcting')).toBeFalsy();
+            expect(view.model.messages.at(1).get('correcting')).toBe(true);
+            expect(view.model.messages.at(2).get('correcting')).toBeFalsy();
+
+            textarea.value = 'It is the east, and Juliet is the sun.';
+            view.keyPressed({
+                target: textarea,
+                preventDefault: _.noop,
+                keyCode: 13 // Enter
+            });
+            expect(textarea.value).toBe('');
+            const messages = view.el.querySelectorAll('.chat-msg');
+            expect(messages.length).toBe(3);
+            expect(messages[0].querySelector('.chat-msg-text').textContent)
+                .toBe('But soft, what light through yonder window breaks?');
+            expect(messages[1].querySelector('.chat-msg-text').textContent)
+                .toBe('It is the east, and Juliet is the sun.');
+            expect(messages[2].querySelector('.chat-msg-text').textContent)
+                .toBe('Arise, fair sun, and kill the envious moon');
+
+            expect(view.model.messages.at(0).get('correcting')).toBeFalsy();
+            expect(view.model.messages.at(1).get('correcting')).toBeFalsy();
+            expect(view.model.messages.at(2).get('correcting')).toBeFalsy();
             done();
         }));
 

+ 43 - 17
src/converse-chatview.js

@@ -919,9 +919,9 @@
                     if (ev.keyCode === KEY.ENTER) {
                         this.onFormSubmitted(ev);
                     } else if (ev.keyCode === KEY.UP_ARROW && !ev.target.selectionEnd) {
-                        this.editPreviousMessage();
+                        this.editEarlierMessage();
                     } else if (ev.keyCode === KEY.DOWN_ARROW && ev.target.selectionEnd === ev.target.value.length) {
-                        this.cancelMessageCorrection();
+                        this.editLaterMessage();
                     } else if (ev.keyCode !== KEY.FORWARD_SLASH && this.model.get('chat_state') !== _converse.COMPOSING) {
                         // Set chat state to composing if keyCode is not a forward-slash
                         // (which would imply an internal command and not a message).
@@ -929,18 +929,44 @@
                     }
                 },
 
-                cancelMessageCorrection () {
-                    this.insertIntoTextArea('', true);
-                    this.model.messages.where('correcting').forEach(msg => msg.save('correcting', false));
+                editLaterMessage () {
+                    let message;
+                    let idx = this.model.messages.findLastIndex('correcting');
+                    if (idx >= 0) {
+                        this.model.messages.at(idx).save('correcting', false);
+                        while (idx < this.model.messages.length-1) {
+                            idx += 1;
+                            if (this.model.messages.at(idx).get('message')) {
+                                message = this.model.messages.at(idx);
+                                break;
+                            }
+                        }
+                    }
+                    if (message) {
+                        this.insertIntoTextArea(message.get('message'), true);
+                        message.save('correcting', true);
+                    } else {
+                        this.insertIntoTextArea('', true);
+                    }
                 },
 
-                editPreviousMessage () {
-                    const msg = _.findLast(this.model.messages.models, (msg) => msg.get('message'));
-                    if (msg) {
-                        this.insertIntoTextArea(msg.get('message'), true);
-                        // We don't set "correcting" the Backbone-way, because
-                        // we don't want it to persist to storage.
-                        msg.save('correcting', true);
+                editEarlierMessage () {
+                    let message;
+                    let idx = this.model.messages.findLastIndex('correcting');
+                    if (idx >= 0) {
+                        this.model.messages.at(idx).save('correcting', false);
+                        while (idx > 0) {
+                            idx -= 1;
+                            if (this.model.messages.at(idx).get('message')) {
+                                message = this.model.messages.at(idx);
+                                break;
+                            }
+                        }
+                    }
+                    message = message || _.findLast(this.model.messages.models, (msg) => msg.get('message'));
+                    if (message) {
+                        this.insertIntoTextArea(message.get('message'), true);
+                        message.save('correcting', true);
                     }
                 },
 
@@ -961,17 +987,17 @@
                 },
 
                 insertIntoTextArea (value, replace=false) {
-                    const textbox_el = this.el.querySelector('.chat-textarea');
+                    const textarea = this.el.querySelector('.chat-textarea');
                     if (replace) {
-                        textbox_el.value = value;
+                        textarea.value = value;
                     } else {
-                        let existing = textbox_el.value;
+                        let existing = textarea.value;
                         if (existing && (existing[existing.length-1] !== ' ')) {
                             existing = existing + ' ';
                         }
-                        textbox_el.value = existing+value+' ';
+                        textarea.value = existing+value+' ';
                     }
-                    textbox_el.focus()
+                    textarea.focus()
                 },
 
                 createEmojiPicker () {