Skip to content

Commit 8e2748c

Browse files
committed
Replace MatrixClient.isRoomEncrypted by MatrixClient.CryptoApi.isEncryptionEnabledInRoom in RoomView
1 parent c2ce7db commit 8e2748c

File tree

5 files changed

+78
-55
lines changed

5 files changed

+78
-55
lines changed

Diff for: src/components/structures/RoomView.tsx

+27-7
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,11 @@ export interface IRoomState {
233233
liveTimeline?: EventTimeline;
234234
narrow: boolean;
235235
msc3946ProcessDynamicPredecessor: boolean;
236+
/**
237+
* Whether the room is encrypted or not.
238+
* If null, we are still determining the encryption status.
239+
*/
240+
isRoomEncrypted: boolean | null;
236241

237242
canAskToJoin: boolean;
238243
promptAskToJoin: boolean;
@@ -417,6 +422,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
417422
canAskToJoin: this.askToJoinEnabled,
418423
promptAskToJoin: false,
419424
viewRoomOpts: { buttons: [] },
425+
isRoomEncrypted: false,
420426
};
421427
}
422428

@@ -847,7 +853,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
847853
return isManuallyShown && widgets.length > 0;
848854
}
849855

850-
public componentDidMount(): void {
856+
public async componentDidMount(): Promise<void> {
851857
this.unmounted = false;
852858

853859
this.dispatcherRef = defaultDispatcher.register(this.onAction);
@@ -914,6 +920,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
914920
const callState = call?.state;
915921
this.setState({
916922
callState,
923+
isRoomEncrypted: await this.getIsRoomEncrypted(),
917924
});
918925

919926
this.context.legacyCallHandler.on(LegacyCallHandlerEvent.CallState, this.onCallState);
@@ -1377,6 +1384,13 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
13771384
return room?.currentState.getStateEvents(EventType.RoomTombstone, "") ?? undefined;
13781385
}
13791386

1387+
private async getIsRoomEncrypted(roomId = this.state.roomId): Promise<boolean> {
1388+
const crypto = this.context.client?.getCrypto();
1389+
if (!crypto || !roomId) return false;
1390+
1391+
return await crypto.isEncryptionEnabledInRoom(roomId);
1392+
}
1393+
13801394
private async calculateRecommendedVersion(room: Room): Promise<void> {
13811395
const upgradeRecommendation = await room.getRecommendedVersion();
13821396
if (this.unmounted) return;
@@ -1411,7 +1425,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
14111425

14121426
private updatePreviewUrlVisibility({ roomId }: Room): void {
14131427
// URL Previews in E2EE rooms can be a privacy leak so use a different setting which is per-room explicit
1414-
const key = this.context.client?.isRoomEncrypted(roomId) ? "urlPreviewsEnabled_e2ee" : "urlPreviewsEnabled";
1428+
const key = this.state.isRoomEncrypted ? "urlPreviewsEnabled_e2ee" : "urlPreviewsEnabled";
14151429
this.setState({
14161430
showUrlPreview: SettingsStore.getValue(key, roomId),
14171431
});
@@ -1456,7 +1470,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
14561470
};
14571471

14581472
private async updateE2EStatus(room: Room): Promise<void> {
1459-
if (!this.context.client?.isRoomEncrypted(room.roomId)) return;
1473+
if (!this.context.client || !this.state.isRoomEncrypted) return;
14601474

14611475
// If crypto is not currently enabled, we aren't tracking devices at all,
14621476
// so we don't know what the answer is. Let's error on the safe side and show
@@ -1480,15 +1494,19 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
14801494
}
14811495
};
14821496

1483-
private onRoomStateEvents = (ev: MatrixEvent, state: RoomState): void => {
1497+
private onRoomStateEvents = async (ev: MatrixEvent, state: RoomState): Promise<void> => {
14841498
// ignore if we don't have a room yet
14851499
if (!this.state.room || this.state.room.roomId !== state.roomId) return;
14861500

14871501
switch (ev.getType()) {
14881502
case EventType.RoomTombstone:
14891503
this.setState({ tombstone: this.getRoomTombstone() });
14901504
break;
1491-
1505+
case EventType.RoomEncryption:
1506+
this.setState({ isRoomEncrypted: await this.getIsRoomEncrypted() }, () => {
1507+
if (this.state.room) this.updatePreviewUrlVisibility(this.state.room);
1508+
});
1509+
break;
14921510
default:
14931511
this.updatePermissions(this.state.room);
14941512
}
@@ -2026,7 +2044,9 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
20262044
};
20272045

20282046
public render(): ReactNode {
2029-
if (!this.context.client) return null;
2047+
const { isRoomEncrypted } = this.state;
2048+
const isRoomEncryptionLoading = isRoomEncrypted === null;
2049+
if (!this.context.client || isRoomEncryptionLoading) return null;
20302050

20312051
if (this.state.room instanceof LocalRoom) {
20322052
if (this.state.room.state === LocalRoomState.CREATING) {
@@ -2247,7 +2267,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
22472267
searchInfo={this.state.search}
22482268
onCancelClick={this.onCancelSearchClick}
22492269
onSearchScopeChange={this.onSearchScopeChange}
2250-
isRoomEncrypted={this.context.client.isRoomEncrypted(this.state.room.roomId)}
2270+
isRoomEncrypted={isRoomEncrypted}
22512271
/>
22522272
);
22532273
} else if (showRoomUpgradeBar) {

Diff for: src/contexts/RoomContext.ts

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ const RoomContext = createContext<
7575
canAskToJoin: false,
7676
promptAskToJoin: false,
7777
viewRoomOpts: { buttons: [] },
78+
isRoomEncrypted: null,
7879
});
7980
RoomContext.displayName = "RoomContext";
8081
export default RoomContext;

Diff for: test/test-utils/test-utils.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export function createTestClient(): MatrixClient {
117117

118118
getCrypto: jest.fn().mockReturnValue({
119119
getOwnDeviceKeys: jest.fn(),
120-
getUserDeviceInfo: jest.fn(),
120+
getUserDeviceInfo: jest.fn().mockResolvedValue(new Map()),
121121
getUserVerificationStatus: jest.fn(),
122122
getDeviceVerificationStatus: jest.fn(),
123123
resetKeyBackup: jest.fn(),

Diff for: test/unit-tests/components/structures/RoomView-test.tsx

+24-22
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,17 @@ import React, { createRef, RefObject } from "react";
1010
import { mocked, MockedObject } from "jest-mock";
1111
import {
1212
ClientEvent,
13-
MatrixClient,
14-
Room,
15-
RoomEvent,
13+
EventTimeline,
1614
EventType,
15+
IEvent,
1716
JoinRule,
17+
MatrixClient,
1818
MatrixError,
19-
RoomStateEvent,
2019
MatrixEvent,
20+
Room,
21+
RoomEvent,
22+
RoomStateEvent,
2123
SearchResult,
22-
IEvent,
2324
} from "matrix-js-sdk/src/matrix";
2425
import { CryptoApi, UserVerificationStatus } from "matrix-js-sdk/src/crypto-api";
2526
import { KnownMembership } from "matrix-js-sdk/src/types";
@@ -87,8 +88,7 @@ describe("RoomView", () => {
8788

8889
beforeEach(() => {
8990
mockPlatformPeg({ reload: () => {} });
90-
stubClient();
91-
cli = mocked(MatrixClientPeg.safeGet());
91+
cli = mocked(stubClient());
9292

9393
room = new Room(`!${roomCount++}:example.org`, cli, "@alice:example.org");
9494
jest.spyOn(room, "findPredecessor");
@@ -247,8 +247,9 @@ describe("RoomView", () => {
247247

248248
it("updates url preview visibility on encryption state change", async () => {
249249
room.getMyMembership = jest.fn().mockReturnValue(KnownMembership.Join);
250+
jest.spyOn(cli, "getCrypto").mockReturnValue(crypto);
250251
// we should be starting unencrypted
251-
expect(cli.isRoomEncrypted(room.roomId)).toEqual(false);
252+
expect(await cli.getCrypto()?.isEncryptionEnabledInRoom(room.roomId)).toEqual(false);
252253

253254
const roomViewInstance = await getRoomViewInstance();
254255

@@ -263,23 +264,23 @@ describe("RoomView", () => {
263264
expect(roomViewInstance.state.showUrlPreview).toBe(true);
264265

265266
// now enable encryption
266-
cli.isRoomEncrypted.mockReturnValue(true);
267+
jest.spyOn(cli.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(true);
267268

268269
// and fake an encryption event into the room to prompt it to re-check
269-
await act(() =>
270-
room.addLiveEvents([
271-
new MatrixEvent({
272-
type: "m.room.encryption",
273-
sender: cli.getUserId()!,
274-
content: {},
275-
event_id: "someid",
276-
room_id: room.roomId,
277-
}),
278-
]),
279-
);
270+
act(() => {
271+
const encryptionEvent = new MatrixEvent({
272+
type: EventType.RoomEncryption,
273+
sender: cli.getUserId()!,
274+
content: {},
275+
event_id: "someid",
276+
room_id: room.roomId,
277+
});
278+
const roomState = room.getLiveTimeline().getState(EventTimeline.FORWARDS)!;
279+
cli.emit(RoomStateEvent.Events, encryptionEvent, roomState, null);
280+
});
280281

281282
// URL previews should now be disabled
282-
expect(roomViewInstance.state.showUrlPreview).toBe(false);
283+
await waitFor(() => expect(roomViewInstance.state.showUrlPreview).toBe(false));
283284
});
284285

285286
it("updates live timeline when a timeline reset happens", async () => {
@@ -427,7 +428,8 @@ describe("RoomView", () => {
427428
]);
428429
jest.spyOn(DMRoomMap.shared(), "getUserIdForRoomId").mockReturnValue(cli.getSafeUserId());
429430
jest.spyOn(DMRoomMap.shared(), "getRoomIds").mockReturnValue(new Set([room.roomId]));
430-
mocked(cli).isRoomEncrypted.mockReturnValue(true);
431+
jest.spyOn(cli, "getCrypto").mockReturnValue(crypto);
432+
jest.spyOn(cli.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(true);
431433
await renderRoomView();
432434
});
433435

0 commit comments

Comments
 (0)