From e56b15237ef2f130c102dc2bc1093500f10568b7 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Tue, 6 Jul 2021 16:14:04 -0700 Subject: [PATCH] Parse formatted message bodies in addition to plain ones. --- .../room/timeline/tiles/BaseTextTile.js | 14 +++++--- .../room/timeline/tiles/EncryptedEventTile.js | 8 +++-- .../session/room/timeline/tiles/TextTile.js | 35 +++++++++++++++---- .../session/room/timeline/TextMessageView.js | 1 + 4 files changed, 43 insertions(+), 15 deletions(-) diff --git a/src/domain/session/room/timeline/tiles/BaseTextTile.js b/src/domain/session/room/timeline/tiles/BaseTextTile.js index 401fd719..f566f6e1 100644 --- a/src/domain/session/room/timeline/tiles/BaseTextTile.js +++ b/src/domain/session/room/timeline/tiles/BaseTextTile.js @@ -21,26 +21,30 @@ export class BaseTextTile extends BaseMessageTile { constructor(options) { super(options); this._messageBody = null; + this._messageFormat = null } get shape() { return "message"; } - _parseBody(bodyString) { - return stringAsBody(bodyString); + _parseBody(body) { + return stringAsBody(body.string); } get body() { - const body = this._getBodyAsString(); - // body is a string, so we can check for difference by just + const body = this._getBody(); + // body.string is a string, so we can check for difference by just // doing an equality check - if (!this._messageBody || this._messageBody.sourceString !== body) { + // Even if the body hasn't changed, but the format has, we need + // to re-fill our cache. + if (!this._messageBody || this._messageBody.sourceString !== body.string || this._messageFormat !== body.format) { // body with markup is an array of parts, // so we should not recreate it for the same body string, // or else the equality check in the binding will always fail. // So cache it here. this._messageBody = this._parseBody(body); + this._messageFormat = body.format; } return this._messageBody; } diff --git a/src/domain/session/room/timeline/tiles/EncryptedEventTile.js b/src/domain/session/room/timeline/tiles/EncryptedEventTile.js index 155ce4a9..51788530 100644 --- a/src/domain/session/room/timeline/tiles/EncryptedEventTile.js +++ b/src/domain/session/room/timeline/tiles/EncryptedEventTile.js @@ -33,13 +33,15 @@ export class EncryptedEventTile extends BaseTextTile { return "message-status" } - _getBodyAsString() { + _getBody() { const decryptionError = this._entry.decryptionError; const code = decryptionError?.code; + let string; if (code === "MEGOLM_NO_SESSION") { - return this.i18n`The sender hasn't sent us the key for this message yet.`; + string = this.i18n`The sender hasn't sent us the key for this message yet.`; } else { - return decryptionError?.message || this.i18n`Could not decrypt message because of unknown reason.`; + string = decryptionError?.message || this.i18n`Could not decrypt message because of unknown reason.`; } + return { string, format: "plain" }; } } diff --git a/src/domain/session/room/timeline/tiles/TextTile.js b/src/domain/session/room/timeline/tiles/TextTile.js index 07e7ce8f..f7e1d8c2 100644 --- a/src/domain/session/room/timeline/tiles/TextTile.js +++ b/src/domain/session/room/timeline/tiles/TextTile.js @@ -16,18 +16,39 @@ limitations under the License. import {BaseTextTile} from "./BaseTextTile.js"; import {parsePlainBody} from "../MessageBody.js"; +import {parseHTMLBody} from "../../../../../platform/web/dom/deserialize.js"; export class TextTile extends BaseTextTile { - _getBodyAsString() { + _getContentString(key, format, fallback = null) { const content = this._getContent(); - let body = content?.body || ""; - if (content.msgtype === "m.emote") { - body = `* ${this.displayName} ${body}`; + let val = content?.[key] || fallback; + if (!val && val !== "") { // empty string is falsy, but OK here. + return null; } - return body; + if (content.msgtype === "m.emote") { + val = `* ${this.displayName} ${body}`; + } + return { string: val, format }; } - _parseBody(bodyString) { - return parsePlainBody(bodyString); + _getPlainBody() { + return this._getContentString("body", "plain", ""); + } + + _getFormattedBody() { + return this._getContentString("formatted_body", "html"); + } + + _getBody() { + return this._getFormattedBody() || this._getPlainBody(); + } + + _parseBody(body) { + const string = body.string; + if (body.format === "html") { + return parseHTMLBody(this.platform, string); + } else { + return parsePlainBody(string); + } } } diff --git a/src/platform/web/ui/session/room/timeline/TextMessageView.js b/src/platform/web/ui/session/room/timeline/TextMessageView.js index 5809cca9..1f59af9c 100644 --- a/src/platform/web/ui/session/room/timeline/TextMessageView.js +++ b/src/platform/web/ui/session/room/timeline/TextMessageView.js @@ -42,6 +42,7 @@ const formatFunction = { code: codePart => tag.code({}, text(codePart.text)), text: textPart => text(textPart.text), link: linkPart => tag.a({ href: linkPart.url, target: "_blank", rel: "noopener" }, renderParts(linkPart.inlines)), + format: formatPart => tag[formatPart.format]({}, renderParts(formatPart.children)), newline: () => tag.br() };