move between editable events with arrow keys
This commit is contained in:
parent
8926fcb3a6
commit
3591eedcfa
2 changed files with 47 additions and 8 deletions
|
@ -23,6 +23,7 @@ import EditorModel from '../../../editor/model';
|
||||||
import {setCaretPosition} from '../../../editor/caret';
|
import {setCaretPosition} from '../../../editor/caret';
|
||||||
import {getCaretOffsetAndText} from '../../../editor/dom';
|
import {getCaretOffsetAndText} from '../../../editor/dom';
|
||||||
import {htmlSerializeIfNeeded, textSerialize} from '../../../editor/serialize';
|
import {htmlSerializeIfNeeded, textSerialize} from '../../../editor/serialize';
|
||||||
|
import {findPreviousEditableEvent, findNextEditableEvent} from '../../../utils/EventUtils';
|
||||||
import {parseEvent} from '../../../editor/deserialize';
|
import {parseEvent} from '../../../editor/deserialize';
|
||||||
import Autocomplete from '../rooms/Autocomplete';
|
import Autocomplete from '../rooms/Autocomplete';
|
||||||
import {PartCreator} from '../../../editor/parts';
|
import {PartCreator} from '../../../editor/parts';
|
||||||
|
@ -42,7 +43,7 @@ export default class MessageEditor extends React.Component {
|
||||||
|
|
||||||
constructor(props, context) {
|
constructor(props, context) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
const room = this.context.matrixClient.getRoom(this.props.event.getRoomId());
|
const room = this._getRoom();
|
||||||
const partCreator = new PartCreator(
|
const partCreator = new PartCreator(
|
||||||
() => this._autocompleteRef,
|
() => this._autocompleteRef,
|
||||||
query => this.setState({query}),
|
query => this.setState({query}),
|
||||||
|
@ -61,6 +62,10 @@ export default class MessageEditor extends React.Component {
|
||||||
this._autocompleteRef = null;
|
this._autocompleteRef = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_getRoom() {
|
||||||
|
return this.context.matrixClient.getRoom(this.props.event.getRoomId());
|
||||||
|
}
|
||||||
|
|
||||||
_updateEditorState = (caret) => {
|
_updateEditorState = (caret) => {
|
||||||
renderModel(this._editorRef, this.model);
|
renderModel(this._editorRef, this.model);
|
||||||
if (caret) {
|
if (caret) {
|
||||||
|
@ -79,6 +84,16 @@ export default class MessageEditor extends React.Component {
|
||||||
this.model.update(text, event.inputType, caret);
|
this.model.update(text, event.inputType, caret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_isCaretAtStart() {
|
||||||
|
const {caret} = getCaretOffsetAndText(this._editorRef, document.getSelection());
|
||||||
|
return caret.offset === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_isCaretAtEnd() {
|
||||||
|
const {caret, text} = getCaretOffsetAndText(this._editorRef, document.getSelection());
|
||||||
|
return caret.offset === text.length;
|
||||||
|
}
|
||||||
|
|
||||||
_onKeyDown = (event) => {
|
_onKeyDown = (event) => {
|
||||||
// insert newline on Shift+Enter
|
// insert newline on Shift+Enter
|
||||||
if (event.shiftKey && event.key === "Enter") {
|
if (event.shiftKey && event.key === "Enter") {
|
||||||
|
@ -112,6 +127,27 @@ export default class MessageEditor extends React.Component {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
} else if (event.key === "Escape") {
|
} else if (event.key === "Escape") {
|
||||||
this._cancelEdit();
|
this._cancelEdit();
|
||||||
|
} else if (event.key === "ArrowUp") {
|
||||||
|
if (!this._isCaretAtStart()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const previousEvent = findPreviousEditableEvent(this._getRoom(), this.props.event.getId());
|
||||||
|
if (previousEvent) {
|
||||||
|
dis.dispatch({action: 'edit_event', event: previousEvent});
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
} else if (event.key === "ArrowDown") {
|
||||||
|
if (!this._isCaretAtEnd()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const nextEvent = findNextEditableEvent(this._getRoom(), this.props.event.getId());
|
||||||
|
if (nextEvent) {
|
||||||
|
dis.dispatch({action: 'edit_event', event: nextEvent});
|
||||||
|
} else {
|
||||||
|
dis.dispatch({action: 'edit_event', event: null});
|
||||||
|
dis.dispatch({action: 'focus_composer'});
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ import RoomViewStore from '../../../stores/RoomViewStore';
|
||||||
import ReplyThread from "../elements/ReplyThread";
|
import ReplyThread from "../elements/ReplyThread";
|
||||||
import {ContentHelpers} from 'matrix-js-sdk';
|
import {ContentHelpers} from 'matrix-js-sdk';
|
||||||
import AccessibleButton from '../elements/AccessibleButton';
|
import AccessibleButton from '../elements/AccessibleButton';
|
||||||
|
import { findPreviousEditableEvent } from '../../../utils/EventUtils';
|
||||||
|
|
||||||
const REGEX_EMOTICON_WHITESPACE = new RegExp('(?:^|\\s)(' + EMOTICON_REGEX.source + ')\\s$');
|
const REGEX_EMOTICON_WHITESPACE = new RegExp('(?:^|\\s)(' + EMOTICON_REGEX.source + ')\\s$');
|
||||||
|
|
||||||
|
@ -1188,14 +1189,16 @@ export default class MessageComposerInput extends React.Component {
|
||||||
// and we must be at the edge of the document (up=start, down=end)
|
// and we must be at the edge of the document (up=start, down=end)
|
||||||
if (up) {
|
if (up) {
|
||||||
if (!selection.anchor.isAtStartOfNode(document)) return;
|
if (!selection.anchor.isAtStartOfNode(document)) return;
|
||||||
} else {
|
|
||||||
if (!selection.anchor.isAtEndOfNode(document)) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const selected = this.selectHistory(up);
|
const editEvent = findPreviousEditableEvent(this.props.room);
|
||||||
if (selected) {
|
if (editEvent) {
|
||||||
// We're selecting history, so prevent the key event from doing anything else
|
// We're selecting history, so prevent the key event from doing anything else
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
dis.dispatch({
|
||||||
|
action: 'edit_event',
|
||||||
|
event: editEvent,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.moveAutocompleteSelection(up);
|
this.moveAutocompleteSelection(up);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue