Use the KeyBindingsManager in EditMessageComposer

pull/21833/head
Clemens Zeidler 2021-02-16 19:05:39 +13:00
parent 4a138f3b84
commit 12387b4978
2 changed files with 65 additions and 39 deletions

View File

@ -2,21 +2,33 @@ import { isMac, Key } from './Keyboard';
import SettingsStore from './settings/SettingsStore';
export enum KeyBindingContext {
SendMessageComposer = 'SendMessageComposer',
/** Key bindings for the chat message composer component */
MessageComposer = 'MessageComposer',
}
export enum KeyAction {
None = 'None',
// SendMessageComposer actions:
/** Send a message */
Send = 'Send',
/** Go backwards through the send history and use the message in composer view */
SelectPrevSendHistory = 'SelectPrevSendHistory',
/** Go forwards through the send history */
SelectNextSendHistory = 'SelectNextSendHistory',
EditLastMessage = 'EditLastMessage',
/** Start editing the user's last sent message */
EditPrevMessage = 'EditPrevMessage',
/** Start editing the user's next sent message */
EditNextMessage = 'EditNextMessage',
/** Cancel editing a message */
CancelEditing = 'CancelEditing',
}
/**
* Represent a key combination.
*
*
* The combo is evaluated strictly, i.e. the KeyboardEvent must match exactly what is specified in the KeyCombo.
*/
export type KeyCombo = {
@ -55,10 +67,22 @@ const messageComposerBindings = (): KeyBinding[] => {
},
},
{
action: KeyAction.EditLastMessage,
action: KeyAction.EditPrevMessage,
keyCombo: {
key: Key.ARROW_UP,
}
},
},
{
action: KeyAction.EditNextMessage,
keyCombo: {
key: Key.ARROW_DOWN,
},
},
{
action: KeyAction.CancelEditing,
keyCombo: {
key: Key.ESCAPE,
},
},
];
if (SettingsStore.getValue('MessageComposerInput.ctrlEnterToSend')) {
@ -83,7 +107,7 @@ const messageComposerBindings = (): KeyBinding[] => {
/**
* Helper method to check if a KeyboardEvent matches a KeyCombo
*
*
* Note, this method is only exported for testing.
*/
export function isKeyComboMatch(ev: KeyboardEvent, combo: KeyCombo, onMac: boolean): boolean {
@ -130,12 +154,12 @@ export type KeyBindingsGetter = () => KeyBinding[];
export class KeyBindingsManager {
/**
* Map of KeyBindingContext to a KeyBinding getter arrow function.
*
*
* Returning a getter function allowed to have dynamic bindings, e.g. when settings change the bindings can be
* recalculated.
*/
contextBindings: Record<KeyBindingContext, KeyBindingsGetter> = {
[KeyBindingContext.SendMessageComposer]: messageComposerBindings,
[KeyBindingContext.MessageComposer]: messageComposerBindings,
};
/**

View File

@ -29,11 +29,10 @@ import EditorStateTransfer from '../../../utils/EditorStateTransfer';
import classNames from 'classnames';
import {EventStatus} from 'matrix-js-sdk';
import BasicMessageComposer from "./BasicMessageComposer";
import {Key, isOnlyCtrlOrCmdKeyEvent} from "../../../Keyboard";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import {Action} from "../../../dispatcher/actions";
import SettingsStore from "../../../settings/SettingsStore";
import CountlyAnalytics from "../../../CountlyAnalytics";
import {getKeyBindingsManager, KeyAction, KeyBindingContext} from '../../../KeyBindingsManager';
function _isReply(mxEvent) {
const relatesTo = mxEvent.getContent()["m.relates_to"];
@ -134,38 +133,41 @@ export default class EditMessageComposer extends React.Component {
if (this._editorRef.isComposing(event)) {
return;
}
if (event.metaKey || event.altKey || event.shiftKey) {
return;
}
const ctrlEnterToSend = !!SettingsStore.getValue('MessageComposerInput.ctrlEnterToSend');
const send = ctrlEnterToSend ? event.key === Key.ENTER && isOnlyCtrlOrCmdKeyEvent(event)
: event.key === Key.ENTER;
if (send) {
this._sendEdit();
event.preventDefault();
} else if (event.key === Key.ESCAPE) {
this._cancelEdit();
} else if (event.key === Key.ARROW_UP) {
if (this._editorRef.isModified() || !this._editorRef.isCaretAtStart()) {
return;
}
const previousEvent = findEditableEvent(this._getRoom(), false, this.props.editState.getEvent().getId());
if (previousEvent) {
dis.dispatch({action: 'edit_event', event: previousEvent});
const action = getKeyBindingsManager().getAction(KeyBindingContext.MessageComposer, event);
switch (action) {
case KeyAction.Send:
this._sendEdit();
event.preventDefault();
break;
case KeyAction.CancelEditing:
this._cancelEdit();
break;
case KeyAction.EditPrevMessage: {
if (this._editorRef.isModified() || !this._editorRef.isCaretAtStart()) {
return;
}
const previousEvent = findEditableEvent(this._getRoom(), false,
this.props.editState.getEvent().getId());
if (previousEvent) {
dis.dispatch({action: 'edit_event', event: previousEvent});
event.preventDefault();
}
break;
}
} else if (event.key === Key.ARROW_DOWN) {
if (this._editorRef.isModified() || !this._editorRef.isCaretAtEnd()) {
return;
case KeyAction.EditNextMessage: {
if (this._editorRef.isModified() || !this._editorRef.isCaretAtEnd()) {
return;
}
const nextEvent = findEditableEvent(this._getRoom(), true, this.props.editState.getEvent().getId());
if (nextEvent) {
dis.dispatch({action: 'edit_event', event: nextEvent});
} else {
dis.dispatch({action: 'edit_event', event: null});
dis.fire(Action.FocusComposer);
}
event.preventDefault();
break;
}
const nextEvent = findEditableEvent(this._getRoom(), true, this.props.editState.getEvent().getId());
if (nextEvent) {
dis.dispatch({action: 'edit_event', event: nextEvent});
} else {
dis.dispatch({action: 'edit_event', event: null});
dis.fire(Action.FocusComposer);
}
event.preventDefault();
}
}