Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 62cd0f1

Browse files
authored
Use the room avatar as a placeholder in calls (#10231)
* Use the room avatar as a placeholder in calls Rather than the image for the user we're in a call with. This makes it work correctly with virtual rooms easily since we'll get the avatar for the correct room. * Prettier * TS strict errors * More TS strict fixes * More strict TS * Prettier * Even more TS strict * more stricter
1 parent c22971e commit 62cd0f1

File tree

3 files changed

+102
-8
lines changed

3 files changed

+102
-8
lines changed

src/components/views/voip/LegacyCallView.tsx

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,8 @@ export default class LegacyCallView extends React.Component<IProps, IState> {
430430
const { pipMode, call, onResize } = this.props;
431431
const { isLocalOnHold, isRemoteOnHold, sidebarShown, primaryFeed, secondaryFeed, sidebarFeeds } = this.state;
432432

433-
const callRoom = MatrixClientPeg.get().getRoom(call.roomId) ?? undefined;
433+
const callRoomId = LegacyCallHandler.instance.roomIdForCall(call);
434+
const callRoom = (callRoomId ? MatrixClientPeg.get().getRoom(callRoomId) : undefined) ?? undefined;
434435
const avatarSize = pipMode ? 76 : 160;
435436
const transfereeCall = LegacyCallHandler.instance.getTransfereeForCallId(call.callId);
436437
const isOnHold = isLocalOnHold || isRemoteOnHold;
@@ -527,23 +528,44 @@ export default class LegacyCallView extends React.Component<IProps, IState> {
527528
</div>
528529
);
529530
} else if (pipMode) {
531+
// We've already checked that we have feeds so we cast away the optional when passing the feed
530532
return (
531533
<div className="mx_LegacyCallView_content" onMouseMove={this.onMouseMove}>
532-
<VideoFeed feed={primaryFeed} call={call} pipMode={pipMode} onResize={onResize} primary={true} />
534+
<VideoFeed
535+
feed={primaryFeed as CallFeed}
536+
call={call}
537+
pipMode={pipMode}
538+
onResize={onResize}
539+
primary={true}
540+
/>
533541
</div>
534542
);
535543
} else if (secondaryFeed) {
536544
return (
537545
<div className="mx_LegacyCallView_content" onMouseMove={this.onMouseMove}>
538-
<VideoFeed feed={primaryFeed} call={call} pipMode={pipMode} onResize={onResize} primary={true} />
546+
<VideoFeed
547+
feed={primaryFeed as CallFeed}
548+
call={call}
549+
pipMode={pipMode}
550+
onResize={onResize}
551+
primary={true}
552+
/>
539553
{secondaryFeedElement}
540554
</div>
541555
);
542556
} else {
543557
return (
544558
<div className="mx_LegacyCallView_content" onMouseMove={this.onMouseMove}>
545-
<VideoFeed feed={primaryFeed} call={call} pipMode={pipMode} onResize={onResize} primary={true} />
546-
{sidebarShown && <LegacyCallViewSidebar feeds={sidebarFeeds} call={call} pipMode={pipMode} />}
559+
<VideoFeed
560+
feed={primaryFeed as CallFeed}
561+
call={call}
562+
pipMode={pipMode}
563+
onResize={onResize}
564+
primary={true}
565+
/>
566+
{sidebarShown && (
567+
<LegacyCallViewSidebar feeds={sidebarFeeds} call={call} pipMode={Boolean(pipMode)} />
568+
)}
547569
</div>
548570
);
549571
}

src/components/views/voip/VideoFeed.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ import { logger } from "matrix-js-sdk/src/logger";
2323
import { SDPStreamMetadataPurpose } from "matrix-js-sdk/src/webrtc/callEventTypes";
2424

2525
import SettingsStore from "../../../settings/SettingsStore";
26-
import MemberAvatar from "../avatars/MemberAvatar";
26+
import LegacyCallHandler from "../../../LegacyCallHandler";
27+
import { MatrixClientPeg } from "../../../MatrixClientPeg";
28+
import RoomAvatar from "../avatars/RoomAvatar";
2729

2830
interface IProps {
2931
call: MatrixCall;
@@ -197,15 +199,16 @@ export default class VideoFeed extends React.PureComponent<IProps, IState> {
197199

198200
let content;
199201
if (this.state.videoMuted) {
200-
const member = this.props.feed.getMember();
202+
const callRoomId = LegacyCallHandler.instance.roomIdForCall(this.props.call);
203+
const callRoom = (callRoomId ? MatrixClientPeg.get().getRoom(callRoomId) : undefined) ?? undefined;
201204

202205
let avatarSize;
203206
if (pipMode && primary) avatarSize = 76;
204207
else if (pipMode && !primary) avatarSize = 16;
205208
else if (!pipMode && primary) avatarSize = 160;
206209
else; // TBD
207210

208-
content = <MemberAvatar member={member} height={avatarSize} width={avatarSize} />;
211+
content = <RoomAvatar room={callRoom} height={avatarSize} width={avatarSize} />;
209212
} else {
210213
const videoClasses = classnames("mx_VideoFeed_video", {
211214
mx_VideoFeed_video_mirror:
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
Copyright 2023 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
import React from "react";
18+
import { render, screen } from "@testing-library/react";
19+
import { CallFeed } from "matrix-js-sdk/src/webrtc/callFeed";
20+
import { MatrixCall } from "matrix-js-sdk/src/webrtc/call";
21+
import { MatrixClient } from "matrix-js-sdk/src/client";
22+
import { Room } from "matrix-js-sdk/src/models/room";
23+
24+
import * as AvatarModule from "../../../../src/Avatar";
25+
import VideoFeed from "../../../../src/components/views/voip/VideoFeed";
26+
import { stubClient, useMockedCalls } from "../../../test-utils";
27+
import LegacyCallHandler from "../../../../src/LegacyCallHandler";
28+
import DMRoomMap from "../../../../src/utils/DMRoomMap";
29+
30+
const FAKE_AVATAR_URL = "http://fakeurl.dummy/fake.png";
31+
32+
describe("VideoFeed", () => {
33+
useMockedCalls();
34+
35+
let client: MatrixClient;
36+
37+
beforeAll(() => {
38+
client = stubClient();
39+
(AvatarModule as any).avatarUrlForRoom = jest.fn().mockReturnValue(FAKE_AVATAR_URL);
40+
41+
const dmRoomMap = new DMRoomMap(client);
42+
jest.spyOn(dmRoomMap, "getUserIdForRoomId");
43+
jest.spyOn(DMRoomMap, "shared").mockReturnValue(dmRoomMap);
44+
});
45+
46+
afterAll(() => {
47+
jest.restoreAllMocks();
48+
});
49+
50+
it("Displays the room avatar when no video is available", () => {
51+
window.mxLegacyCallHandler = {
52+
roomIdForCall: jest.fn().mockReturnValue("!this:room.here"),
53+
} as unknown as LegacyCallHandler;
54+
55+
const mockCall = {
56+
room: new Room("!room:example.com", client, client.getSafeUserId()),
57+
};
58+
59+
const feed = {
60+
isAudioMuted: jest.fn().mockReturnValue(false),
61+
isVideoMuted: jest.fn().mockReturnValue(true),
62+
addListener: jest.fn(),
63+
removeListener: jest.fn(),
64+
};
65+
render(<VideoFeed feed={feed as unknown as CallFeed} call={mockCall as unknown as MatrixCall} />);
66+
const avatarImg = screen.getByRole("img");
67+
expect(avatarImg).toHaveAttribute("src", FAKE_AVATAR_URL);
68+
});
69+
});

0 commit comments

Comments
 (0)