diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index 22da73bef7..396ab105d1 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -11,6 +11,7 @@ import React, { createRef, forwardRef, JSX, MouseEvent, ReactNode } from "react" import classNames from "classnames"; import { EventStatus, + EventTimeline, EventType, MatrixEvent, MatrixEventEvent, @@ -21,6 +22,7 @@ import { Room, RoomEvent, RoomMember, + RoomStateEvent, Thread, ThreadEvent, } from "matrix-js-sdk/src/matrix"; @@ -262,6 +264,10 @@ interface IState { thread: Thread | null; threadNotification?: NotificationCountType; + /** + * Whether the event is encrypted. + */ + isRoomEncrypted: boolean; } /** @@ -318,6 +324,7 @@ export class UnwrappedEventTile extends React.Component hover: false, thread, + isRoomEncrypted: false, }; // don't do RR animations until we are mounted @@ -386,7 +393,7 @@ export class UnwrappedEventTile extends React.Component return true; } - public componentDidMount(): void { + public async componentDidMount(): Promise { this.unmounted = false; this.suppressReadReceiptAnimation = false; const client = MatrixClientPeg.safeGet(); @@ -413,6 +420,12 @@ export class UnwrappedEventTile extends React.Component room?.on(ThreadEvent.New, this.onNewThread); this.verifyEvent(); + + room?.getLiveTimeline().getState(EventTimeline.FORWARDS)?.on(RoomStateEvent.Events, this.onRoomStateEvents); + + const crypto = client.getCrypto(); + if (!room || !crypto) return; + this.setState({ isRoomEncrypted: await crypto.isEncryptionEnabledInRoom(room.roomId) }); } private updateThread = (thread: Thread): void => { @@ -470,6 +483,17 @@ export class UnwrappedEventTile extends React.Component } }; + private onRoomStateEvents = async (evt: MatrixEvent): Promise => { + const client = MatrixClientPeg.safeGet(); + const crypto = client.getCrypto(); + if (!crypto) return; + + const room = client.getRoom(evt.getRoomId()); + if (room && evt.getType() === EventType.RoomEncryption) { + this.setState({ isRoomEncrypted: await crypto.isEncryptionEnabledInRoom(room.roomId) }); + } + }; + private get thread(): Thread | null { let thread: Thread | undefined = this.props.mxEvent.getThread(); /** @@ -767,7 +791,7 @@ export class UnwrappedEventTile extends React.Component } } - if (MatrixClientPeg.safeGet().isRoomEncrypted(ev.getRoomId()!)) { + if (this.state.isRoomEncrypted) { // else if room is encrypted // and event is being encrypted or is not_sent (Unknown Devices/Network Error) if (ev.status === EventStatus.ENCRYPTING) { diff --git a/test/unit-tests/components/views/dialogs/ForwardDialog-test.tsx b/test/unit-tests/components/views/dialogs/ForwardDialog-test.tsx index 6942f76cda..2912f47f27 100644 --- a/test/unit-tests/components/views/dialogs/ForwardDialog-test.tsx +++ b/test/unit-tests/components/views/dialogs/ForwardDialog-test.tsx @@ -32,6 +32,7 @@ import { mkEvent, mkMessage, mkStubRoom, + mockClientMethodsCrypto, mockPlatformPeg, } from "../../../../test-utils"; import { TILE_SERVER_WK_KEY } from "../../../../../src/utils/WellKnownUtils"; @@ -67,7 +68,6 @@ describe("ForwardDialog", () => { getAccountData: jest.fn().mockReturnValue(accountDataEvent), getPushActionsForEvent: jest.fn(), mxcUrlToHttp: jest.fn().mockReturnValue(""), - isRoomEncrypted: jest.fn().mockReturnValue(false), getProfileInfo: jest.fn().mockResolvedValue({ displayname: "Alice", }), @@ -76,6 +76,7 @@ describe("ForwardDialog", () => { getClientWellKnown: jest.fn().mockReturnValue({ [TILE_SERVER_WK_KEY.name]: { map_style_url: "maps.com" }, }), + ...mockClientMethodsCrypto(), }); const defaultRooms = ["a", "A", "b"].map((name) => mkStubRoom(name, name, mockClient)); diff --git a/test/unit-tests/components/views/rooms/EventTile-test.tsx b/test/unit-tests/components/views/rooms/EventTile-test.tsx index 4cb2296760..43c70039a6 100644 --- a/test/unit-tests/components/views/rooms/EventTile-test.tsx +++ b/test/unit-tests/components/views/rooms/EventTile-test.tsx @@ -243,6 +243,7 @@ describe("EventTile", () => { const mockCrypto = { // a mocked version of getEncryptionInfoForEvent which will pick its result from `eventToEncryptionInfoMap` getEncryptionInfoForEvent: async (event: MatrixEvent) => eventToEncryptionInfoMap.get(event.getId()!)!, + isEncryptionEnabledInRoom: jest.fn().mockResolvedValue(false), } as unknown as CryptoApi; client.getCrypto = () => mockCrypto; }); @@ -434,7 +435,7 @@ describe("EventTile", () => { }); it("should update the warning when the event is replaced with an unencrypted one", async () => { - jest.spyOn(client, "isRoomEncrypted").mockReturnValue(true); + jest.spyOn(client.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(true); // we start out with an event from the trusted device mxEvent = await mkEncryptedMatrixEvent({