Merge pull request #3105 from matrix-org/bwindels/edit-emotes

Support editing emote messages
This commit is contained in:
Bruno Windels 2019-06-14 15:47:29 +00:00 committed by GitHub
commit 638b5c6d31
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 11 deletions

View file

@ -150,16 +150,28 @@ export default class MessageEditor extends React.Component {
dis.dispatch({action: 'focus_composer'}); dis.dispatch({action: 'focus_composer'});
} }
_isEmote() {
const firstPart = this.model.parts[0];
return firstPart && firstPart.type === "plain" && firstPart.text.startsWith("/me ");
}
_sendEdit = () => { _sendEdit = () => {
const isEmote = this._isEmote();
let model = this.model;
if (isEmote) {
// trim "/me "
model = model.clone();
model.removeText({index: 0, offset: 0}, 4);
}
const newContent = { const newContent = {
"msgtype": "m.text", "msgtype": isEmote ? "m.emote" : "m.text",
"body": textSerialize(this.model), "body": textSerialize(model),
}; };
const contentBody = { const contentBody = {
msgtype: newContent.msgtype, msgtype: newContent.msgtype,
body: ` * ${newContent.body}`, body: ` * ${newContent.body}`,
}; };
const formattedBody = htmlSerializeIfNeeded(this.model); const formattedBody = htmlSerializeIfNeeded(model);
if (formattedBody) { if (formattedBody) {
newContent.format = "org.matrix.custom.html"; newContent.format = "org.matrix.custom.html";
newContent.formatted_body = formattedBody; newContent.formatted_body = formattedBody;

View file

@ -207,12 +207,13 @@ function parseHtmlMessage(html, room, client) {
export function parseEvent(event, room, client) { export function parseEvent(event, room, client) {
const content = event.getContent(); const content = event.getContent();
let parts;
if (content.format === "org.matrix.custom.html") { if (content.format === "org.matrix.custom.html") {
return parseHtmlMessage(content.formatted_body || "", room, client); parts = parseHtmlMessage(content.formatted_body || "", room, client);
} else { } else {
const body = content.body || ""; const body = content.body || "";
const lines = body.split("\n"); const lines = body.split("\n");
const parts = lines.reduce((parts, line, i) => { parts = lines.reduce((parts, line, i) => {
const isLast = i === lines.length - 1; const isLast = i === lines.length - 1;
const text = new PlainPart(line); const text = new PlainPart(line);
const newLine = !isLast && new NewlinePart("\n"); const newLine = !isLast && new NewlinePart("\n");
@ -222,6 +223,9 @@ export function parseEvent(event, room, client) {
return parts.concat(text); return parts.concat(text);
} }
}, []); }, []);
return parts;
} }
if (content.msgtype === "m.emote") {
parts.unshift(new PlainPart("/me "));
}
return parts;
} }

View file

@ -27,6 +27,10 @@ export default class EditorModel {
this._updateCallback = updateCallback; this._updateCallback = updateCallback;
} }
clone() {
return new EditorModel(this._parts, this._partCreator, this._updateCallback);
}
_insertPart(index, part) { _insertPart(index, part) {
this._parts.splice(index, 0, part); this._parts.splice(index, 0, part);
if (this._activePartIdx >= index) { if (this._activePartIdx >= index) {
@ -91,7 +95,7 @@ export default class EditorModel {
const position = this.positionForOffset(diff.at, caret.atNodeEnd); const position = this.positionForOffset(diff.at, caret.atNodeEnd);
let removedOffsetDecrease = 0; let removedOffsetDecrease = 0;
if (diff.removed) { if (diff.removed) {
removedOffsetDecrease = this._removeText(position, diff.removed.length); removedOffsetDecrease = this.removeText(position, diff.removed.length);
} }
let addedLen = 0; let addedLen = 0;
if (diff.added) { if (diff.added) {
@ -177,7 +181,7 @@ export default class EditorModel {
* @return {Number} how many characters before pos were also removed, * @return {Number} how many characters before pos were also removed,
* usually because of non-editable parts that can only be removed in their entirety. * usually because of non-editable parts that can only be removed in their entirety.
*/ */
_removeText(pos, len) { removeText(pos, len) {
let {index, offset} = pos; let {index, offset} = pos;
let removedOffsetDecrease = 0; let removedOffsetDecrease = 0;
while (len > 0) { while (len > 0) {

View file

@ -46,9 +46,12 @@ export function isContentActionable(mxEvent) {
} }
export function canEditContent(mxEvent) { export function canEditContent(mxEvent) {
return mxEvent.status !== EventStatus.CANCELLED && if (mxEvent.status === EventStatus.CANCELLED || mxEvent.getType() !== "m.room.message") {
mxEvent.getType() === 'm.room.message' && return false;
mxEvent.getOriginalContent().msgtype === "m.text" && }
const content = mxEvent.getOriginalContent();
const {msgtype} = content;
return (msgtype === "m.text" || msgtype === "m.emote") &&
mxEvent.getSender() === MatrixClientPeg.get().getUserId(); mxEvent.getSender() === MatrixClientPeg.get().getUserId();
} }