Skip to content

Commit

Permalink
type fixups
Browse files Browse the repository at this point in the history
  • Loading branch information
toger5 committed Feb 21, 2025
1 parent 3407610 commit e648b43
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 47 deletions.
21 changes: 14 additions & 7 deletions src/reactions/ReactionsReader.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ afterEach(() => {
});

test("handles a hand raised reaction", () => {
const { rtcSession } = getBasicRTCSession([local, alice]);
const { rtcSession, matrixRoom } = getBasicRTCSession([local, alice]);
const reactionEventId = "$my_event_id:example.org";
const localTimestamp = new Date();
withTestScheduler(({ schedule, expectObservable }) => {
renderHook(() => {
const { raisedHands$ } = new ReactionsReader(
rtcSession as unknown as MatrixRTCSession,
matrixRoom,
);
schedule("ab", {
a: () => {},
Expand Down Expand Up @@ -80,13 +81,14 @@ test("handles a hand raised reaction", () => {
});

test("handles a redaction", () => {
const { rtcSession } = getBasicRTCSession([local, alice]);
const { rtcSession, matrixRoom } = getBasicRTCSession([local, alice]);
const reactionEventId = "$my_event_id:example.org";
const localTimestamp = new Date();
withTestScheduler(({ schedule, expectObservable }) => {
renderHook(() => {
const { raisedHands$ } = new ReactionsReader(
rtcSession as unknown as MatrixRTCSession,
matrixRoom,
);
schedule("abc", {
a: () => {},
Expand Down Expand Up @@ -143,13 +145,14 @@ test("handles a redaction", () => {
});

test("handles waiting for event decryption", () => {
const { rtcSession } = getBasicRTCSession([local, alice]);
const { rtcSession, matrixRoom } = getBasicRTCSession([local, alice]);
const reactionEventId = "$my_event_id:example.org";
const localTimestamp = new Date();
withTestScheduler(({ schedule, expectObservable }) => {
renderHook(() => {
const { raisedHands$ } = new ReactionsReader(
rtcSession as unknown as MatrixRTCSession,
matrixRoom,
);
schedule("abc", {
a: () => {},
Expand Down Expand Up @@ -212,13 +215,14 @@ test("handles waiting for event decryption", () => {
});

test("hands rejecting events without a proper membership", () => {
const { rtcSession } = getBasicRTCSession([local, alice]);
const { rtcSession, matrixRoom } = getBasicRTCSession([local, alice]);
const reactionEventId = "$my_event_id:example.org";
const localTimestamp = new Date();
withTestScheduler(({ schedule, expectObservable }) => {
renderHook(() => {
const { raisedHands$ } = new ReactionsReader(
rtcSession as unknown as MatrixRTCSession,
matrixRoom,
);
schedule("ab", {
a: () => {},
Expand Down Expand Up @@ -253,7 +257,7 @@ test("hands rejecting events without a proper membership", () => {
});

test("handles a reaction", () => {
const { rtcSession } = getBasicRTCSession([local, alice]);
const { rtcSession, matrixRoom } = getBasicRTCSession([local, alice]);
const reactionEventId = "$my_event_id:example.org";
const reaction = ReactionSet[1];

Expand All @@ -264,6 +268,7 @@ test("handles a reaction", () => {
renderHook(() => {
const { reactions$ } = new ReactionsReader(
rtcSession as unknown as MatrixRTCSession,
matrixRoom,
);
schedule(`abc`, {
a: () => {},
Expand Down Expand Up @@ -312,7 +317,7 @@ test("handles a reaction", () => {
});

test("ignores bad reaction events", () => {
const { rtcSession } = getBasicRTCSession([local, alice]);
const { rtcSession, matrixRoom } = getBasicRTCSession([local, alice]);
const reactionEventId = "$my_event_id:example.org";
const reaction = ReactionSet[1];

Expand All @@ -322,6 +327,7 @@ test("ignores bad reaction events", () => {
renderHook(() => {
const { reactions$ } = new ReactionsReader(
rtcSession as unknown as MatrixRTCSession,
matrixRoom,
);
schedule("ab", {
a: () => {},
Expand Down Expand Up @@ -434,7 +440,7 @@ test("ignores bad reaction events", () => {
});

test("that reactions cannot be spammed", () => {
const { rtcSession } = getBasicRTCSession([local, alice]);
const { rtcSession, matrixRoom } = getBasicRTCSession([local, alice]);
const reactionEventId = "$my_event_id:example.org";
const reactionA = ReactionSet[1];
const reactionB = ReactionSet[2];
Expand All @@ -446,6 +452,7 @@ test("that reactions cannot be spammed", () => {
renderHook(() => {
const { reactions$ } = new ReactionsReader(
rtcSession as unknown as MatrixRTCSession,
matrixRoom,
);
schedule("abcd", {
a: () => {},
Expand Down
52 changes: 19 additions & 33 deletions src/reactions/ReactionsReader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import {
type MatrixRTCSession,
} from "matrix-js-sdk/src/matrixrtc";
import { logger } from "matrix-js-sdk/src/logger";
import { type MatrixEvent, MatrixEventEvent } from "matrix-js-sdk/src/matrix";
import {
type MatrixEvent,
MatrixEventEvent,
type Room,
} from "matrix-js-sdk/src/matrix";
import { type ReactionEventContent } from "matrix-js-sdk/src/types";
import {
RelationType,
Expand Down Expand Up @@ -56,7 +60,10 @@ export class ReactionsReader {

private readonly reactionsSub: Subscription;

public constructor(private readonly rtcSession: MatrixRTCSession) {
public constructor(
private readonly rtcSession: MatrixRTCSession,
private readonly room: Room,
) {
// Hide reactions after a given time.
this.reactionsSub = this.reactionsSubject$
.pipe(delay(REACTION_ACTIVE_TIME_MS))
Expand All @@ -71,22 +78,13 @@ export class ReactionsReader {
this.reactionsSubject$.next(nextEntries);
});

this.rtcSession.room.on(MatrixRoomEvent.Timeline, this.handleReactionEvent);
this.rtcSession.room.on(
MatrixRoomEvent.Redaction,
this.handleReactionEvent,
);
this.rtcSession.room.client.on(
MatrixEventEvent.Decrypted,
this.handleReactionEvent,
);
this.room.on(MatrixRoomEvent.Timeline, this.handleReactionEvent);
this.room.on(MatrixRoomEvent.Redaction, this.handleReactionEvent);
this.room.client.on(MatrixEventEvent.Decrypted, this.handleReactionEvent);

// We listen for a local echo to get the real event ID, as timeline events
// may still be sending.
this.rtcSession.room.on(
MatrixRoomEvent.LocalEchoUpdated,
this.handleReactionEvent,
);
this.room.on(MatrixRoomEvent.LocalEchoUpdated, this.handleReactionEvent);

rtcSession.on(
MatrixRTCSessionEvent.MembershipsChanged,
Expand All @@ -108,7 +106,7 @@ export class ReactionsReader {
membershipEventId: string,
expectedSender: string,
): MatrixEvent | undefined {
const relations = this.rtcSession.room.relations.getChildEventsForEvent(
const relations = this.room.relations.getChildEventsForEvent(
membershipEventId,
RelationType.Annotation,
EventType.Reaction,
Expand Down Expand Up @@ -198,7 +196,7 @@ export class ReactionsReader {
* @param event The incoming matrix event, which may or may not be decrypted.
*/
private handleReactionEvent = (event: MatrixEvent): void => {
const room = this.rtcSession.room;
const room = this.room;
// Decrypted events might come from a different room
if (event.getRoomId() !== room.roomId) return;
// Skip any events that are still sending.
Expand Down Expand Up @@ -318,22 +316,10 @@ export class ReactionsReader {
MatrixRTCSessionEvent.MembershipsChanged,
this.onMembershipsChanged,
);
this.rtcSession.room.off(
MatrixRoomEvent.Timeline,
this.handleReactionEvent,
);
this.rtcSession.room.off(
MatrixRoomEvent.Redaction,
this.handleReactionEvent,
);
this.rtcSession.room.client.off(
MatrixEventEvent.Decrypted,
this.handleReactionEvent,
);
this.rtcSession.room.off(
MatrixRoomEvent.LocalEchoUpdated,
this.handleReactionEvent,
);
this.room.off(MatrixRoomEvent.Timeline, this.handleReactionEvent);
this.room.off(MatrixRoomEvent.Redaction, this.handleReactionEvent);
this.room.client.off(MatrixEventEvent.Decrypted, this.handleReactionEvent);
this.room.off(MatrixRoomEvent.LocalEchoUpdated, this.handleReactionEvent);
this.reactionsSub.unsubscribe();
}
}
5 changes: 3 additions & 2 deletions src/reactions/useReactionsSender.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/

import { EventType, RelationType } from "matrix-js-sdk/src/matrix";
import { EventType, RelationType, type Room } from "matrix-js-sdk/src/matrix";
import {
createContext,
useContext,
Expand Down Expand Up @@ -47,17 +47,18 @@ export const useReactionsSender = (): ReactionsSenderContextType => {
export const ReactionsSenderProvider = ({
children,
rtcSession,
room,
vm,
}: {
children: ReactNode;
rtcSession: MatrixRTCSession;
room: Room;
vm: CallViewModel;
}): JSX.Element => {
const memberships = useMatrixRTCSessionMemberships(rtcSession);
const clientState = useClientState();
const supportsReactions =
clientState?.state === "valid" && clientState.supportedFeatures.reactions;
const room = rtcSession.room;
const myUserId = room.client.getUserId();

Check failure on line 62 in src/reactions/useReactionsSender.tsx

View workflow job for this annotation

GitHub Actions / Run vitest tests

src/button/ReactionToggleButton.test.tsx > Can open menu

TypeError: Cannot read properties of undefined (reading 'client') ❯ ReactionsSenderProvider src/reactions/useReactionsSender.tsx:62:25 ❯ renderWithHooks node_modules/react-dom/cjs/react-dom.development.js:15486:18 ❯ mountIndeterminateComponent node_modules/react-dom/cjs/react-dom.development.js:20103:13 ❯ beginWork node_modules/react-dom/cjs/react-dom.development.js:21626:16 ❯ beginWork$1 node_modules/react-dom/cjs/react-dom.development.js:27465:14 ❯ performUnitOfWork node_modules/react-dom/cjs/react-dom.development.js:26599:12 ❯ workLoopSync node_modules/react-dom/cjs/react-dom.development.js:26505:5 ❯ renderRootSync node_modules/react-dom/cjs/react-dom.development.js:26473:7 ❯ recoverFromConcurrentError node_modules/react-dom/cjs/react-dom.development.js:25889:20 ❯ performConcurrentWorkOnRoot node_modules/react-dom/cjs/react-dom.development.js:25789:22

Check failure on line 62 in src/reactions/useReactionsSender.tsx

View workflow job for this annotation

GitHub Actions / Run vitest tests

src/button/ReactionToggleButton.test.tsx > Can raise hand

TypeError: Cannot read properties of undefined (reading 'client') ❯ ReactionsSenderProvider src/reactions/useReactionsSender.tsx:62:25 ❯ renderWithHooks node_modules/react-dom/cjs/react-dom.development.js:15486:18 ❯ mountIndeterminateComponent node_modules/react-dom/cjs/react-dom.development.js:20103:13 ❯ beginWork node_modules/react-dom/cjs/react-dom.development.js:21626:16 ❯ beginWork$1 node_modules/react-dom/cjs/react-dom.development.js:27465:14 ❯ performUnitOfWork node_modules/react-dom/cjs/react-dom.development.js:26599:12 ❯ workLoopSync node_modules/react-dom/cjs/react-dom.development.js:26505:5 ❯ renderRootSync node_modules/react-dom/cjs/react-dom.development.js:26473:7 ❯ recoverFromConcurrentError node_modules/react-dom/cjs/react-dom.development.js:25889:20 ❯ performConcurrentWorkOnRoot node_modules/react-dom/cjs/react-dom.development.js:25789:22

Check failure on line 62 in src/reactions/useReactionsSender.tsx

View workflow job for this annotation

GitHub Actions / Run vitest tests

src/button/ReactionToggleButton.test.tsx > Can lower hand

TypeError: Cannot read properties of undefined (reading 'client') ❯ ReactionsSenderProvider src/reactions/useReactionsSender.tsx:62:25 ❯ renderWithHooks node_modules/react-dom/cjs/react-dom.development.js:15486:18 ❯ mountIndeterminateComponent node_modules/react-dom/cjs/react-dom.development.js:20103:13 ❯ beginWork node_modules/react-dom/cjs/react-dom.development.js:21626:16 ❯ beginWork$1 node_modules/react-dom/cjs/react-dom.development.js:27465:14 ❯ performUnitOfWork node_modules/react-dom/cjs/react-dom.development.js:26599:12 ❯ workLoopSync node_modules/react-dom/cjs/react-dom.development.js:26505:5 ❯ renderRootSync node_modules/react-dom/cjs/react-dom.development.js:26473:7 ❯ recoverFromConcurrentError node_modules/react-dom/cjs/react-dom.development.js:25889:20 ❯ performConcurrentWorkOnRoot node_modules/react-dom/cjs/react-dom.development.js:25789:22

Check failure on line 62 in src/reactions/useReactionsSender.tsx

View workflow job for this annotation

GitHub Actions / Run vitest tests

src/button/ReactionToggleButton.test.tsx > Can react with emoji

TypeError: Cannot read properties of undefined (reading 'client') ❯ ReactionsSenderProvider src/reactions/useReactionsSender.tsx:62:25 ❯ renderWithHooks node_modules/react-dom/cjs/react-dom.development.js:15486:18 ❯ mountIndeterminateComponent node_modules/react-dom/cjs/react-dom.development.js:20103:13 ❯ beginWork node_modules/react-dom/cjs/react-dom.development.js:21626:16 ❯ beginWork$1 node_modules/react-dom/cjs/react-dom.development.js:27465:14 ❯ performUnitOfWork node_modules/react-dom/cjs/react-dom.development.js:26599:12 ❯ workLoopSync node_modules/react-dom/cjs/react-dom.development.js:26505:5 ❯ renderRootSync node_modules/react-dom/cjs/react-dom.development.js:26473:7 ❯ recoverFromConcurrentError node_modules/react-dom/cjs/react-dom.development.js:25889:20 ❯ performConcurrentWorkOnRoot node_modules/react-dom/cjs/react-dom.development.js:25789:22

Check failure on line 62 in src/reactions/useReactionsSender.tsx

View workflow job for this annotation

GitHub Actions / Run vitest tests

src/button/ReactionToggleButton.test.tsx > Can fully expand emoji picker

TypeError: Cannot read properties of undefined (reading 'client') ❯ ReactionsSenderProvider src/reactions/useReactionsSender.tsx:62:25 ❯ renderWithHooks node_modules/react-dom/cjs/react-dom.development.js:15486:18 ❯ mountIndeterminateComponent node_modules/react-dom/cjs/react-dom.development.js:20103:13 ❯ beginWork node_modules/react-dom/cjs/react-dom.development.js:21626:16 ❯ beginWork$1 node_modules/react-dom/cjs/react-dom.development.js:27465:14 ❯ performUnitOfWork node_modules/react-dom/cjs/react-dom.development.js:26599:12 ❯ workLoopSync node_modules/react-dom/cjs/react-dom.development.js:26505:5 ❯ renderRootSync node_modules/react-dom/cjs/react-dom.development.js:26473:7 ❯ recoverFromConcurrentError node_modules/react-dom/cjs/react-dom.development.js:25889:20 ❯ performConcurrentWorkOnRoot node_modules/react-dom/cjs/react-dom.development.js:25789:22

Check failure on line 62 in src/reactions/useReactionsSender.tsx

View workflow job for this annotation

GitHub Actions / Run vitest tests

src/button/ReactionToggleButton.test.tsx > Can close reaction dialog

TypeError: Cannot read properties of undefined (reading 'client') ❯ ReactionsSenderProvider src/reactions/useReactionsSender.tsx:62:25 ❯ renderWithHooks node_modules/react-dom/cjs/react-dom.development.js:15486:18 ❯ mountIndeterminateComponent node_modules/react-dom/cjs/react-dom.development.js:20103:13 ❯ beginWork node_modules/react-dom/cjs/react-dom.development.js:21626:16 ❯ beginWork$1 node_modules/react-dom/cjs/react-dom.development.js:27465:14 ❯ performUnitOfWork node_modules/react-dom/cjs/react-dom.development.js:26599:12 ❯ workLoopSync node_modules/react-dom/cjs/react-dom.development.js:26505:5 ❯ renderRootSync node_modules/react-dom/cjs/react-dom.development.js:26473:7 ❯ recoverFromConcurrentError node_modules/react-dom/cjs/react-dom.development.js:25889:20 ❯ performConcurrentWorkOnRoot node_modules/react-dom/cjs/react-dom.development.js:25789:22

Check failure on line 62 in src/reactions/useReactionsSender.tsx

View workflow job for this annotation

GitHub Actions / Run vitest tests

src/tile/GridTile.test.tsx > GridTile is accessible

TypeError: Cannot read properties of undefined (reading 'client') ❯ ReactionsSenderProvider src/reactions/useReactionsSender.tsx:62:25 ❯ renderWithHooks node_modules/react-dom/cjs/react-dom.development.js:15486:18 ❯ mountIndeterminateComponent node_modules/react-dom/cjs/react-dom.development.js:20103:13 ❯ beginWork node_modules/react-dom/cjs/react-dom.development.js:21626:16 ❯ beginWork$1 node_modules/react-dom/cjs/react-dom.development.js:27465:14 ❯ performUnitOfWork node_modules/react-dom/cjs/react-dom.development.js:26599:12 ❯ workLoopSync node_modules/react-dom/cjs/react-dom.development.js:26505:5 ❯ renderRootSync node_modules/react-dom/cjs/react-dom.development.js:26473:7 ❯ recoverFromConcurrentError node_modules/react-dom/cjs/react-dom.development.js:25889:20 ❯ performConcurrentWorkOnRoot node_modules/react-dom/cjs/react-dom.development.js:25789:22
const myDeviceId = room.client.getDeviceId();
const myMembershipIdentifier = `${myUserId}:${myDeviceId}`;
Expand Down
20 changes: 17 additions & 3 deletions src/room/InCallView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,11 @@ export const ActiveCall: FC<ActiveCallProps> = (props) => {

useEffect(() => {
if (livekitRoom !== undefined) {
const reactionsReader = new ReactionsReader(props.rtcSession);
const reactionsReader = new ReactionsReader(
props.rtcSession,
// TODO pass the room through the props instead of !
props.client.getRoom(props.rtcSession.room.roomId)!,
);
const vm = new CallViewModel(
props.rtcSession,
livekitRoom,
Expand All @@ -147,13 +151,23 @@ export const ActiveCall: FC<ActiveCallProps> = (props) => {
reactionsReader.destroy();
};
}
}, [props.rtcSession, livekitRoom, props.e2eeSystem, connStateObservable$]);
}, [
props.rtcSession,
livekitRoom,
props.e2eeSystem,
connStateObservable$,
props.client,
]);

if (livekitRoom === undefined || vm === null) return null;

return (
<RoomContext.Provider value={livekitRoom}>
<ReactionsSenderProvider vm={vm} rtcSession={props.rtcSession}>
<ReactionsSenderProvider
vm={vm}
rtcSession={props.rtcSession}
room={props.client.getRoom(props.rtcSession.room.roomId)!}
>
<InCallView
{...props}
vm={vm}
Expand Down
3 changes: 2 additions & 1 deletion src/rtcSessionHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
isLivekitFocusConfig,
} from "matrix-js-sdk/src/matrixrtc/LivekitFocus";
import { AutoDiscovery } from "matrix-js-sdk/src/autodiscovery";
import { type Room } from "matrix-js-sdk/src/matrix";

import { PosthogAnalytics } from "./analytics/PosthogAnalytics";
import { Config } from "./config/Config";
Expand Down Expand Up @@ -45,7 +46,7 @@ async function makePreferredLivekitFoci(
}

// Prioritize the .well-known/matrix/client, if available, over the configured SFU
const domain = rtcSession.room.client.getDomain();
const domain = (rtcSession.room as Room).client.getDomain();
if (domain) {
// we use AutoDiscovery instead of relying on the MatrixClient having already
// been fully configured and started
Expand Down
5 changes: 4 additions & 1 deletion src/utils/test-viewmodel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Please see LICENSE in the repository root for full details.

import { ConnectionState } from "livekit-client";
import { type MatrixClient } from "matrix-js-sdk/src/client";
import { type RoomMember } from "matrix-js-sdk/src/matrix";
import { type Room, type RoomMember } from "matrix-js-sdk/src/matrix";
import {
type CallMembership,
type MatrixRTCSession,
Expand All @@ -33,6 +33,7 @@ export function getBasicRTCSession(
initialRemoteRtcMemberships: CallMembership[] = [aliceRtcMember],
): {
rtcSession: MockRTCSession;
matrixRoom: Room;
remoteRtcMemberships$: BehaviorSubject<CallMembership[]>;
} {
const matrixRoomId = "!myRoomId:example.com";
Expand Down Expand Up @@ -93,11 +94,13 @@ export function getBasicRTCSession(

const rtcSession = new MockRTCSession(
matrixRoom,

localRtcMember,
).withMemberships(remoteRtcMemberships$);

return {
rtcSession,
matrixRoom,
remoteRtcMemberships$,
};
}
Expand Down

0 comments on commit e648b43

Please sign in to comment.