mirror of https://github.com/vector-im/riot-web
Add reactions to html export (#28210)
* Absorb the matrix-react-sdk repository (#28192) Co-authored-by: github-merge-queue <118344674+github-merge-queue@users.noreply.github.com> Co-authored-by: github-merge-queue <github-merge-queue@users.noreply.github.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Florian Duros <florian.duros@ormaz.fr> Co-authored-by: Kim Brose <kim.brose@nordeck.net> Co-authored-by: Florian Duros <florianduros@element.io> Co-authored-by: R Midhun Suresh <hi@midhun.dev> Co-authored-by: dbkr <986903+dbkr@users.noreply.github.com> Co-authored-by: ElementRobot <releases@riot.im> Co-authored-by: dbkr <dbkr@users.noreply.github.com> Co-authored-by: David Baker <dbkr@users.noreply.github.com> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Co-authored-by: David Langley <davidl@element.io> Co-authored-by: Michael Weimann <michaelw@matrix.org> Co-authored-by: Timshel <Timshel@users.noreply.github.com> Co-authored-by: Sahil Silare <32628578+sahil9001@users.noreply.github.com> Co-authored-by: Will Hunt <will@half-shot.uk> Co-authored-by: Hubert Chathi <hubert@uhoreg.ca> Co-authored-by: Andrew Ferrazzutti <andrewf@element.io> Co-authored-by: Robin <robin@robin.town> Co-authored-by: Tulir Asokan <tulir@maunium.net> * Update dependency @sentry/browser to v8.33.0 [SECURITY] (#28194) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update babel monorepo (#28196) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update dependency @types/react to v17.0.83 (#28138) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update dependency @matrix-org/spec to v1.12.0 (#28200) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update dependency @formatjs/intl-segmenter to v11.5.9 (#28197) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Remove references to `MatrixClient.crypto` (#28204) * Remove `VerificationExplorer` * Remove `remakeolm` slash command * Remove call to `crypto.cancelAndResendAllOutgoingKeyRequests` * Remove crypto mock in `LoginWithQR-test.tsx` * Remove `StopGadWidgetDriver.sendToDevice` * Remove remaining mock * Update dependency typescript to v5.6.3 (#28198) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update dependency eslint-plugin-unicorn to v56 (#28202) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update dependency stylelint to v16.10.0 (#28201) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Update browserslist (#28199) * Update browserslist * Update tests Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> * Add reactions to html export and add test * Add reaction to snapshot test * Update snapshot output * Remove logging * Add reaction to html export screenshot test. * lint * Update reference screenshot. --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: github-merge-queue <118344674+github-merge-queue@users.noreply.github.com> Co-authored-by: github-merge-queue <github-merge-queue@users.noreply.github.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Florian Duros <florian.duros@ormaz.fr> Co-authored-by: Kim Brose <kim.brose@nordeck.net> Co-authored-by: Florian Duros <florianduros@element.io> Co-authored-by: R Midhun Suresh <hi@midhun.dev> Co-authored-by: dbkr <986903+dbkr@users.noreply.github.com> Co-authored-by: ElementRobot <releases@riot.im> Co-authored-by: dbkr <dbkr@users.noreply.github.com> Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Co-authored-by: Michael Weimann <michaelw@matrix.org> Co-authored-by: Timshel <Timshel@users.noreply.github.com> Co-authored-by: Sahil Silare <32628578+sahil9001@users.noreply.github.com> Co-authored-by: Will Hunt <will@half-shot.uk> Co-authored-by: Hubert Chathi <hubert@uhoreg.ca> Co-authored-by: Andrew Ferrazzutti <andrewf@element.io> Co-authored-by: Robin <robin@robin.town> Co-authored-by: Tulir Asokan <tulir@maunium.net>pull/28007/head
parent
06d1239608
commit
59cd5180af
|
@ -96,7 +96,10 @@ test.describe("HTML Export", () => {
|
|||
|
||||
// Send a bunch of messages to populate the room
|
||||
for (let i = 1; i < 10; i++) {
|
||||
await app.client.sendMessage(room.roomId, { body: `Testing ${i}`, msgtype: "m.text" });
|
||||
const respone = await app.client.sendMessage(room.roomId, { body: `Testing ${i}`, msgtype: "m.text" });
|
||||
if (i == 1) {
|
||||
await app.client.reactToMessage(room.roomId, null, respone.event_id, "🙃");
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for all the messages to be displayed
|
||||
|
|
|
@ -222,14 +222,7 @@ export class MessageBuilder {
|
|||
threadId: !ev.isThreadRoot ? ev.threadRootId : undefined,
|
||||
}));
|
||||
const roomId = await room.evaluate((room) => room.roomId);
|
||||
|
||||
await bot.sendEvent(roomId, threadId ?? null, "m.reaction", {
|
||||
"m.relates_to": {
|
||||
rel_type: "m.annotation",
|
||||
event_id: id,
|
||||
key: reaction,
|
||||
},
|
||||
});
|
||||
await bot.reactToMessage(roomId, threadId, id, reaction);
|
||||
}
|
||||
})(this);
|
||||
}
|
||||
|
|
|
@ -143,6 +143,29 @@ export class Client {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a reaction to to a message
|
||||
* @param roomId ID of the room to send the reaction into
|
||||
* @param threadId ID of the thread to send into or null for main timeline
|
||||
* @param eventId Event ID of the message you are reacting to
|
||||
* @param reaction The reaction text to send
|
||||
* @returns
|
||||
*/
|
||||
public async reactToMessage(
|
||||
roomId: string,
|
||||
threadId: string | null,
|
||||
eventId: string,
|
||||
reaction: string,
|
||||
): Promise<ISendEventResponse> {
|
||||
return this.sendEvent(roomId, threadId ?? null, "m.reaction", {
|
||||
"m.relates_to": {
|
||||
rel_type: "m.annotation",
|
||||
event_id: eventId,
|
||||
key: reaction,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a room with given options.
|
||||
* @param options the options to apply when creating the room
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
|
@ -6,8 +6,8 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
|||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { Direction, MatrixEvent, Room } from "matrix-js-sdk/src/matrix";
|
||||
import { MediaEventContent } from "matrix-js-sdk/src/types";
|
||||
import { Direction, MatrixEvent, Relations, Room } from "matrix-js-sdk/src/matrix";
|
||||
import { EventType, MediaEventContent, RelationType } from "matrix-js-sdk/src/types";
|
||||
import { saveAs } from "file-saver";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import sanitizeFilename from "sanitize-filename";
|
||||
|
@ -284,5 +284,13 @@ export default abstract class Exporter {
|
|||
return mxEv.getType() === attachmentTypes[0] || attachmentTypes.includes(mxEv.getContent().msgtype!);
|
||||
}
|
||||
|
||||
protected getRelationsForEvent = (
|
||||
eventId: string,
|
||||
relationType: RelationType | string,
|
||||
eventType: EventType | string,
|
||||
): Relations | undefined => {
|
||||
return this.room.getUnfilteredTimelineSet().relations.getChildEventsForEvent(eventId, relationType, eventType);
|
||||
};
|
||||
|
||||
public abstract export(): Promise<void>;
|
||||
}
|
||||
|
|
|
@ -288,9 +288,10 @@ export default class HTMLExporter extends Exporter {
|
|||
permalinkCreator={this.permalinkCreator}
|
||||
lastSuccessful={false}
|
||||
isSelectedEvent={false}
|
||||
showReactions={false}
|
||||
showReactions={true}
|
||||
layout={Layout.Group}
|
||||
showReadReceipts={false}
|
||||
getRelationsForEvent={this.getRelationsForEvent}
|
||||
/>
|
||||
</TooltipProvider>
|
||||
</MatrixClientContext.Provider>
|
||||
|
|
|
@ -7,19 +7,24 @@ Please see LICENSE files in the repository root for full details.
|
|||
*/
|
||||
|
||||
import {
|
||||
EventTimeline,
|
||||
EventTimelineSet,
|
||||
EventType,
|
||||
IRoomEvent,
|
||||
MatrixClient,
|
||||
MatrixEvent,
|
||||
MsgType,
|
||||
Relations,
|
||||
RelationType,
|
||||
Room,
|
||||
RoomMember,
|
||||
RoomState,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
import escapeHtml from "escape-html";
|
||||
import { RelationsContainer } from "matrix-js-sdk/src/models/relations-container";
|
||||
|
||||
import { filterConsole, mkStubRoom, REPEATABLE_DATE, stubClient } from "../../../test-utils";
|
||||
import { filterConsole, mkReaction, mkStubRoom, REPEATABLE_DATE, stubClient } from "../../../test-utils";
|
||||
import { ExportType, IExportOptions } from "../../../../src/utils/exportUtils/exportUtils";
|
||||
import SdkConfig from "../../../../src/SdkConfig";
|
||||
import HTMLExporter from "../../../../src/utils/exportUtils/HtmlExport";
|
||||
|
@ -123,6 +128,35 @@ describe("HTMLExport", () => {
|
|||
fetchMock.get(media.srcHttp!, body);
|
||||
}
|
||||
|
||||
function mockReactionForMessage(message: IRoomEvent): MatrixEvent {
|
||||
const firstMessage = new MatrixEvent(message);
|
||||
const reaction = mkReaction(firstMessage);
|
||||
|
||||
const relationsContainer = {
|
||||
getRelations: jest.fn(),
|
||||
getChildEventsForEvent: jest.fn(),
|
||||
} as unknown as RelationsContainer;
|
||||
const relations = new Relations(RelationType.Annotation, EventType.Reaction, client);
|
||||
relations.addEvent(reaction);
|
||||
relationsContainer.getChildEventsForEvent = jest
|
||||
.fn()
|
||||
.mockImplementation(
|
||||
(eventId: string, relationType: RelationType | string, eventType: EventType | string) => {
|
||||
if (eventId === firstMessage.getId()) {
|
||||
return relations;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const timelineSet = {
|
||||
relations: relationsContainer,
|
||||
getLiveTimeline: () => timeline,
|
||||
} as unknown as EventTimelineSet;
|
||||
const timeline = new EventTimeline(timelineSet);
|
||||
room.getUnfilteredTimelineSet = jest.fn().mockReturnValue(timelineSet);
|
||||
return reaction;
|
||||
}
|
||||
|
||||
it("should throw when created with invalid config for LastNMessages", async () => {
|
||||
expect(
|
||||
() =>
|
||||
|
@ -167,6 +201,7 @@ describe("HTMLExport", () => {
|
|||
body: `Message #${i}`,
|
||||
},
|
||||
}));
|
||||
mockReactionForMessage(events[0]);
|
||||
mockMessages(...events);
|
||||
|
||||
const exporter = new HTMLExporter(
|
||||
|
@ -587,4 +622,24 @@ describe("HTMLExport", () => {
|
|||
expect(await file.text()).toContain("testing testing");
|
||||
expect(client.createMessagesRequest).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should include reactions", async () => {
|
||||
const reaction = mockReactionForMessage(EVENT_MESSAGE);
|
||||
mockMessages(EVENT_MESSAGE);
|
||||
const exporter = new HTMLExporter(
|
||||
room,
|
||||
ExportType.LastNMessages,
|
||||
{
|
||||
attachmentsIncluded: false,
|
||||
maxSize: 1_024 * 1_024,
|
||||
numberOfMessages: 40,
|
||||
},
|
||||
() => {},
|
||||
);
|
||||
|
||||
await exporter.export();
|
||||
|
||||
const file = getMessageFile(exporter);
|
||||
expect(await file.text()).toContain(reaction.getContent()["m.relates_to"]?.key);
|
||||
});
|
||||
});
|
||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue