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

Commit 7c4437a

Browse files
authored
Merge pull request #5815 from czeidler/keybindings-follow-up
Keybindings follow up
2 parents b7ee11a + be00320 commit 7c4437a

File tree

8 files changed

+58
-57
lines changed

8 files changed

+58
-57
lines changed

src/KeyBindingsDefaults.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,27 +161,27 @@ const messageComposerBindings = (): KeyBinding<MessageComposerAction>[] => {
161161
const autocompleteBindings = (): KeyBinding<AutocompleteAction>[] => {
162162
return [
163163
{
164-
action: AutocompleteAction.ApplySelection,
164+
action: AutocompleteAction.CompleteOrNextSelection,
165165
keyCombo: {
166166
key: Key.TAB,
167167
},
168168
},
169169
{
170-
action: AutocompleteAction.ApplySelection,
170+
action: AutocompleteAction.CompleteOrNextSelection,
171171
keyCombo: {
172172
key: Key.TAB,
173173
ctrlKey: true,
174174
},
175175
},
176176
{
177-
action: AutocompleteAction.ApplySelection,
177+
action: AutocompleteAction.CompleteOrPrevSelection,
178178
keyCombo: {
179179
key: Key.TAB,
180180
shiftKey: true,
181181
},
182182
},
183183
{
184-
action: AutocompleteAction.ApplySelection,
184+
action: AutocompleteAction.CompleteOrPrevSelection,
185185
keyCombo: {
186186
key: Key.TAB,
187187
ctrlKey: true,

src/KeyBindingsManager.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,19 @@ export enum MessageComposerAction {
5252

5353
/** Actions for text editing autocompletion */
5454
export enum AutocompleteAction {
55-
/** Apply the current autocomplete selection */
56-
ApplySelection = 'ApplySelection',
57-
/** Cancel autocompletion */
58-
Cancel = 'Cancel',
55+
/**
56+
* Select previous selection or, if the autocompletion window is not shown, open the window and select the first
57+
* selection.
58+
*/
59+
CompleteOrPrevSelection = 'ApplySelection',
60+
/** Select next selection or, if the autocompletion window is not shown, open it and select the first selection */
61+
CompleteOrNextSelection = 'CompleteOrNextSelection',
5962
/** Move to the previous autocomplete selection */
6063
PrevSelection = 'PrevSelection',
6164
/** Move to the next autocomplete selection */
6265
NextSelection = 'NextSelection',
66+
/** Close the autocompletion window */
67+
Cancel = 'Cancel',
6368
}
6469

6570
/** Actions for the room list sidebar */

src/components/structures/LeftPanel.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ import { UPDATE_EVENT } from "../../stores/AsyncStore";
3434
import ResizeNotifier from "../../utils/ResizeNotifier";
3535
import SettingsStore from "../../settings/SettingsStore";
3636
import RoomListStore, { LISTS_UPDATE_EVENT } from "../../stores/room-list/RoomListStore";
37-
import {Key} from "../../Keyboard";
3837
import IndicatorScrollbar from "../structures/IndicatorScrollbar";
3938
import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton";
4039
import { OwnProfileStore } from "../../stores/OwnProfileStore";
@@ -43,6 +42,7 @@ import LeftPanelWidget from "./LeftPanelWidget";
4342
import {replaceableComponent} from "../../utils/replaceableComponent";
4443
import {mediaFromMxc} from "../../customisations/Media";
4544
import SpaceStore, {UPDATE_SELECTED_SPACE} from "../../stores/SpaceStore";
45+
import { getKeyBindingsManager, RoomListAction } from "../../KeyBindingsManager";
4646

4747
interface IProps {
4848
isMinimized: boolean;
@@ -297,17 +297,18 @@ export default class LeftPanel extends React.Component<IProps, IState> {
297297
private onKeyDown = (ev: React.KeyboardEvent) => {
298298
if (!this.focusedElement) return;
299299

300-
switch (ev.key) {
301-
case Key.ARROW_UP:
302-
case Key.ARROW_DOWN:
300+
const action = getKeyBindingsManager().getRoomListAction(ev);
301+
switch (action) {
302+
case RoomListAction.NextRoom:
303+
case RoomListAction.PrevRoom:
303304
ev.stopPropagation();
304305
ev.preventDefault();
305-
this.onMoveFocus(ev.key === Key.ARROW_UP);
306+
this.onMoveFocus(action === RoomListAction.PrevRoom);
306307
break;
307308
}
308309
};
309310

310-
private onEnter = () => {
311+
private selectRoom = () => {
311312
const firstRoom = this.listContainerRef.current.querySelector<HTMLDivElement>(".mx_RoomTile");
312313
if (firstRoom) {
313314
firstRoom.click();
@@ -388,8 +389,8 @@ export default class LeftPanel extends React.Component<IProps, IState> {
388389
>
389390
<RoomSearch
390391
isMinimized={this.props.isMinimized}
391-
onVerticalArrow={this.onKeyDown}
392-
onEnter={this.onEnter}
392+
onKeyDown={this.onKeyDown}
393+
onSelectRoom={this.selectRoom}
393394
/>
394395
<AccessibleTooltipButton
395396
className={classNames("mx_LeftPanel_exploreButton", {

src/components/structures/LoggedInView.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,7 @@ class LoggedInView extends React.Component<IProps, IState> {
444444
case RoomAction.RoomScrollDown:
445445
case RoomAction.JumpToFirstMessage:
446446
case RoomAction.JumpToLatestMessage:
447+
// pass the event down to the scroll panel
447448
this._onScrollKeyPressed(ev);
448449
handled = true;
449450
break;

src/components/structures/RoomSearch.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,11 @@ import SpaceStore, {UPDATE_SELECTED_SPACE} from "../../stores/SpaceStore";
3030

3131
interface IProps {
3232
isMinimized: boolean;
33-
onVerticalArrow(ev: React.KeyboardEvent): void;
34-
onEnter(ev: React.KeyboardEvent): boolean;
33+
onKeyDown(ev: React.KeyboardEvent): void;
34+
/**
35+
* @returns true if a room has been selected and the search field should be cleared
36+
*/
37+
onSelectRoom(): boolean;
3538
}
3639

3740
interface IState {
@@ -120,10 +123,11 @@ export default class RoomSearch extends React.PureComponent<IProps, IState> {
120123
break;
121124
case RoomListAction.NextRoom:
122125
case RoomListAction.PrevRoom:
123-
this.props.onVerticalArrow(ev);
126+
// we don't handle these actions here put pass the event on to the interested party (LeftPanel)
127+
this.props.onKeyDown(ev);
124128
break;
125129
case RoomListAction.SelectRoom: {
126-
const shouldClear = this.props.onEnter(ev);
130+
const shouldClear = this.props.onSelectRoom();
127131
if (shouldClear) {
128132
// wrap in set immediate to delay it so that we don't clear the filter & then change room
129133
setImmediate(() => {

src/components/structures/ScrollPanel.js

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ limitations under the License.
1616

1717
import React, {createRef} from "react";
1818
import PropTypes from 'prop-types';
19-
import { Key } from '../../Keyboard';
2019
import Timer from '../../utils/Timer';
2120
import AutoHideScrollbar from "./AutoHideScrollbar";
2221
import {replaceableComponent} from "../../utils/replaceableComponent";
22+
import {getKeyBindingsManager, RoomAction} from "../../KeyBindingsManager";
2323

2424
const DEBUG_SCROLL = false;
2525

@@ -535,29 +535,19 @@ export default class ScrollPanel extends React.Component {
535535
* @param {object} ev the keyboard event
536536
*/
537537
handleScrollKey = ev => {
538-
switch (ev.key) {
539-
case Key.PAGE_UP:
540-
if (!ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) {
541-
this.scrollRelative(-1);
542-
}
538+
const roomAction = getKeyBindingsManager().getRoomAction(ev);
539+
switch (roomAction) {
540+
case RoomAction.ScrollUp:
541+
this.scrollRelative(-1);
543542
break;
544-
545-
case Key.PAGE_DOWN:
546-
if (!ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) {
547-
this.scrollRelative(1);
548-
}
543+
case RoomAction.RoomScrollDown:
544+
this.scrollRelative(1);
549545
break;
550-
551-
case Key.HOME:
552-
if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) {
553-
this.scrollToTop();
554-
}
546+
case RoomAction.JumpToFirstMessage:
547+
this.scrollToTop();
555548
break;
556-
557-
case Key.END:
558-
if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) {
559-
this.scrollToBottom();
560-
}
549+
case RoomAction.JumpToLatestMessage:
550+
this.scrollToBottom();
561551
break;
562552
}
563553
};

src/components/views/rooms/BasicMessageComposer.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -485,16 +485,14 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
485485
if (model.autoComplete && model.autoComplete.hasCompletions()) {
486486
const autoComplete = model.autoComplete;
487487
switch (autocompleteAction) {
488+
case AutocompleteAction.CompleteOrPrevSelection:
488489
case AutocompleteAction.PrevSelection:
489-
autoComplete.onUpArrow(event);
490+
autoComplete.selectPreviousSelection();
490491
handled = true;
491492
break;
493+
case AutocompleteAction.CompleteOrNextSelection:
492494
case AutocompleteAction.NextSelection:
493-
autoComplete.onDownArrow(event);
494-
handled = true;
495-
break;
496-
case AutocompleteAction.ApplySelection:
497-
autoComplete.onTab(event);
495+
autoComplete.selectNextSelection();
498496
handled = true;
499497
break;
500498
case AutocompleteAction.Cancel:
@@ -504,8 +502,10 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
504502
default:
505503
return; // don't preventDefault on anything else
506504
}
507-
} else if (autocompleteAction === AutocompleteAction.ApplySelection) {
508-
this.tabCompleteName(event);
505+
} else if (autocompleteAction === AutocompleteAction.CompleteOrPrevSelection
506+
|| autocompleteAction === AutocompleteAction.CompleteOrNextSelection) {
507+
// there is no current autocomplete window, try to open it
508+
this.tabCompleteName();
509509
handled = true;
510510
} else if (event.key === Key.BACKSPACE || event.key === Key.DELETE) {
511511
this.formatBarRef.current.hide();
@@ -517,7 +517,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
517517
}
518518
};
519519

520-
private async tabCompleteName(event: React.KeyboardEvent) {
520+
private async tabCompleteName() {
521521
try {
522522
await new Promise<void>(resolve => this.setState({showVisualBell: false}, resolve));
523523
const {model} = this.props;
@@ -540,7 +540,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
540540

541541
// Don't try to do things with the autocomplete if there is none shown
542542
if (model.autoComplete) {
543-
await model.autoComplete.onTab(event);
543+
await model.autoComplete.startSelection();
544544
if (!model.autoComplete.hasSelection()) {
545545
this.setState({showVisualBell: true});
546546
model.autoComplete.close();

src/editor/autocomplete.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,24 +68,24 @@ export default class AutocompleteWrapperModel {
6868
this.updateCallback({close: true});
6969
}
7070

71-
public async onTab(e: KeyboardEvent) {
71+
/**
72+
* If there is no current autocompletion, start one and move to the first selection.
73+
*/
74+
public async startSelection() {
7275
const acComponent = this.getAutocompleterComponent();
73-
7476
if (acComponent.countCompletions() === 0) {
7577
// Force completions to show for the text currently entered
7678
await acComponent.forceComplete();
7779
// Select the first item by moving "down"
7880
await acComponent.moveSelection(+1);
79-
} else {
80-
await acComponent.moveSelection(e.shiftKey ? -1 : +1);
8181
}
8282
}
8383

84-
public onUpArrow(e: KeyboardEvent) {
84+
public selectPreviousSelection() {
8585
this.getAutocompleterComponent().moveSelection(-1);
8686
}
8787

88-
public onDownArrow(e: KeyboardEvent) {
88+
public selectNextSelection() {
8989
this.getAutocompleterComponent().moveSelection(+1);
9090
}
9191

0 commit comments

Comments
 (0)