Refactor reactions / hand raised to use rxjs and start ordering tiles based on hand raised. (#2885)
* Add support for using CallViewModel for reactions sounds. * Drop setting * Convert reaction sounds to call view model / rxjs * Use call view model for hand raised reactions * Support raising reactions for matrix rtc members. * Tie up last bits of useReactions * linting * Update calleventaudiorenderer * Update reaction audio renderer * more test bits * All the test bits and pieces * More refactors * Refactor reactions into a sender and receiver. * Fixup reaction toggle button * Adapt reactions test * Tests all pass. * lint * fix a couple of bugs * remove unused helper file * lint * finnish notation * Add tests for useReactionsReader * remove mistaken vitest file * fix * filter * invert * fixup tests with fake timers * Port useReactionsReader hook to ReactionsReader class. * lint * exclude some files from coverage * Add screen share sound effect. * cancel sub on destroy * tidy tidy
This commit is contained in:
@@ -5,47 +5,47 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { render } from "@testing-library/react";
|
||||
import { act, render } from "@testing-library/react";
|
||||
import { expect, test } from "vitest";
|
||||
import { TooltipProvider } from "@vector-im/compound-web";
|
||||
import { userEvent } from "@testing-library/user-event";
|
||||
import { type ReactNode } from "react";
|
||||
import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
|
||||
|
||||
import {
|
||||
MockRoom,
|
||||
MockRTCSession,
|
||||
TestReactionsWrapper,
|
||||
} from "../utils/testReactions";
|
||||
import { ReactionToggleButton } from "./ReactionToggleButton";
|
||||
import { ElementCallReactionEventType } from "../reactions";
|
||||
import { type CallViewModel } from "../state/CallViewModel";
|
||||
import { getBasicCallViewModelEnvironment } from "../utils/test-viewmodel";
|
||||
import { alice, local, localRtcMember } from "../utils/test-fixtures";
|
||||
import { type MockRTCSession } from "../utils/test";
|
||||
import { ReactionsSenderProvider } from "../reactions/useReactionsSender";
|
||||
|
||||
const memberUserIdAlice = "@alice:example.org";
|
||||
const memberEventAlice = "$membership-alice:example.org";
|
||||
|
||||
const membership: Record<string, string> = {
|
||||
[memberEventAlice]: memberUserIdAlice,
|
||||
};
|
||||
const localIdent = `${localRtcMember.sender}:${localRtcMember.deviceId}`;
|
||||
|
||||
function TestComponent({
|
||||
rtcSession,
|
||||
vm,
|
||||
}: {
|
||||
rtcSession: MockRTCSession;
|
||||
vm: CallViewModel;
|
||||
}): ReactNode {
|
||||
return (
|
||||
<TooltipProvider>
|
||||
<TestReactionsWrapper rtcSession={rtcSession}>
|
||||
<ReactionToggleButton userId={memberUserIdAlice} />
|
||||
</TestReactionsWrapper>
|
||||
<ReactionsSenderProvider
|
||||
vm={vm}
|
||||
rtcSession={rtcSession as unknown as MatrixRTCSession}
|
||||
>
|
||||
<ReactionToggleButton vm={vm} identifier={localIdent} />
|
||||
</ReactionsSenderProvider>
|
||||
</TooltipProvider>
|
||||
);
|
||||
}
|
||||
|
||||
test("Can open menu", async () => {
|
||||
const user = userEvent.setup();
|
||||
const room = new MockRoom(memberUserIdAlice);
|
||||
const rtcSession = new MockRTCSession(room, membership);
|
||||
const { vm, rtcSession } = getBasicCallViewModelEnvironment([alice]);
|
||||
const { getByLabelText, container } = render(
|
||||
<TestComponent rtcSession={rtcSession} />,
|
||||
<TestComponent vm={vm} rtcSession={rtcSession} />,
|
||||
);
|
||||
await user.click(getByLabelText("common.reactions"));
|
||||
expect(container).toMatchSnapshot();
|
||||
@@ -53,102 +53,120 @@ test("Can open menu", async () => {
|
||||
|
||||
test("Can raise hand", async () => {
|
||||
const user = userEvent.setup();
|
||||
const room = new MockRoom(memberUserIdAlice);
|
||||
const rtcSession = new MockRTCSession(room, membership);
|
||||
const { vm, rtcSession, handRaisedSubject$ } =
|
||||
getBasicCallViewModelEnvironment([local, alice]);
|
||||
const { getByLabelText, container } = render(
|
||||
<TestComponent rtcSession={rtcSession} />,
|
||||
<TestComponent vm={vm} rtcSession={rtcSession} />,
|
||||
);
|
||||
await user.click(getByLabelText("common.reactions"));
|
||||
await user.click(getByLabelText("action.raise_hand"));
|
||||
expect(room.testSentEvents).toEqual([
|
||||
[
|
||||
undefined,
|
||||
"m.reaction",
|
||||
{
|
||||
"m.relates_to": {
|
||||
event_id: memberEventAlice,
|
||||
key: "🖐️",
|
||||
rel_type: "m.annotation",
|
||||
},
|
||||
expect(rtcSession.room.client.sendEvent).toHaveBeenCalledWith(
|
||||
rtcSession.room.roomId,
|
||||
"m.reaction",
|
||||
{
|
||||
"m.relates_to": {
|
||||
event_id: localRtcMember.eventId,
|
||||
key: "🖐️",
|
||||
rel_type: "m.annotation",
|
||||
},
|
||||
],
|
||||
]);
|
||||
},
|
||||
);
|
||||
act(() => {
|
||||
// Mock receiving a reaction.
|
||||
handRaisedSubject$.next({
|
||||
[localIdent]: {
|
||||
time: new Date(),
|
||||
reactionEventId: "",
|
||||
membershipEventId: localRtcMember.eventId!,
|
||||
},
|
||||
});
|
||||
});
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test("Can lower hand", async () => {
|
||||
const reactionEventId = "$my-reaction-event:example.org";
|
||||
const user = userEvent.setup();
|
||||
const room = new MockRoom(memberUserIdAlice);
|
||||
const rtcSession = new MockRTCSession(room, membership);
|
||||
const { vm, rtcSession, handRaisedSubject$ } =
|
||||
getBasicCallViewModelEnvironment([local, alice]);
|
||||
const { getByLabelText, container } = render(
|
||||
<TestComponent rtcSession={rtcSession} />,
|
||||
<TestComponent vm={vm} rtcSession={rtcSession} />,
|
||||
);
|
||||
const reactionEvent = room.testSendHandRaise(memberEventAlice, membership);
|
||||
await user.click(getByLabelText("common.reactions"));
|
||||
await user.click(getByLabelText("action.raise_hand"));
|
||||
act(() => {
|
||||
handRaisedSubject$.next({
|
||||
[localIdent]: {
|
||||
time: new Date(),
|
||||
reactionEventId,
|
||||
membershipEventId: localRtcMember.eventId!,
|
||||
},
|
||||
});
|
||||
});
|
||||
await user.click(getByLabelText("common.reactions"));
|
||||
await user.click(getByLabelText("action.lower_hand"));
|
||||
expect(room.testRedactedEvents).toEqual([[undefined, reactionEvent]]);
|
||||
expect(rtcSession.room.client.redactEvent).toHaveBeenCalledWith(
|
||||
rtcSession.room.roomId,
|
||||
reactionEventId,
|
||||
);
|
||||
act(() => {
|
||||
// Mock receiving a redacted reaction.
|
||||
handRaisedSubject$.next({});
|
||||
});
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test("Can react with emoji", async () => {
|
||||
const user = userEvent.setup();
|
||||
const room = new MockRoom(memberUserIdAlice);
|
||||
const rtcSession = new MockRTCSession(room, membership);
|
||||
const { vm, rtcSession } = getBasicCallViewModelEnvironment([local, alice]);
|
||||
const { getByLabelText, getByText } = render(
|
||||
<TestComponent rtcSession={rtcSession} />,
|
||||
<TestComponent vm={vm} rtcSession={rtcSession} />,
|
||||
);
|
||||
await user.click(getByLabelText("common.reactions"));
|
||||
await user.click(getByText("🐶"));
|
||||
expect(room.testSentEvents).toEqual([
|
||||
[
|
||||
undefined,
|
||||
ElementCallReactionEventType,
|
||||
{
|
||||
"m.relates_to": {
|
||||
event_id: memberEventAlice,
|
||||
rel_type: "m.reference",
|
||||
},
|
||||
name: "dog",
|
||||
emoji: "🐶",
|
||||
expect(rtcSession.room.client.sendEvent).toHaveBeenCalledWith(
|
||||
rtcSession.room.roomId,
|
||||
ElementCallReactionEventType,
|
||||
{
|
||||
"m.relates_to": {
|
||||
event_id: localRtcMember.eventId,
|
||||
rel_type: "m.reference",
|
||||
},
|
||||
],
|
||||
]);
|
||||
name: "dog",
|
||||
emoji: "🐶",
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test("Can fully expand emoji picker", async () => {
|
||||
const user = userEvent.setup();
|
||||
const room = new MockRoom(memberUserIdAlice);
|
||||
const rtcSession = new MockRTCSession(room, membership);
|
||||
const { getByText, container, getByLabelText } = render(
|
||||
<TestComponent rtcSession={rtcSession} />,
|
||||
const { vm, rtcSession } = getBasicCallViewModelEnvironment([local, alice]);
|
||||
const { getByLabelText, container, getByText } = render(
|
||||
<TestComponent vm={vm} rtcSession={rtcSession} />,
|
||||
);
|
||||
await user.click(getByLabelText("common.reactions"));
|
||||
await user.click(getByLabelText("action.show_more"));
|
||||
expect(container).toMatchSnapshot();
|
||||
await user.click(getByText("🦗"));
|
||||
|
||||
expect(room.testSentEvents).toEqual([
|
||||
[
|
||||
undefined,
|
||||
ElementCallReactionEventType,
|
||||
{
|
||||
"m.relates_to": {
|
||||
event_id: memberEventAlice,
|
||||
rel_type: "m.reference",
|
||||
},
|
||||
name: "crickets",
|
||||
emoji: "🦗",
|
||||
expect(rtcSession.room.client.sendEvent).toHaveBeenCalledWith(
|
||||
rtcSession.room.roomId,
|
||||
ElementCallReactionEventType,
|
||||
{
|
||||
"m.relates_to": {
|
||||
event_id: localRtcMember.eventId,
|
||||
rel_type: "m.reference",
|
||||
},
|
||||
],
|
||||
]);
|
||||
name: "crickets",
|
||||
emoji: "🦗",
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test("Can close reaction dialog", async () => {
|
||||
const user = userEvent.setup();
|
||||
const room = new MockRoom(memberUserIdAlice);
|
||||
const rtcSession = new MockRTCSession(room, membership);
|
||||
const { vm, rtcSession } = getBasicCallViewModelEnvironment([local, alice]);
|
||||
const { getByLabelText, container } = render(
|
||||
<TestComponent rtcSession={rtcSession} />,
|
||||
<TestComponent vm={vm} rtcSession={rtcSession} />,
|
||||
);
|
||||
await user.click(getByLabelText("common.reactions"));
|
||||
await user.click(getByLabelText("action.show_more"));
|
||||
|
||||
Reference in New Issue
Block a user