Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add reactions to html export #28210

Merged
merged 22 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c05c429
Absorb the matrix-react-sdk repository (#28192)
t3chguy Oct 16, 2024
3b75e2a
Update dependency @sentry/browser to v8.33.0 [SECURITY] (#28194)
renovate[bot] Oct 16, 2024
8d235bd
Update babel monorepo (#28196)
renovate[bot] Oct 16, 2024
2a81dc4
Update dependency @types/react to v17.0.83 (#28138)
renovate[bot] Oct 16, 2024
5f7e807
Update dependency @matrix-org/spec to v1.12.0 (#28200)
renovate[bot] Oct 16, 2024
f26b51c
Update dependency @formatjs/intl-segmenter to v11.5.9 (#28197)
renovate[bot] Oct 16, 2024
f56f814
Remove references to `MatrixClient.crypto` (#28204)
florianduros Oct 16, 2024
898b6bd
Update dependency typescript to v5.6.3 (#28198)
renovate[bot] Oct 16, 2024
77c822a
Update dependency eslint-plugin-unicorn to v56 (#28202)
renovate[bot] Oct 16, 2024
e859efe
Update dependency stylelint to v16.10.0 (#28201)
renovate[bot] Oct 16, 2024
705625d
Update browserslist (#28199)
renovate[bot] Oct 16, 2024
a19b9d3
Add reactions to html export and add test
langleyd Oct 16, 2024
ecc3b84
Add reaction to snapshot test
langleyd Oct 17, 2024
c21d759
Merge branch 'develop' of github.com:vector-im/element-web into langl…
langleyd Oct 17, 2024
46d8efa
Update snapshot output
langleyd Oct 17, 2024
5ab338f
Remove logging
langleyd Oct 17, 2024
3125c07
Add reaction to html export screenshot test.
langleyd Oct 17, 2024
61569be
lint
langleyd Oct 17, 2024
9cd48fa
Merge branch 'develop' into langleyd/add_reactions_to_html_export
langleyd Oct 17, 2024
b096905
Merge branch 'develop' of github.com:vector-im/element-web into langl…
langleyd Oct 18, 2024
b798742
Merge branch 'develop' of github.com:vector-im/element-web into langl…
langleyd Oct 18, 2024
3925e94
Update reference screenshot.
langleyd Oct 18, 2024
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
5 changes: 4 additions & 1 deletion playwright/e2e/chat-export/html-export.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 1 addition & 8 deletions playwright/e2e/read-receipts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
23 changes: 23 additions & 0 deletions playwright/pages/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 10 additions & 2 deletions src/utils/exportUtils/Exporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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>;
}
3 changes: 2 additions & 1 deletion src/utils/exportUtils/HtmlExport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
57 changes: 56 additions & 1 deletion test/unit-tests/utils/exportUtils/HTMLExport-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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(
() =>
Expand Down Expand Up @@ -167,6 +201,7 @@ describe("HTMLExport", () => {
body: `Message #${i}`,
},
}));
mockReactionForMessage(events[0]);
mockMessages(...events);

const exporter = new HTMLExporter(
Expand Down Expand Up @@ -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);
});
});

Large diffs are not rendered by default.

Loading