Merge pull request #3098 from matrix-org/t3chguy/restore_composer_history

Restore Composer History under shift-up & down
This commit is contained in:
Bruno Windels 2019-06-18 08:59:11 +00:00 committed by GitHub
commit 32840fc274
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 167 additions and 28 deletions

View file

@ -60,6 +60,7 @@ import ReplyThread from "../elements/ReplyThread";
import {ContentHelpers} from 'matrix-js-sdk';
import AccessibleButton from '../elements/AccessibleButton';
import {findEditableEvent} from '../../../utils/EventUtils';
import ComposerHistoryManager from "../../../ComposerHistoryManager";
const REGEX_EMOTICON_WHITESPACE = new RegExp('(?:^|\\s)(' + EMOTICON_REGEX.source + ')\\s$');
@ -140,6 +141,7 @@ export default class MessageComposerInput extends React.Component {
client: MatrixClient;
autocomplete: Autocomplete;
historyManager: ComposerHistoryManager;
constructor(props, context) {
super(props, context);
@ -329,6 +331,7 @@ export default class MessageComposerInput extends React.Component {
componentWillMount() {
this.dispatcherRef = dis.register(this.onAction);
this.historyManager = new ComposerHistoryManager(this.props.room.roomId, 'mx_slate_composer_history_');
}
componentWillUnmount() {
@ -1062,6 +1065,7 @@ export default class MessageComposerInput extends React.Component {
if (cmd) {
if (!cmd.error) {
this.historyManager.save(editorState, this.state.isRichTextEnabled ? 'rich' : 'markdown');
this.setState({
editorState: this.createEditorState(),
}, ()=>{
@ -1139,6 +1143,8 @@ export default class MessageComposerInput extends React.Component {
let sendHtmlFn = ContentHelpers.makeHtmlMessage;
let sendTextFn = ContentHelpers.makeTextMessage;
this.historyManager.save(editorState, this.state.isRichTextEnabled ? 'rich' : 'markdown');
if (commandText && commandText.startsWith('/me')) {
if (replyingToEv) {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
@ -1198,31 +1204,88 @@ 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.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) {
if (e.altKey) {
// Try select composer history
const selected = this.selectHistory(up);
if (selected) {
// We're selecting history, so prevent the key event from doing anything else
e.preventDefault();
dis.dispatch({
action: 'edit_event',
event: editEvent,
});
}
} else if (!e.altKey && up) {
// Try edit the latest message
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 (!selection.anchor.isAtStartOfNode(document)) return;
if (!e.altKey) {
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,
});
}
}
}
};
selectHistory = async (up) => {
const delta = up ? -1 : 1;
// True if we are not currently selecting history, but composing a message
if (this.historyManager.currentIndex === this.historyManager.history.length) {
// We can't go any further - there isn't any more history, so nop.
if (!up) {
return;
}
this.setState({
currentlyComposedEditorState: this.state.editorState,
});
} else if (this.historyManager.currentIndex + delta === this.historyManager.history.length) {
// True when we return to the message being composed currently
this.setState({
editorState: this.state.currentlyComposedEditorState,
});
this.historyManager.currentIndex = this.historyManager.history.length;
return;
}
let editorState;
const historyItem = this.historyManager.getItem(delta);
if (!historyItem) return;
if (historyItem.format === 'rich' && !this.state.isRichTextEnabled) {
editorState = this.richToMdEditorState(historyItem.value);
} else if (historyItem.format === 'markdown' && this.state.isRichTextEnabled) {
editorState = this.mdToRichEditorState(historyItem.value);
} else {
editorState = historyItem.value;
}
// Move selection to the end of the selected history
const change = editorState.change().moveToEndOfNode(editorState.document);
// We don't call this.onChange(change) now, as fixups on stuff like pills
// should already have been done and persisted in the history.
editorState = change.value;
this.suppressAutoComplete = true;
this.setState({ editorState }, ()=>{
this._editor.focus();
});
return true;
};
onTab = async (e) => {
this.setState({
someCompletions: null,