From 1523d304f29b177d222ff41e15ce16b569fd2a1b Mon Sep 17 00:00:00 2001
From: Luke Barnard <lukeb@openmarket.com>
Date: Wed, 28 Jun 2017 10:30:59 +0100
Subject: [PATCH 1/3] WIP to prevent RTE from deleting current message input
 when up arrow pressed

---
 src/components/views/rooms/MessageComposerInput.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js
index b05beb2571..7603a45e4c 100644
--- a/src/components/views/rooms/MessageComposerInput.js
+++ b/src/components/views/rooms/MessageComposerInput.js
@@ -560,7 +560,7 @@ export default class MessageComposerInput extends React.Component {
 
     onUpArrow = async (e) => {
         const completion = this.autocomplete.onUpArrow();
-        if (completion == null) {
+        if (completion == null && !(this.historyManager.currentIndex === -1 && this.state.editorState.getCurrentContent().hasText())) {
             const newContent = this.historyManager.getItem(-1, this.state.isRichtextEnabled ? 'html' : 'markdown');
             if (!newContent) return false;
             const editorState = EditorState.push(this.state.editorState,
@@ -575,7 +575,7 @@ export default class MessageComposerInput extends React.Component {
 
     onDownArrow = async (e) => {
         const completion = this.autocomplete.onDownArrow();
-        if (completion == null) {
+        if (completion == null && !(this.historyManager.currentIndex === -1 && this.state.editorState.getCurrentContent().hasText())) {
             const newContent = this.historyManager.getItem(+1, this.state.isRichtextEnabled ? 'html' : 'markdown');
             if (!newContent) return false;
             const editorState = EditorState.push(this.state.editorState,

From bcb67bb273c9b1860b15c0355c2cb26d20714f97 Mon Sep 17 00:00:00 2001
From: Luke Barnard <lukeb@openmarket.com>
Date: Wed, 28 Jun 2017 15:20:16 +0100
Subject: [PATCH 2/3] Refactor shared code between `onUpArrow` and
 `onDownArrow`

---
 .../views/rooms/MessageComposerInput.js       | 42 +++++++++----------
 1 file changed, 20 insertions(+), 22 deletions(-)

diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js
index 7603a45e4c..90ac905553 100644
--- a/src/components/views/rooms/MessageComposerInput.js
+++ b/src/components/views/rooms/MessageComposerInput.js
@@ -556,36 +556,34 @@ export default class MessageComposerInput extends React.Component {
         this.autocomplete.hide();
 
         return true;
+    }
+
+    selectHistory = async (completion, delta) => {
+        if (completion == null) {
+            const newContent = this.historyManager.getItem(delta, this.state.isRichtextEnabled ? 'html' : 'markdown');
+            if (!newContent) return false;
+            let editorState = EditorState.push(
+                this.state.editorState,
+                newContent,
+                'insert-characters',
+            );
+
+            this.setState({editorState});
+            return true;
+        }
+        return await this.setDisplayedCompletion(completion);
     };
 
     onUpArrow = async (e) => {
-        const completion = this.autocomplete.onUpArrow();
-        if (completion == null && !(this.historyManager.currentIndex === -1 && this.state.editorState.getCurrentContent().hasText())) {
-            const newContent = this.historyManager.getItem(-1, this.state.isRichtextEnabled ? 'html' : 'markdown');
-            if (!newContent) return false;
-            const editorState = EditorState.push(this.state.editorState,
-                newContent,
-                'insert-characters');
-            this.setState({editorState});
-            return true;
-        }
         e.preventDefault();
-        return await this.setDisplayedCompletion(completion);
+        const completion = this.autocomplete.onUpArrow();
+        return this.selectHistory(completion, -1);
     };
 
     onDownArrow = async (e) => {
-        const completion = this.autocomplete.onDownArrow();
-        if (completion == null && !(this.historyManager.currentIndex === -1 && this.state.editorState.getCurrentContent().hasText())) {
-            const newContent = this.historyManager.getItem(+1, this.state.isRichtextEnabled ? 'html' : 'markdown');
-            if (!newContent) return false;
-            const editorState = EditorState.push(this.state.editorState,
-                newContent,
-                'insert-characters');
-            this.setState({editorState});
-            return true;
-        }
         e.preventDefault();
-        return await this.setDisplayedCompletion(completion);
+        const completion = this.autocomplete.onDownArrow();
+        return this.selectHistory(completion, -1);
     };
 
     // tab and shift-tab are mapped to down and up arrow respectively

From d696373bc283f475a9e7921055990d7f313ffa37 Mon Sep 17 00:00:00 2001
From: Luke Barnard <lukeb@openmarket.com>
Date: Wed, 28 Jun 2017 15:29:07 +0100
Subject: [PATCH 3/3] Fix issue where the cursor is put at the start of
 selected history item

Leading to strange behaviour when selecting all and deleting it.

Fixes https://github.com/vector-im/riot-web/issues/4450
---
 src/components/views/rooms/MessageComposerInput.js | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js
index 90ac905553..c5fab8242e 100644
--- a/src/components/views/rooms/MessageComposerInput.js
+++ b/src/components/views/rooms/MessageComposerInput.js
@@ -568,6 +568,14 @@ export default class MessageComposerInput extends React.Component {
                 'insert-characters',
             );
 
+            // Move selection to the end of the selected history
+            let newSelection = SelectionState.createEmpty(newContent.getLastBlock().getKey());
+            newSelection = newSelection.merge({
+                focusOffset: newContent.getLastBlock().getLength(),
+                anchorOffset: newContent.getLastBlock().getLength(),
+            });
+            editorState = EditorState.forceSelection(editorState, newSelection);
+
             this.setState({editorState});
             return true;
         }