Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Support rendering of extensible events v2 #9915

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
"lodash": "^4.17.20",
"maplibre-gl": "^2.0.0",
"matrix-encrypt-attachment": "^1.0.3",
"matrix-events-sdk": "0.0.1",
"matrix-events-sdk": "^2.0.0",
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop",
"matrix-widget-api": "^1.1.1",
"minimist": "^1.2.5",
Expand Down
3 changes: 3 additions & 0 deletions src/components/views/messages/IBodyProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,8 @@ export interface IBodyProps {
// helper function to access relations for this event
getRelationsForEvent?: GetRelationsForEvent;

// if true, the **unstable** extensible event functionality will be used to parse the event
forceUnstableExtensibleRendering?: boolean;

ref?: React.RefObject<any> | LegacyRef<any>;
}
23 changes: 22 additions & 1 deletion src/components/views/messages/MessageEvent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { M_BEACON_INFO } from "matrix-js-sdk/src/@types/beacon";
import { M_LOCATION } from "matrix-js-sdk/src/@types/location";
import { M_POLL_START } from "matrix-js-sdk/src/@types/polls";
import { MatrixEventEvent } from "matrix-js-sdk/src/models/event";
import { EmoteEvent, MessageEvent as ExtEvMessageEvent } from "matrix-events-sdk";

import SettingsStore from "../../../settings/SettingsStore";
import { Mjolnir } from "../../../mjolnir/Mjolnir";
Expand Down Expand Up @@ -54,6 +55,9 @@ interface IProps extends Omit<IBodyProps, "onMessageAllowed" | "mediaEventHelper
getRelationsForEvent?: GetRelationsForEvent;

isSeeingThroughMessageHiddenForModeration?: boolean;

// if true, the **unstable** extensible event functionality will be used to parse the event
forceUnstableExtensibleRendering?: boolean;
}

export interface IOperableEventTile {
Expand Down Expand Up @@ -149,7 +153,23 @@ export default class MessageEvent extends React.Component<IProps> implements IMe
public render(): JSX.Element {
const content = this.props.mxEvent.getContent();
const type = this.props.mxEvent.getType();
const msgtype = content.msgtype;
let msgtype = content.msgtype;

if (this.props.forceUnstableExtensibleRendering) {
// interpret the event as a legacy m.room.message event
const extev = this.props.mxEvent.unstableExtensibleEvent;
if (!extev) {
throw new Error("Runtime Error: Extensible event was asked for, but not given");
}
if (ExtEvMessageEvent.type.matches(extev.type)) {
msgtype = MsgType.Text;
} else if (EmoteEvent.type.matches(extev.type)) {
msgtype = MsgType.Emote;
} else {
throw new Error("Runtime Error: Unsupported extensible message type");
}
}

let BodyType: React.ComponentType<Partial<IBodyProps>> | ReactAnyComponent = RedactedBody;
if (!this.props.mxEvent.isRedacted()) {
// only resolve BodyType if event is not redacted
Expand Down Expand Up @@ -210,6 +230,7 @@ export default class MessageEvent extends React.Component<IProps> implements IMe
mediaEventHelper={this.mediaHelper}
getRelationsForEvent={this.props.getRelationsForEvent}
isSeeingThroughMessageHiddenForModeration={this.props.isSeeingThroughMessageHiddenForModeration}
forceUnstableExtensibleRendering={this.props.forceUnstableExtensibleRendering}
/>
) : null;
}
Expand Down
40 changes: 39 additions & 1 deletion src/components/views/messages/TextualBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import React, { createRef, SyntheticEvent, MouseEvent, ReactNode } from "react";
import ReactDOM from "react-dom";
import highlight from "highlight.js";
import { MsgType } from "matrix-js-sdk/src/@types/event";
import { EmoteEvent, MessageEvent as ExtEvMessageEvent } from "matrix-events-sdk";

import * as HtmlUtils from "../../../HtmlUtils";
import { formatDate } from "../../../DateUtils";
Expand Down Expand Up @@ -572,10 +573,47 @@ export default class TextualBody extends React.Component<IBodyProps, IState> {
);
}
const mxEvent = this.props.mxEvent;
const content = mxEvent.getContent();
let content = mxEvent.getContent();
let isNotice = false;
let isEmote = false;

if (this.props.forceUnstableExtensibleRendering) {
// interpret the event as a legacy m.room.message event
const extev = this.props.mxEvent.unstableExtensibleEvent;
if (!extev) {
throw new Error("Runtime Error: Extensible event was asked for, but not given @ TextualEvent");
}
if (ExtEvMessageEvent.type.matches(extev.type)) {
const msg = extev as unknown as ExtEvMessageEvent;
if (msg.text === undefined) {
// TODO(TR): We should probably detect this a whole lot sooner so we can just ignore the event.
throw new Error("Runtime Error: Message event is missing text");
}
content = {
...content,
msgtype: MsgType.Text,
body: msg.text,
format: msg.html !== undefined ? "org.matrix.custom.html" : undefined,
formatted_body: msg.html,
};
} else if (EmoteEvent.type.matches(extev.type)) {
const msg = extev as unknown as EmoteEvent;
if (msg.text === undefined) {
// TODO(TR): We should probably detect this a whole lot sooner so we can just ignore the event.
throw new Error("Runtime Error: Message event is missing text");
}
content = {
...content,
msgtype: MsgType.Emote,
body: msg.text,
format: msg.html !== undefined ? "org.matrix.custom.html" : undefined,
formatted_body: msg.html,
};
} else {
throw new Error("Runtime Error: Unsupported extensible message type @ TextualEvent");
}
}

