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

Replace MatrixClient.isRoomEncrypted by MatrixClient.CryptoApi.isEncryptionEnabledInRoom in EventTile.tsx #28510

32 changes: 30 additions & 2 deletions src/components/views/rooms/EventTile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import React, { createRef, forwardRef, JSX, MouseEvent, ReactNode } from "react"
import classNames from "classnames";
import {
EventStatus,
EventTimeline,
EventType,
MatrixEvent,
MatrixEventEvent,
Expand All @@ -21,6 +22,7 @@ import {
Room,
RoomEvent,
RoomMember,
RoomStateEvent,
Thread,
ThreadEvent,
} from "matrix-js-sdk/src/matrix";
Expand Down Expand Up @@ -262,6 +264,10 @@ interface IState {

thread: Thread | null;
threadNotification?: NotificationCountType;
/**
* Whether the event is encrypted.
*/
isRoomEncrypted: boolean;
florianduros marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down Expand Up @@ -318,6 +324,7 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
hover: false,

thread,
isRoomEncrypted: false,
};

// don't do RR animations until we are mounted
Expand Down Expand Up @@ -386,7 +393,7 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
return true;
}

public componentDidMount(): void {
public async componentDidMount(): Promise<void> {
this.unmounted = false;
this.suppressReadReceiptAnimation = false;
const client = MatrixClientPeg.safeGet();
Expand All @@ -413,6 +420,12 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
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 => {
Expand All @@ -434,6 +447,10 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
client.removeListener(RoomEvent.Receipt, this.onRoomReceipt);
const room = client.getRoom(this.props.mxEvent.getRoomId());
room?.off(ThreadEvent.New, this.onNewThread);
room
?.getLiveTimeline()
.getState(EventTimeline.FORWARDS)
?.off(RoomStateEvent.Events, this.onRoomStateEvents);
}
this.isListeningForReceipts = false;
this.props.mxEvent.removeListener(MatrixEventEvent.Decrypted, this.onDecrypted);
Expand Down Expand Up @@ -470,6 +487,17 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
}
};

private onRoomStateEvents = async (evt: MatrixEvent): Promise<void> => {
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();
/**
Expand Down Expand Up @@ -767,7 +795,7 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
}
}

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) {
Expand Down
1 change: 1 addition & 0 deletions test/test-utils/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export function createTestClient(): MatrixClient {
restoreKeyBackupWithPassphrase: jest.fn(),
loadSessionBackupPrivateKeyFromSecretStorage: jest.fn(),
storeSessionBackupPrivateKey: jest.fn(),
getEncryptionInfoForEvent: jest.fn().mockResolvedValue(null),
}),

getPushActionsForEvent: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
mkEvent,
mkMessage,
mkStubRoom,
mockClientMethodsCrypto,
mockPlatformPeg,
} from "../../../../test-utils";
import { TILE_SERVER_WK_KEY } from "../../../../../src/utils/WellKnownUtils";
Expand Down Expand Up @@ -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",
}),
Expand All @@ -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));

Expand Down
28 changes: 27 additions & 1 deletion test/unit-tests/components/views/rooms/EventTile-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ import * as React from "react";
import { act, fireEvent, render, screen, waitFor } from "jest-matrix-react";
import { mocked } from "jest-mock";
import {
EventTimeline,
EventType,
IEventDecryptionResult,
MatrixClient,
MatrixEvent,
NotificationCountType,
PendingEventOrdering,
Room,
RoomStateEvent,
TweakName,
} from "matrix-js-sdk/src/matrix";
import {
Expand Down Expand Up @@ -243,6 +245,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;
});
Expand Down Expand Up @@ -434,7 +437,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({
Expand Down Expand Up @@ -578,4 +581,27 @@ describe("EventTile", () => {
});
});
});

it("should display the not encrypted status for an unencrypted event when the room becomes encrypted", async () => {
jest.spyOn(client.getCrypto()!, "getEncryptionInfoForEvent").mockResolvedValue({
shieldColour: EventShieldColour.NONE,
shieldReason: null,
});

getComponent();
await flushPromises();
// The room and the event are unencrypted, the tile should not show the not encrypted status
expect(screen.queryByText("Not encrypted")).toBeNull();

// The room is now encrypted
jest.spyOn(client.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(true);
// Emit a state event to trigger a re-render
const roomState = room!.getLiveTimeline().getState(EventTimeline.FORWARDS)!;
act(() => {
roomState.emit(RoomStateEvent.Events, new MatrixEvent({ type: EventType.RoomEncryption }), roomState, null);
});

// The event tile should now show the not encrypted status
await waitFor(() => expect(screen.getByText("Not encrypted")).toBeInTheDocument());
});
});
Loading