Apply the same to quoting & inserting of emoji then consolidate

This commit is contained in:
Michael Telatynski 2021-04-13 15:09:37 +01:00
parent ace3a62bac
commit 5f59e39958
12 changed files with 105 additions and 50 deletions

View file

@ -467,16 +467,17 @@ class TimelinePanel extends React.Component {
break;
}
case "insert_mention": {
case "composer_insert": {
// re-dispatch to the correct composer
if (this.state.editState) {
dis.dispatch({
...payload,
action: "insert_mention_edit_composer",
action: "edit_composer_insert",
});
} else {
dis.dispatch({
...payload,
action: "insert_mention_send_composer",
action: "send_composer_insert",
});
}
break;

View file

@ -233,7 +233,7 @@ export default class MessageContextMenu extends React.Component {
onQuoteClick = () => {
dis.dispatch({
action: 'quote',
action: "composer_insert",
event: this.props.mxEvent,
});
this.closeMenu();

View file

@ -390,8 +390,8 @@ export default class TextualBody extends React.Component {
onEmoteSenderClick = event => {
const mxEvent = this.props.mxEvent;
dis.dispatch({
action: 'insert_mention',
user_id: mxEvent.getSender(),
action: "composer_insert",
userId: mxEvent.getSender(),
});
};

View file

@ -360,8 +360,8 @@ const UserOptionsSection: React.FC<{
const onInsertPillButton = function() {
dis.dispatch({
action: 'insert_mention',
user_id: member.userId,
action: "composer_insert",
userId: member.userId,
});
};

View file

@ -18,6 +18,7 @@ limitations under the License.
import classNames from 'classnames';
import React, {createRef, ClipboardEvent} from 'react';
import {Room} from 'matrix-js-sdk/src/models/room';
import {MatrixEvent} from 'matrix-js-sdk/src/models/event';
import EMOTICON_REGEX from 'emojibase-regex/emoticon';
import EditorModel from '../../../editor/model';
@ -32,7 +33,7 @@ import {
import {getCaretOffsetAndText, getRangeForSelection} from '../../../editor/dom';
import Autocomplete, {generateCompletionDomId} from '../rooms/Autocomplete';
import {getAutoCompleteCreator} from '../../../editor/parts';
import {parsePlainTextMessage} from '../../../editor/deserialize';
import {parseEvent, parsePlainTextMessage} from '../../../editor/deserialize';
import {renderModel} from '../../../editor/render';
import TypingStore from "../../../stores/TypingStore";
import SettingsStore from "../../../settings/SettingsStore";
@ -732,4 +733,30 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
// refocus on composer, as we just clicked "Mention"
this.focus();
}
public insertQuotedMessage(event: MatrixEvent) {
const {model} = this.props;
const {partCreator} = model;
const quoteParts = parseEvent(event, partCreator, {isQuotedMessage: true});
// add two newlines
quoteParts.push(partCreator.newline());
quoteParts.push(partCreator.newline());
model.transform(() => {
const addedLen = model.insert(quoteParts, model.positionForOffset(0));
return model.positionForOffset(addedLen, true);
});
// refocus on composer, as we just clicked "Quote"
this.focus();
}
public insertPlaintext(text: string) {
const {model} = this.props;
const {partCreator} = model;
const caret = this.getCaret();
const position = model.positionForOffset(caret.offset, caret.atNodeEnd);
model.transform(() => {
const addedLen = model.insert([partCreator.plain(text)], position);
return model.positionForOffset(caret.offset + addedLen, true);
});
}
}

View file

@ -281,8 +281,14 @@ export default class EditMessageComposer extends React.Component {
};
onAction = payload => {
if (payload.action === "insert_mention_edit_composer" && this._editorRef) {
this._editorRef.insertMention(payload.user_id);
if (payload.action === "edit_composer_insert" && this._editorRef) {
if (payload.user_id) {
this._editorRef.insertMention(payload.userId);
} else if (payload.event) {
this._editorRef.insertQuotedMessage(payload.event);
} else if (payload.text) {
this._editorRef.insertPlaintext(payload.text);
}
}
};

View file

@ -644,8 +644,8 @@ export default class EventTile extends React.Component {
onSenderProfileClick = event => {
const mxEvent = this.props.mxEvent;
dis.dispatch({
action: 'insert_mention',
user_id: mxEvent.getSender(),
action: "composer_insert",
userId: mxEvent.getSender(),
});
};

View file

@ -312,8 +312,8 @@ export default class MessageComposer extends React.Component {
addEmoji(emoji) {
dis.dispatch({
action: "insert_emoji",
emoji,
action: "composer_insert",
text: emoji,
});
}

View file

@ -482,44 +482,18 @@ export default class SendMessageComposer extends React.Component {
case Action.FocusComposer:
this._editorRef && this._editorRef.focus();
break;
case 'insert_mention_send_composer':
this._editorRef && this._editorRef.insertMention(payload.user_id);
break;
case 'quote':
this._insertQuotedMessage(payload.event);
break;
case 'insert_emoji':
this._insertEmoji(payload.emoji);
case "send_composer_insert":
if (payload.userId) {
this._editorRef && this._editorRef.insertMention(payload.userId);
} else if (payload.event) {
this._editorRef && this._editorRef.insertQuotedMessage(payload.event);
} else if (payload.text) {
this._editorRef && this._editorRef.insertPlaintext(payload.emoji);
}
break;
}
};
_insertQuotedMessage(event) {
const {model} = this;
const {partCreator} = model;
const quoteParts = parseEvent(event, partCreator, {isQuotedMessage: true});
// add two newlines
quoteParts.push(partCreator.newline());
quoteParts.push(partCreator.newline());
model.transform(() => {
const addedLen = model.insert(quoteParts, model.positionForOffset(0));
return model.positionForOffset(addedLen, true);
});
// refocus on composer, as we just clicked "Quote"
this._editorRef && this._editorRef.focus();
}
_insertEmoji = (emoji) => {
const {model} = this;
const {partCreator} = model;
const caret = this._editorRef.getCaret();
const position = model.positionForOffset(caret.offset, caret.atNodeEnd);
model.transform(() => {
const addedLen = model.insert([partCreator.plain(emoji)], position);
return model.positionForOffset(caret.offset + addedLen, true);
});
};
_onPaste = (event) => {
const {clipboardData} = event;
// Prioritize text on the clipboard over files as Office on macOS puts a bitmap