Merge pull request #3105 from matrix-org/bwindels/edit-emotes
Support editing emote messages
This commit is contained in:
commit
638b5c6d31
4 changed files with 34 additions and 11 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue