From 675be154c006f780dc56a8a33c17fdc4331d7e8b Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Fri, 10 Apr 2026 19:12:39 +0100 Subject: [PATCH] evil temporary hack to apply event transforms in one place --- .../views/rooms/SendMessageComposer.tsx | 6 ----- .../rooms/wysiwyg_composer/utils/message.ts | 6 ----- apps/web/src/modules/Api.ts | 23 +++++++++++++++++++ 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/apps/web/src/components/views/rooms/SendMessageComposer.tsx b/apps/web/src/components/views/rooms/SendMessageComposer.tsx index 1d50de4948..0d9a68c45d 100644 --- a/apps/web/src/components/views/rooms/SendMessageComposer.tsx +++ b/apps/web/src/components/views/rooms/SendMessageComposer.tsx @@ -60,7 +60,6 @@ import { type IDiff } from "../../../editor/diff"; import { getBlobSafeMimeType } from "../../../utils/blobs"; import { EMOJI_REGEX } from "../../../HtmlUtils"; import { attachMentions, attachRelation } from "../../../utils/messages"; -import { ModuleApi } from "../../../modules/Api"; // The prefix used when persisting editor drafts to localstorage. export const EDITOR_STATE_STORAGE_PREFIX = "mx_cider_state_"; @@ -417,11 +416,6 @@ export class SendMessageComposer extends React.Component) as RoomMessageEventContent; - } - if (SettingsStore.getValue("Performance.addSendMessageTimingMetadata")) { decorateStartSendingTime(content); } diff --git a/apps/web/src/components/views/rooms/wysiwyg_composer/utils/message.ts b/apps/web/src/components/views/rooms/wysiwyg_composer/utils/message.ts index df8e1b37ce..2594ac4841 100644 --- a/apps/web/src/components/views/rooms/wysiwyg_composer/utils/message.ts +++ b/apps/web/src/components/views/rooms/wysiwyg_composer/utils/message.ts @@ -28,7 +28,6 @@ import { createRedactEventDialog } from "../../../dialogs/ConfirmRedactDialog"; import { endEditing, cancelPreviousPendingEdit } from "./editing"; import type EditorStateTransfer from "../../../../../utils/EditorStateTransfer"; import { createMessageContent, EMOTE_PREFIX } from "./createMessageContent"; -import { ModuleApi } from "../../../../../modules/Api"; import { isContentModified } from "./isContentModified"; import { CommandCategories, getCommand } from "../../../../../slash-commands/SlashCommands"; import { runSlashCommand, shouldSendAnyway } from "../../../../../editor/commands"; @@ -123,11 +122,6 @@ export async function sendMessage( return; } - // Apply module event content transforms - for (const cb of ModuleApi.instance.extras.eventContentTransformCallbacks) { - content = cb(roomId, content as Record) as RoomMessageEventContent; - } - if (SettingsStore.getValue("Performance.addSendMessageTimingMetadata")) { decorateStartSendingTime(content); } diff --git a/apps/web/src/modules/Api.ts b/apps/web/src/modules/Api.ts index 44da332e88..4a936bfedd 100644 --- a/apps/web/src/modules/Api.ts +++ b/apps/web/src/modules/Api.ts @@ -111,6 +111,29 @@ export class ModuleApi implements Api { public static patchClientForEnvelopeTransforms(): void { // eslint-disable-next-line @typescript-eslint/no-explicit-any const proto = MatrixClient.prototype as any; + + // Patch sendCompleteEvent to apply plaintext content transforms before + // encryption. This is the single funnel point for all event sends + // (messages, edits, media, stickers, etc.) and has a clean + // { roomId, eventObject: { type, content } } shape. + const originalSendComplete = proto.sendCompleteEvent; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + proto.sendCompleteEvent = function (this: MatrixClient, params: any) { + if ( + params?.roomId && + params?.eventObject?.content && + ModuleApi._instance?.extras.eventContentTransformCallbacks.length + ) { + let content = params.eventObject.content; + for (const cb of ModuleApi._instance.extras.eventContentTransformCallbacks) { + content = cb(params.roomId, content); + } + params.eventObject.content = content; + } + return originalSendComplete.call(this, params); + }; + + // Patch sendEventHttpRequest to apply envelope transforms after encryption. const original = proto.sendEventHttpRequest; proto.sendEventHttpRequest = function ( this: MatrixClient,