Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Merge pull request #2966 from npny/npny/autocomplete-arrow-keys
Browse files Browse the repository at this point in the history
Allow arrow keys navigation in autocomplete list
  • Loading branch information
bwindels authored Jun 13, 2019
2 parents 3d944b7 + 8158567 commit 48f5cf1
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 64 deletions.
23 changes: 5 additions & 18 deletions src/components/views/rooms/Autocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
86 changes: 49 additions & 37 deletions src/components/views/rooms/MessageComposerInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -673,15 +673,38 @@ 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.countCompletions() > 0) {
if (!(ev.ctrlKey || ev.shiftKey || ev.altKey || ev.metaKey)) {
switch (ev.keyCode) {
case KeyCode.LEFT:
this.autocomplete.moveSelection(-1);
ev.preventDefault();
return true;
case KeyCode.RIGHT:
this.autocomplete.moveSelection(+1);
ev.preventDefault();
return true;
case KeyCode.UP:
this.autocomplete.moveSelection(-1);
ev.preventDefault();
return true;
case KeyCode.DOWN:
this.autocomplete.moveSelection(+1);
ev.preventDefault();
return true;
}
}
}

// skip void nodes - see
// https://github.com/ianstormtaylor/slate/issues/762#issuecomment-304855095
if (ev.keyCode === KeyCode.LEFT) {
this.direction = 'Previous';
} else if (ev.keyCode === KeyCode.RIGHT) {
this.direction = 'Next';
} else {
this.direction = '';
}

switch (ev.keyCode) {
Expand Down Expand Up @@ -1175,35 +1198,28 @@ export default class MessageComposerInput extends React.Component {
};

onVerticalArrow = (e, up) => {
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;

// 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;

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,
});
}
if (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey) return;

// Select history
const selection = this.state.editorState.selection;

// 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;

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();
}
};

Expand All @@ -1212,23 +1228,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) {
Expand Down
14 changes: 5 additions & 9 deletions src/editor/autocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,29 +43,25 @@ 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();
this._getAutocompleterComponent().moveSelection(-1);
}

onDownArrow() {
this._getAutocompleterComponent().onDownArrow();
this._getAutocompleterComponent().moveSelection(+1);
}

onPartUpdate(part, offset) {
Expand Down

0 comments on commit 48f5cf1

Please sign in to comment.