Skip to content

Commit c3608f7

Browse files
committed
feat(voip): hide video button when feature not active on homeserver
1 parent 740d598 commit c3608f7

File tree

3 files changed

+156
-1
lines changed

3 files changed

+156
-1
lines changed

linked-dependencies/matrix-react-sdk/src/components/views/voip/LegacyCallView.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import LegacyCallViewButtons from "./LegacyCallView/LegacyCallViewButtons";
3636
import { ActionPayload } from "../../../dispatcher/payloads";
3737
import { getKeyBindingsManager } from "../../../KeyBindingsManager";
3838
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
39+
import TchapUIFeature from "../../../../../../src/tchap/util/TchapUIFeature"; /** :TCHAP: hide-video-button-on-call-screen */
3940

4041
interface IProps {
4142
// The call for us to display
@@ -348,7 +349,13 @@ export default class LegacyCallView extends React.Component<IProps, IState> {
348349
const { callState, micMuted, vidMuted, screensharing, sidebarShown, secondaryFeed, sidebarFeeds } = this.state;
349350

350351
// If SDPStreamMetadata isn't supported don't show video mute button in voice calls
351-
const vidMuteButtonShown = call.opponentSupportsSDPStreamMetadata() || call.hasLocalUserMediaVideoTrack;
352+
/** :TCHAP: hide-video-button-on-call-screen */
353+
// const vidMuteButtonShown = call.opponentSupportsSDPStreamMetadata() || call.hasLocalUserMediaVideoTrack;
354+
let vidMuteButtonShown = false // hide by default
355+
if (TchapUIFeature.isFeatureActiveForHomeserver("feature_video_call")) {
356+
vidMuteButtonShown = call.opponentSupportsSDPStreamMetadata() || call.hasLocalUserMediaVideoTrack;
357+
};
358+
/** end :TCHAP: */
352359
// Screensharing is possible, if we can send a second stream and
353360
// identify it using SDPStreamMetadata or if we can replace the already
354361
// existing usermedia track by a screensharing track. We also need to be

patches/subtree-modifications.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,11 @@
55
"src/hooks/useUserOnboardingContext.ts",
66
"src/hooks/useUserOnboardingTasks.ts"
77
]
8+
},
9+
"hide-video-button-on-call-screen": {
10+
"issue": "https://github.com/tchapgouv/tchap-web-v4/issues/952",
11+
"files": [
12+
"src/components/views/voip/LegacyCallView.tsx"
13+
]
814
}
915
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import { stubClient } from "matrix-react-sdk/test/test-utils";
2+
import SdkConfig, { ConfigOptions } from "matrix-react-sdk/src/SdkConfig";
3+
import { MatrixClientPeg } from "matrix-react-sdk/src/MatrixClientPeg";
4+
import React from "react";
5+
import { MatrixCall } from "matrix-js-sdk/src/webrtc/call";
6+
import { CallState } from "matrix-js-sdk/src/webrtc/call";
7+
import { fireEvent, render, waitFor } from "@testing-library/react";
8+
import { MatrixClient } from "matrix-js-sdk/src/matrix";
9+
10+
import LegacyCallView from "~matrix-react-sdk/src/components/views/voip/LegacyCallView";
11+
import DMRoomMap from "~matrix-react-sdk/src/utils/DMRoomMap";
12+
13+
describe("LegacyCallView", () => {
14+
const featureName: string = "feature_video_call";
15+
const homeserverName: string = "my.home.server";
16+
const roomId: string = "roomId";
17+
// const fakeCall: MatrixCall = new FakeCall(roomId) as unknown as MatrixCall;
18+
let fakeCall: MatrixCall;
19+
20+
beforeAll(() => {
21+
SdkConfig.reset(); // in case other tests didn't clean up
22+
});
23+
24+
beforeEach(() => {
25+
stubClient();
26+
MatrixClientPeg.getHomeserverName = () => homeserverName;
27+
28+
const mockClient: MatrixClient = MatrixClientPeg.safeGet();
29+
mockClient.isFallbackICEServerAllowed = jest.fn();
30+
31+
const dmRoomMap = new DMRoomMap(mockClient);
32+
33+
jest.spyOn(dmRoomMap, "getUserIdForRoomId");
34+
jest.spyOn(DMRoomMap, "shared").mockReturnValue(dmRoomMap);
35+
36+
fakeCall = new MatrixCall({
37+
client: mockClient,
38+
roomId,
39+
});
40+
41+
jest.spyOn(fakeCall, "state", "get").mockReturnValue(CallState.Connected);
42+
jest.spyOn(fakeCall, "isLocalOnHold").mockReturnValue(false);
43+
jest.spyOn(fakeCall, "isRemoteOnHold").mockReturnValue(false);
44+
jest.spyOn(fakeCall, "isMicrophoneMuted").mockReturnValue(false);
45+
jest.spyOn(fakeCall, "isLocalVideoMuted").mockReturnValue(true);
46+
jest.spyOn(fakeCall, "isScreensharing").mockReturnValue(false);
47+
jest.spyOn(fakeCall, "isScreensharing").mockReturnValue(false);
48+
});
49+
50+
afterEach(function () {
51+
SdkConfig.reset(); // we touch the config, so clean up
52+
jest.clearAllMocks();
53+
});
54+
55+
const mockFeatureConfig = (homeservers: string[]) => {
56+
// mock SdkConfig.get("tchap_features")
57+
const config: ConfigOptions = { tchap_features: {} };
58+
config.tchap_features[featureName] = homeservers;
59+
SdkConfig.put(config);
60+
};
61+
62+
const renderCallView = () => {
63+
return render(
64+
<LegacyCallView
65+
key="call-view"
66+
onMouseDownOnHeader={() => null}
67+
call={fakeCall}
68+
secondaryCall={fakeCall}
69+
pipMode={false}
70+
onResize={() => null}
71+
/>,
72+
);
73+
};
74+
75+
it("returns true when the the homeserver include video_call feature", () => {
76+
jest.spyOn(fakeCall, "opponentSupportsSDPStreamMetadata").mockReturnValue(true);
77+
78+
mockFeatureConfig([homeserverName]);
79+
const { container } = renderCallView();
80+
81+
// needs to hover on the component to make the control button appears
82+
fireEvent.mouseEnter(container);
83+
waitFor(() => container.getElementsByClassName("mx_LegacyCallViewButtons").length);
84+
85+
expect(container.getElementsByClassName("mx_LegacyCallViewButtons_button_vid").length).toBe(1);
86+
});
87+
88+
it("returns false when the the homeserver doesnt include video_call feature", async () => {
89+
jest.spyOn(fakeCall, "opponentSupportsSDPStreamMetadata").mockReturnValue(true);
90+
91+
mockFeatureConfig(["other.homeserver"]);
92+
const { container } = renderCallView();
93+
94+
// needs to hover on the component to make the control button appears
95+
fireEvent.mouseEnter(container);
96+
waitFor(() => container.getElementsByClassName("mx_LegacyCallViewButtons").length);
97+
98+
expect(container.getElementsByClassName("mx_LegacyCallViewButtons_button_vid").length).toBe(0);
99+
});
100+
101+
it("returns false when the call doesnt support opponentSupportsSDPStreamMetadata or hasLocalUserMediaVideoTrack", async () => {
102+
jest.spyOn(fakeCall, "opponentSupportsSDPStreamMetadata").mockReturnValue(false);
103+
jest.spyOn(fakeCall, "hasLocalUserMediaVideoTrack", "get").mockReturnValue(false);
104+
105+
mockFeatureConfig([homeserverName]);
106+
const { container } = renderCallView();
107+
108+
// needs to hover on the component to make the control button appears
109+
fireEvent.mouseEnter(container);
110+
waitFor(() => container.getElementsByClassName("mx_LegacyCallViewButtons").length);
111+
112+
expect(container.getElementsByClassName("mx_LegacyCallViewButtons_button_vid").length).toBe(0);
113+
});
114+
115+
it("returns true when the call support opponentSupportsSDPStreamMetadata", async () => {
116+
jest.spyOn(fakeCall, "opponentSupportsSDPStreamMetadata").mockReturnValue(true);
117+
jest.spyOn(fakeCall, "hasLocalUserMediaVideoTrack", "get").mockReturnValue(false);
118+
119+
mockFeatureConfig([homeserverName]);
120+
const { container } = renderCallView();
121+
122+
// needs to hover on the component to make the control button appears
123+
fireEvent.mouseEnter(container);
124+
waitFor(() => container.getElementsByClassName("mx_LegacyCallViewButtons").length);
125+
126+
expect(container.getElementsByClassName("mx_LegacyCallViewButtons_button_vid").length).toBe(1);
127+
});
128+
129+
it("returns true when the call support hasLocalUserMediaVideoTrack", async () => {
130+
jest.spyOn(fakeCall, "opponentSupportsSDPStreamMetadata").mockReturnValue(false);
131+
jest.spyOn(fakeCall, "hasLocalUserMediaVideoTrack", "get").mockReturnValue(true);
132+
133+
mockFeatureConfig([homeserverName]);
134+
const { container } = renderCallView();
135+
136+
// needs to hover on the component to make the control button appears
137+
fireEvent.mouseEnter(container);
138+
waitFor(() => container.getElementsByClassName("mx_LegacyCallViewButtons").length);
139+
140+
expect(container.getElementsByClassName("mx_LegacyCallViewButtons_button_vid").length).toBe(1);
141+
});
142+
});

0 commit comments

Comments
 (0)