// only strip reply if this is the original replying event, edits thereafter do not have the fallback
const stripReply = !mxEvent.replacingEvent() && !!getParentEventId(mxEvent);
let body: ReactNode;
Expand Down
20 changes: 19 additions & 1 deletion src/events/EventTileFactory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ limitations under the License.
import React from "react";
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { EventType, MsgType, RelationType } from "matrix-js-sdk/src/@types/event";
import { Optional } from "matrix-events-sdk";
import { EmoteEvent, Optional, MessageEvent as ExtEvMessageEvent } from "matrix-events-sdk";
import { M_POLL_START } from "matrix-js-sdk/src/@types/polls";
import { MatrixClient } from "matrix-js-sdk/src/client";
import { GroupCallIntent } from "matrix-js-sdk/src/webrtc/groupCall";
Expand Down Expand Up @@ -98,6 +98,14 @@ const EVENT_TILE_TYPES = new Map<string, Factory>([
[EventType.CallInvite, LegacyCallEventFactory], // note that this requires a special factory type
]);

const MSC1767MessageFactory: Factory = (ref, props) => <MessageEvent ref={ref} {...props} forceUnstableExtensibleRendering={true} />;
const MSC1767_EVENT_TILE_TYPES = new Map<string, Factory>([
[ExtEvMessageEvent.type.name, MSC1767MessageFactory],
[ExtEvMessageEvent.type.altName, MSC1767MessageFactory],
[EmoteEvent.type.name, MSC1767MessageFactory],
[EmoteEvent.type.altName, MSC1767MessageFactory],
]);

const STATE_EVENT_TILE_TYPES = new Map<string, Factory>([
[EventType.RoomEncryption, (ref, props) => <EncryptionEvent ref={ref} {...props} />],
[EventType.RoomCanonicalAlias, TextualEventFactory],
Expand Down Expand Up @@ -177,6 +185,16 @@ export function pickFactory(
return HiddenEventFactory;
}

// Early intercept: MSC1767-supported rooms require us to not render non-extensible
// events, so we simply ignore everything that isn't extensible in nature. This doesn't
// apply to state events though, as that would quickly turn the timeline blank.
// TODO(TR): Some event types are legal to let through here because they are extensible,
// but we don't have proper parsers set up for them yet, so ignore them for now.
const room = cli.getRoom(mxEvent.getRoomId());
if (!mxEvent.isState() && room?.unstableRequiresExtensibleEvents()) {
return MSC1767_EVENT_TILE_TYPES.get(mxEvent.getType()) ?? noEventFactoryFactory();
}

if (evType === EventType.RoomMessage) {
// don't show verification requests we're not involved in,
// not even when showing hidden events
Expand Down
23 changes: 23 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2564,6 +2564,11 @@ aggregate-error@^3.0.0:
clean-stack "^2.0.0"
indent-string "^4.0.0"

ajv-errors@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-3.0.0.tgz#e54f299f3a3d30fe144161e5f0d8d51196c527bc"
integrity sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==

ajv-keywords@^3.5.2:
version "3.5.2"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
Expand All @@ -2589,6 +2594,16 @@ ajv@^8.0.1, ajv@^8.6.2:
require-from-string "^2.0.2"
uri-js "^4.2.2"

ajv@^8.11.2:
version "8.12.0"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1"
integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==
dependencies:
fast-deep-equal "^3.1.1"
json-schema-traverse "^1.0.0"
require-from-string "^2.0.2"
uri-js "^4.2.2"

allchange@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/allchange/-/allchange-1.1.0.tgz#f8fa129e4b40c0b0a2c072c530f2324c6590e208"
Expand Down Expand Up @@ -6481,6 +6496,14 @@ [email protected]:
resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1.tgz#c8c38911e2cb29023b0bbac8d6f32e0de2c957dd"
integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==

matrix-events-sdk@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-2.0.0.tgz#f5f8dafbe4eae07fdbb628627f430ca5b1fd8c7a"
integrity sha512-UZbifYIO2o9+sNn4YuGjhMof/88TG68PyecKnH/pt8V3MFq0RZsbBUe+3/k5ZeVcEtr0pQLmcKB7d8aQVsVO/w==
dependencies:
ajv "^8.11.2"
ajv-errors "^3.0.0"

"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop":
version "23.0.0"
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/1ebcac37cca04f108548376f02a7a2d0666904d6"
Expand Down