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:
Will Hunt
2024-12-19 15:54:28 +00:00
committed by GitHub
parent 7d00f85abc
commit abf2ecd521
28 changed files with 1835 additions and 1184 deletions

View File

@@ -7,44 +7,18 @@ Please see LICENSE in the repository root for full details.
import { render } from "@testing-library/react";
import { expect, test, afterEach } from "vitest";
import { TooltipProvider } from "@vector-im/compound-web";
import { act, type ReactNode } from "react";
import { act } from "react";
import {
MockRoom,
MockRTCSession,
TestReactionsWrapper,
} from "../utils/testReactions";
import { showReactions } from "../settings/settings";
import { ReactionsOverlay } from "./ReactionsOverlay";
import { ReactionSet } from "../reactions";
const memberUserIdAlice = "@alice:example.org";
const memberUserIdBob = "@bob:example.org";
const memberUserIdCharlie = "@charlie:example.org";
const memberEventAlice = "$membership-alice:example.org";
const memberEventBob = "$membership-bob:example.org";
const memberEventCharlie = "$membership-charlie:example.org";
const membership: Record<string, string> = {
[memberEventAlice]: memberUserIdAlice,
[memberEventBob]: memberUserIdBob,
[memberEventCharlie]: memberUserIdCharlie,
};
function TestComponent({
rtcSession,
}: {
rtcSession: MockRTCSession;
}): ReactNode {
return (
<TooltipProvider>
<TestReactionsWrapper rtcSession={rtcSession}>
<ReactionsOverlay />
</TestReactionsWrapper>
</TooltipProvider>
);
}
import {
local,
alice,
aliceRtcMember,
bobRtcMember,
} from "../utils/test-fixtures";
import { getBasicCallViewModelEnvironment } from "../utils/test-viewmodel";
afterEach(() => {
showReactions.setValue(showReactions.defaultValue);
@@ -52,22 +26,26 @@ afterEach(() => {
test("defaults to showing no reactions", () => {
showReactions.setValue(true);
const rtcSession = new MockRTCSession(
new MockRoom(memberUserIdAlice),
membership,
);
const { container } = render(<TestComponent rtcSession={rtcSession} />);
const { vm } = getBasicCallViewModelEnvironment([local, alice]);
const { container } = render(<ReactionsOverlay vm={vm} />);
expect(container.getElementsByTagName("span")).toHaveLength(0);
});
test("shows a reaction when sent", () => {
showReactions.setValue(true);
const { vm, reactionsSubject$ } = getBasicCallViewModelEnvironment([
local,
alice,
]);
const { getByRole } = render(<ReactionsOverlay vm={vm} />);
const reaction = ReactionSet[0];
const room = new MockRoom(memberUserIdAlice);
const rtcSession = new MockRTCSession(room, membership);
const { getByRole } = render(<TestComponent rtcSession={rtcSession} />);
act(() => {
room.testSendReaction(memberEventAlice, reaction, membership);
reactionsSubject$.next({
[aliceRtcMember.deviceId]: {
reactionOption: reaction,
expireAfter: new Date(0),
},
});
});
const span = getByRole("presentation");
expect(getByRole("presentation")).toBeTruthy();
@@ -77,29 +55,45 @@ test("shows a reaction when sent", () => {
test("shows two of the same reaction when sent", () => {
showReactions.setValue(true);
const reaction = ReactionSet[0];
const room = new MockRoom(memberUserIdAlice);
const rtcSession = new MockRTCSession(room, membership);
const { getAllByRole } = render(<TestComponent rtcSession={rtcSession} />);
const { vm, reactionsSubject$ } = getBasicCallViewModelEnvironment([
local,
alice,
]);
const { getAllByRole } = render(<ReactionsOverlay vm={vm} />);
act(() => {
room.testSendReaction(memberEventAlice, reaction, membership);
});
act(() => {
room.testSendReaction(memberEventBob, reaction, membership);
reactionsSubject$.next({
[aliceRtcMember.deviceId]: {
reactionOption: reaction,
expireAfter: new Date(0),
},
[bobRtcMember.deviceId]: {
reactionOption: reaction,
expireAfter: new Date(0),
},
});
});
expect(getAllByRole("presentation")).toHaveLength(2);
});
test("shows two different reactions when sent", () => {
showReactions.setValue(true);
const room = new MockRoom(memberUserIdAlice);
const rtcSession = new MockRTCSession(room, membership);
const [reactionA, reactionB] = ReactionSet;
const { getAllByRole } = render(<TestComponent rtcSession={rtcSession} />);
const { vm, reactionsSubject$ } = getBasicCallViewModelEnvironment([
local,
alice,
]);
const { getAllByRole } = render(<ReactionsOverlay vm={vm} />);
act(() => {
room.testSendReaction(memberEventAlice, reactionA, membership);
});
act(() => {
room.testSendReaction(memberEventBob, reactionB, membership);
reactionsSubject$.next({
[aliceRtcMember.deviceId]: {
reactionOption: reactionA,
expireAfter: new Date(0),
},
[bobRtcMember.deviceId]: {
reactionOption: reactionB,
expireAfter: new Date(0),
},
});
});
const [reactionElementA, reactionElementB] = getAllByRole("presentation");
expect(reactionElementA.innerHTML).toEqual(reactionA.emoji);
@@ -109,11 +103,18 @@ test("shows two different reactions when sent", () => {
test("hides reactions when reaction animations are disabled", () => {
showReactions.setValue(false);
const reaction = ReactionSet[0];
const room = new MockRoom(memberUserIdAlice);
const rtcSession = new MockRTCSession(room, membership);
const { vm, reactionsSubject$ } = getBasicCallViewModelEnvironment([
local,
alice,
]);
const { container } = render(<ReactionsOverlay vm={vm} />);
act(() => {
room.testSendReaction(memberEventAlice, reaction, membership);
reactionsSubject$.next({
[aliceRtcMember.deviceId]: {
reactionOption: reaction,
expireAfter: new Date(0),
},
});
});
const { container } = render(<TestComponent rtcSession={rtcSession} />);
expect(container.getElementsByTagName("span")).toHaveLength(0);
});