Skip to content

Commit

Permalink
Listen to events so that encryption icon updates when status changes (#…
Browse files Browse the repository at this point in the history
…28407)

* listen to events so that encryption icon updates when status changes

* remove debugging message
  • Loading branch information
uhoreg authored Nov 18, 2024
1 parent 4f8e9eb commit ed97951
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 10 deletions.
37 changes: 28 additions & 9 deletions src/hooks/useEncryptionStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,40 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/

import { MatrixClient, Room } from "matrix-js-sdk/src/matrix";
import { useEffect, useState } from "react";
import { CryptoEvent, MatrixClient, Room, RoomStateEvent } from "matrix-js-sdk/src/matrix";
import { useEffect, useMemo, useState } from "react";
import { throttle } from "lodash";

import { E2EStatus, shieldStatusForRoom } from "../utils/ShieldUtils";
import { useTypedEventEmitter } from "./useEventEmitter";

export function useEncryptionStatus(client: MatrixClient, room: Room): E2EStatus | null {
const [e2eStatus, setE2eStatus] = useState<E2EStatus | null>(null);

useEffect(() => {
if (client.getCrypto()) {
shieldStatusForRoom(client, room).then((e2eStatus) => {
setE2eStatus(e2eStatus);
});
}
}, [client, room]);
const updateEncryptionStatus = useMemo(
() =>
throttle(
() => {
if (client.getCrypto()) {
shieldStatusForRoom(client, room).then((e2eStatus) => {
setE2eStatus(e2eStatus);
});
}
},
250,
{ leading: true, trailing: true },
),
[client, room],
);

useEffect(updateEncryptionStatus, [updateEncryptionStatus]);

// shieldStatusForRoom depends on the room membership, each member's trust
// status for each member, and each member's devices, so we update the
// status whenever any of those changes.
useTypedEventEmitter(room, RoomStateEvent.Members, updateEncryptionStatus);
useTypedEventEmitter(client, CryptoEvent.UserTrustStatusChanged, updateEncryptionStatus);
useTypedEventEmitter(client, CryptoEvent.DevicesUpdated, updateEncryptionStatus);

return e2eStatus;
}
58 changes: 57 additions & 1 deletion test/unit-tests/components/views/rooms/RoomHeader-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,19 @@ Please see LICENSE files in the repository root for full details.

import React from "react";
import { CallType, MatrixCall } from "matrix-js-sdk/src/webrtc/call";
import { EventType, JoinRule, MatrixEvent, PendingEventOrdering, Room, RoomMember } from "matrix-js-sdk/src/matrix";
import {
EventType,
JoinRule,
MatrixEvent,
PendingEventOrdering,
Room,
RoomStateEvent,
RoomMember,
} from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types";
import { CryptoEvent, UserVerificationStatus } from "matrix-js-sdk/src/crypto-api";
import {
act,
createEvent,
fireEvent,
getAllByLabelText,
Expand Down Expand Up @@ -632,6 +642,52 @@ describe("RoomHeader", () => {

expect(asFragment()).toMatchSnapshot();
});

it("updates the icon when the encryption status changes", async () => {
// The room starts verified
jest.spyOn(ShieldUtils, "shieldStatusForRoom").mockResolvedValue(ShieldUtils.E2EStatus.Verified);
render(<RoomHeader room={room} />, getWrapper());
await waitFor(() => expect(getByLabelText(document.body, "Verified")).toBeInTheDocument());

// A new member joins, and the room becomes unverified
jest.spyOn(ShieldUtils, "shieldStatusForRoom").mockResolvedValue(ShieldUtils.E2EStatus.Warning);
act(() => {
room.emit(
RoomStateEvent.Members,
new MatrixEvent({
event_id: "$event_id",
type: EventType.RoomMember,
state_key: "@alice:example.org",
content: {
membership: "join",
},
room_id: ROOM_ID,
sender: "@alice:example.org",
}),
room.currentState,
new RoomMember(room.roomId, "@alice:example.org"),
);
});
await waitFor(() => expect(getByLabelText(document.body, "Untrusted")).toBeInTheDocument());

// The user becomes verified
jest.spyOn(ShieldUtils, "shieldStatusForRoom").mockResolvedValue(ShieldUtils.E2EStatus.Verified);
act(() => {
MatrixClientPeg.get()!.emit(
CryptoEvent.UserTrustStatusChanged,
"@alice:example.org",
new UserVerificationStatus(true, true, true, false),
);
});
await waitFor(() => expect(getByLabelText(document.body, "Verified")).toBeInTheDocument());

// An unverified device is added
jest.spyOn(ShieldUtils, "shieldStatusForRoom").mockResolvedValue(ShieldUtils.E2EStatus.Warning);
act(() => {
MatrixClientPeg.get()!.emit(CryptoEvent.DevicesUpdated, ["@alice:example.org"], false);
});
await waitFor(() => expect(getByLabelText(document.body, "Untrusted")).toBeInTheDocument());
});
});

it("renders additionalButtons", async () => {
Expand Down

0 comments on commit ed97951

Please sign in to comment.