Parse formatted message bodies in addition to plain ones.

This commit is contained in:
Danila Fedorin 2021-07-06 16:14:04 -07:00
parent cfa686867c
commit e56b15237e
4 changed files with 43 additions and 15 deletions

View file

@ -21,26 +21,30 @@ export class BaseTextTile extends BaseMessageTile {
constructor(options) { constructor(options) {
super(options); super(options);
this._messageBody = null; this._messageBody = null;
this._messageFormat = null
} }
get shape() { get shape() {
return "message"; return "message";
} }
_parseBody(bodyString) { _parseBody(body) {
return stringAsBody(bodyString); return stringAsBody(body.string);
} }
get body() { get body() {
const body = this._getBodyAsString(); const body = this._getBody();
// body is a string, so we can check for difference by just // body.string is a string, so we can check for difference by just
// doing an equality check // 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, // body with markup is an array of parts,
// so we should not recreate it for the same body string, // so we should not recreate it for the same body string,
// or else the equality check in the binding will always fail. // or else the equality check in the binding will always fail.
// So cache it here. // So cache it here.
this._messageBody = this._parseBody(body); this._messageBody = this._parseBody(body);
this._messageFormat = body.format;
} }
return this._messageBody; return this._messageBody;
} }

View file

@ -33,13 +33,15 @@ export class EncryptedEventTile extends BaseTextTile {
return "message-status" return "message-status"
} }
_getBodyAsString() { _getBody() {
const decryptionError = this._entry.decryptionError; const decryptionError = this._entry.decryptionError;
const code = decryptionError?.code; const code = decryptionError?.code;
let string;
if (code === "MEGOLM_NO_SESSION") { 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 { } 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" };
} }
} }

View file

@ -16,18 +16,39 @@ limitations under the License.
import {BaseTextTile} from "./BaseTextTile.js"; import {BaseTextTile} from "./BaseTextTile.js";
import {parsePlainBody} from "../MessageBody.js"; import {parsePlainBody} from "../MessageBody.js";
import {parseHTMLBody} from "../../../../../platform/web/dom/deserialize.js";
export class TextTile extends BaseTextTile { export class TextTile extends BaseTextTile {
_getBodyAsString() { _getContentString(key, format, fallback = null) {
const content = this._getContent(); const content = this._getContent();
let body = content?.body || ""; let val = content?.[key] || fallback;
if (content.msgtype === "m.emote") { if (!val && val !== "") { // empty string is falsy, but OK here.
body = `* ${this.displayName} ${body}`; return null;
} }
return body; if (content.msgtype === "m.emote") {
val = `* ${this.displayName} ${body}`;
}
return { string: val, format };
} }
_parseBody(bodyString) { _getPlainBody() {
return parsePlainBody(bodyString); 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);
}
} }
} }

View file

@ -42,6 +42,7 @@ const formatFunction = {
code: codePart => tag.code({}, text(codePart.text)), code: codePart => tag.code({}, text(codePart.text)),
text: textPart => text(textPart.text), text: textPart => text(textPart.text),
link: linkPart => tag.a({ href: linkPart.url, target: "_blank", rel: "noopener" }, renderParts(linkPart.inlines)), 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() newline: () => tag.br()
}; };