From 6cb59f7071dc39de76fd0fb232937ccf3acd27f2 Mon Sep 17 00:00:00 2001 From: Pierre Boyer Date: Tue, 14 May 2019 08:54:00 +0200 Subject: [PATCH 1/7] Allow left/right arrow keys to navigate through the autocompletion list --- .../views/rooms/MessageComposerInput.js | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js index a525fcb874..e569c5bb3b 100644 --- a/src/components/views/rooms/MessageComposerInput.js +++ b/src/components/views/rooms/MessageComposerInput.js @@ -670,6 +670,31 @@ export default class MessageComposerInput extends React.Component { onKeyDown = (ev: KeyboardEvent, change: Change, editor: Editor) => { this.suppressAutoComplete = false; + this.direction = ''; + + // Navigate autocomplete list with arrow keys + if (this.autocomplete.state.completionList.length > 0) { + if (!(ev.ctrlKey || ev.shiftKey || ev.altKey || ev.metaKey)) { + switch (ev.keyCode) { + case KeyCode.LEFT: + this.moveAutocompleteSelection(true); + ev.preventDefault(); + return true; + case KeyCode.RIGHT: + this.moveAutocompleteSelection(false); + ev.preventDefault(); + return true; + case KeyCode.UP: + this.moveAutocompleteSelection(true); + ev.preventDefault(); + return true; + case KeyCode.DOWN: + this.moveAutocompleteSelection(false); + ev.preventDefault(); + return true; + } + } + } // skip void nodes - see // https://github.com/ianstormtaylor/slate/issues/762#issuecomment-304855095 From 6e4c3bfe5680bb6685d828913dd9f706e205e874 Mon Sep 17 00:00:00 2001 From: Pierre Boyer Date: Tue, 14 May 2019 09:27:20 +0200 Subject: [PATCH 2/7] Remove now unused code --- .../views/rooms/MessageComposerInput.js | 43 ++++++++----------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js index e569c5bb3b..8b54a2d8bb 100644 --- a/src/components/views/rooms/MessageComposerInput.js +++ b/src/components/views/rooms/MessageComposerInput.js @@ -702,8 +702,6 @@ export default class MessageComposerInput extends React.Component { this.direction = 'Previous'; } else if (ev.keyCode === KeyCode.RIGHT) { this.direction = 'Next'; - } else { - this.direction = ''; } switch (ev.keyCode) { @@ -1197,35 +1195,28 @@ export default class MessageComposerInput extends React.Component { }; onVerticalArrow = (e, up) => { - if (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey) { - return; - } + if (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey) return; - // Select history only if we are not currently auto-completing - if (this.autocomplete.state.completionList.length === 0) { - const selection = this.state.editorState.selection; + // Select history + const selection = this.state.editorState.selection; - // selection must be collapsed - if (!selection.isCollapsed) return; - const document = this.state.editorState.document; + // selection must be collapsed + if (!selection.isCollapsed) return; + const document = this.state.editorState.document; - // and we must be at the edge of the document (up=start, down=end) - if (up) { - if (!selection.anchor.isAtStartOfNode(document)) return; + // and we must be at the edge of the document (up=start, down=end) + if (up) { + if (!selection.anchor.isAtStartOfNode(document)) return; - const editEvent = findEditableEvent(this.props.room, false); - if (editEvent) { - // We're selecting history, so prevent the key event from doing anything else - e.preventDefault(); - dis.dispatch({ - action: 'edit_event', - event: editEvent, - }); - } + const editEvent = findEditableEvent(this.props.room, false); + if (editEvent) { + // We're selecting history, so prevent the key event from doing anything else + e.preventDefault(); + dis.dispatch({ + action: 'edit_event', + event: editEvent, + }); } - } else { - this.moveAutocompleteSelection(up); - e.preventDefault(); } }; From bb133c1ebcb291c62c3f6f02d202f180f3d2ced4 Mon Sep 17 00:00:00 2001 From: Pierre Boyer Date: Tue, 14 May 2019 10:13:04 +0200 Subject: [PATCH 3/7] Merge onUpArrow and onDownArrow into more general moveSelection --- src/components/views/rooms/Autocomplete.js | 23 +++++----------------- 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/src/components/views/rooms/Autocomplete.js b/src/components/views/rooms/Autocomplete.js index 9aef5433c3..243cfe2f75 100644 --- a/src/components/views/rooms/Autocomplete.js +++ b/src/components/views/rooms/Autocomplete.js @@ -171,26 +171,13 @@ export default class Autocomplete extends React.Component { } // called from MessageComposerInput - onUpArrow(): ?Completion { + moveSelection(delta): ?Completion { const completionCount = this.countCompletions(); - // completionCount + 1, since 0 means composer is selected - const selectionOffset = (completionCount + 1 + this.state.selectionOffset - 1) - % (completionCount + 1); - if (!completionCount) { - return null; - } - this.setSelection(selectionOffset); - } + if (completionCount === 0) return; // there are no items to move the selection through - // called from MessageComposerInput - onDownArrow(): ?Completion { - const completionCount = this.countCompletions(); - // completionCount + 1, since 0 means composer is selected - const selectionOffset = (this.state.selectionOffset + 1) % (completionCount + 1); - if (!completionCount) { - return null; - } - this.setSelection(selectionOffset); + // Note: selectionOffset 0 represents the unsubstituted text, while 1 means first pill selected + const index = (this.state.selectionOffset + delta + completionCount + 1) % (completionCount + 1); + this.setSelection(index); } onEscape(e): boolean { From 97d4d1b73a3d21289c882ec37043aae8b5c28f8c Mon Sep 17 00:00:00 2001 From: Pierre Boyer Date: Tue, 14 May 2019 10:16:10 +0200 Subject: [PATCH 4/7] Update composer to correctly call countCompletions and moveSelection --- .../views/rooms/MessageComposerInput.js | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js index 8b54a2d8bb..74f358c161 100644 --- a/src/components/views/rooms/MessageComposerInput.js +++ b/src/components/views/rooms/MessageComposerInput.js @@ -673,23 +673,23 @@ export default class MessageComposerInput extends React.Component { this.direction = ''; // Navigate autocomplete list with arrow keys - if (this.autocomplete.state.completionList.length > 0) { + if (this.autocomplete.countCompletions() > 0) { if (!(ev.ctrlKey || ev.shiftKey || ev.altKey || ev.metaKey)) { switch (ev.keyCode) { case KeyCode.LEFT: - this.moveAutocompleteSelection(true); + this.autocomplete.moveSelection(-1); ev.preventDefault(); return true; case KeyCode.RIGHT: - this.moveAutocompleteSelection(false); + this.autocomplete.moveSelection(+1); ev.preventDefault(); return true; case KeyCode.UP: - this.moveAutocompleteSelection(true); + this.autocomplete.moveSelection(-1); ev.preventDefault(); return true; case KeyCode.DOWN: - this.moveAutocompleteSelection(false); + this.autocomplete.moveSelection(+1); ev.preventDefault(); return true; } @@ -1225,23 +1225,19 @@ export default class MessageComposerInput extends React.Component { someCompletions: null, }); e.preventDefault(); - if (this.autocomplete.state.completionList.length === 0) { + if (this.autocomplete.countCompletions() === 0) { // Force completions to show for the text currently entered const completionCount = await this.autocomplete.forceComplete(); this.setState({ someCompletions: completionCount > 0, }); // Select the first item by moving "down" - await this.moveAutocompleteSelection(false); + await this.autocomplete.moveSelection(+1); } else { - await this.moveAutocompleteSelection(e.shiftKey); + await this.autocomplete.moveSelection(e.shiftKey ? -1 : +1); } }; - moveAutocompleteSelection = (up) => { - up ? this.autocomplete.onUpArrow() : this.autocomplete.onDownArrow(); - }; - onEscape = async (e) => { e.preventDefault(); if (this.autocomplete) { From ed6427571e724c53f75d8fd41807df5c7b4950eb Mon Sep 17 00:00:00 2001 From: Pierre Boyer Date: Tue, 4 Jun 2019 13:21:39 +0200 Subject: [PATCH 5/7] Update src/editor/autocomplete to correctly call countCompletions and moveSelection --- src/editor/autocomplete.js | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/src/editor/autocomplete.js b/src/editor/autocomplete.js index ceaf18c444..ba18207de1 100644 --- a/src/editor/autocomplete.js +++ b/src/editor/autocomplete.js @@ -42,31 +42,19 @@ export default class AutocompleteWrapperModel { async onTab(e) { const acComponent = this._getAutocompleterComponent(); - if (acComponent.state.completionList.length === 0) { + if (acComponent.countCompletions() === 0) { // Force completions to show for the text currently entered await acComponent.forceComplete(); // Select the first item by moving "down" - await acComponent.onDownArrow(); + await acComponent.moveSelection(+1); } else { - if (e.shiftKey) { - await acComponent.onUpArrow(); - } else { - await acComponent.onDownArrow(); - } + await acComponent.moveSelection(e.shiftKey ? -1 : +1); } this._updateCallback({ close: true, }); } - onUpArrow() { - this._getAutocompleterComponent().onUpArrow(); - } - - onDownArrow() { - this._getAutocompleterComponent().onDownArrow(); - } - onPartUpdate(part, offset) { // cache the typed value and caret here // so we can restore it in onComponentSelectionChange when the value is undefined (meaning it should be the typed text) From a4dec88c651a731fd40175b0c3260dc85169176b Mon Sep 17 00:00:00 2001 From: Pierre Boyer Date: Tue, 4 Jun 2019 13:57:15 +0200 Subject: [PATCH 6/7] Add back on..Arrow functions. Add left/right key navigation in MessageEditor --- src/components/views/elements/MessageEditor.js | 4 ++++ src/editor/autocomplete.js | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/components/views/elements/MessageEditor.js b/src/components/views/elements/MessageEditor.js index ed86bcb0a3..98569023cb 100644 --- a/src/components/views/elements/MessageEditor.js +++ b/src/components/views/elements/MessageEditor.js @@ -116,6 +116,10 @@ export default class MessageEditor extends React.Component { autoComplete.onUpArrow(event); break; case "ArrowDown": autoComplete.onDownArrow(event); break; + case "ArrowLeft": + autoComplete.onLeftArrow(event); break; + case "ArrowRight": + autoComplete.onRightArrow(event); break; case "Tab": autoComplete.onTab(event); break; case "Escape": diff --git a/src/editor/autocomplete.js b/src/editor/autocomplete.js index ba18207de1..c0dc020897 100644 --- a/src/editor/autocomplete.js +++ b/src/editor/autocomplete.js @@ -55,6 +55,22 @@ export default class AutocompleteWrapperModel { }); } + onUpArrow() { + this._getAutocompleterComponent().moveSelection(-1); + } + + onDownArrow() { + this._getAutocompleterComponent().moveSelection(+1); + } + + onLeftArrow() { + this._getAutocompleterComponent().moveSelection(-1); + } + + onRightArrow() { + this._getAutocompleterComponent().moveSelection(+1); + } + onPartUpdate(part, offset) { // cache the typed value and caret here // so we can restore it in onComponentSelectionChange when the value is undefined (meaning it should be the typed text) From 81585676407bfe603691b7ec49431e0ba9591ed2 Mon Sep 17 00:00:00 2001 From: Pierre Boyer Date: Wed, 5 Jun 2019 10:49:49 +0200 Subject: [PATCH 7/7] Remove left/right autocomplete navigation for MessageEditor --- src/components/views/elements/MessageEditor.js | 4 ---- src/editor/autocomplete.js | 8 -------- 2 files changed, 12 deletions(-) diff --git a/src/components/views/elements/MessageEditor.js b/src/components/views/elements/MessageEditor.js index 98569023cb..ed86bcb0a3 100644 --- a/src/components/views/elements/MessageEditor.js +++ b/src/components/views/elements/MessageEditor.js @@ -116,10 +116,6 @@ export default class MessageEditor extends React.Component { autoComplete.onUpArrow(event); break; case "ArrowDown": autoComplete.onDownArrow(event); break; - case "ArrowLeft": - autoComplete.onLeftArrow(event); break; - case "ArrowRight": - autoComplete.onRightArrow(event); break; case "Tab": autoComplete.onTab(event); break; case "Escape": diff --git a/src/editor/autocomplete.js b/src/editor/autocomplete.js index c0dc020897..ce0550d88e 100644 --- a/src/editor/autocomplete.js +++ b/src/editor/autocomplete.js @@ -63,14 +63,6 @@ export default class AutocompleteWrapperModel { this._getAutocompleterComponent().moveSelection(+1); } - onLeftArrow() { - this._getAutocompleterComponent().moveSelection(-1); - } - - onRightArrow() { - this._getAutocompleterComponent().moveSelection(+1); - } - onPartUpdate(part, offset) { // cache the typed value and caret here // so we can restore it in onComponentSelectionChange when the value is undefined (meaning it should be the typed text)